Porting a tomcat web project from eclipse ganymede to intellij 8.1 - eclipse

I have a standard (I think) web project developed with the eclipse IDE. I wish to port it to Intellij idea 8.1 - I think that, among other things, it has better taglib support.
My project structure is as follows:
Project Folder
./src [java source files etc.]
./conf [configuration files - log4j, spring beans...]
./buid [ant files]
./WebContent
./WebContent/images [image files]
./WebContent/META-INF
./WebContent/META-INF/context.xml
./WebContent/pages [.jsp+.html files]
./WebContent/scripts [.js files]
./WebContent/skins [.css files]
./WebContent/WEB-INF
./WebContent/WEB-INF/classes [.class files]
./WebContent/WEB-INF/lib [.jar files]
./WebContent/WEB-INF/tags [.tag files]
./WebContent/WEB-INF/web.xml
I can't seem to get this project configured with my local tomcat server (version: apache-tomcat-6.0.18).
I think that a good answer would be a standard, step by step, cookbook answer as to how to port (and perhaps how to correctly define a tomcat web application within intellij idea).
Thanks all!

I think the first step would be to create a stand-alone build file which will produce a WAR. Do this before attempting to import the project into InteliJ.
I would use Maven. Creating a maven POM file to create a WAR is almost trivial and you can easily override the the default locations for your src, conf, and web content to match you existing src directory. Then test the build by deploying your newly Maven created WAR to Tomcat. I wouldn't think this first task would take more than a half day (at most a full day).
IntelliJ has a built in utility to import Maven projects. Then you should be off and running....
Regardless of the IDE you finally settle on, your project will be much better off in the long run for the Maven migration.
You initial Maven POM file will look something like this...
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yourcompany.yourapp</groupId>
<artifactId>yourapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Your project name here</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
*** other dependencies here ***
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>conf</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.0</version>
<configuration>
<webResources>
<resource>
<!-- this is relative to the pom.xml directory -->
<directory>WebContent</directory>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
*** This is an example POM only... It's just meant to get you started and may not work "as is".

Start off by creating an empty web application for tomcat, within IntelliJ - and make sure that it deploys correctly
This will produce a directory structure that you should then be able to copy your source files/web assets into.
The thing that you'll probably need to handle differently is the lib files - don't store these directly in the WEB-INF directory, as keeping them in a separate 'library' area, and allowing the IDE to include them in the WAR at build time is generally a better approach, as it promotes re-use across projects.
The key thing to aim for is to not try to set your project up to completely mirror a tomcat application, as the build process will pull together the various parts for you. It all breaks down into 3 sections...
Static assets - images, config files and jsp files (Ok, I know JSP files are kinda dynamic)
Java classes - source code that you write yourself (The IDE will compile these and place them in the appropriate location)
Java Libraries - third party code that you compile against (Again the IDE will place these in the appropriate location)
There are a few bits of configuration, within the project file, that you'll need to tweak to suit your needs, but it's generally straightforward.

By default, log4j will look for it's configuration file (either log4j.xml or log4j.properties) from the classpath of your application. So this means you should place it in WEB-INF\classes, or you can specify a different location with the environment variable log4j.configuration. See the log4j manual.
What IDE you use should have no impact on the structure of your application when it gets deployed to your servlet container. It sounds like maybe you were relying on Eclipse to package the files in a specific way - this is probably a bad practice. Are you using an actual build script?

Related

Maven Exec plugin, ClassLoader ClassNotFoundException

I've tried many suggestions on StackOverflow, and tested with many combinations of setup and pom.xml for 3 days, none of them works. Please help.
I started with a big project with a lot of dependencies, spring-boot, hibernate, etc. Then I create another small console project which import and use some classes from the big project. They are not parent and child project. All I do is add <dependency/> to the child project pom, like this.
P.S. the big project has a <parent/> spring-boot-starter-parent and use spring-boot-maven-plugin.
<dependency>
<groupId>myGroup</groupId>
<artifactId>bigProject</artifactId>
<version>1.0.1</version>
</dependency>
This works on Eclipse with m2e, I just use "Run as" java application and the small project works.
But I need to upload and run those project on my linux VM, which does not use GUI and Eclipse, only terminal.
Then after some reading, I try to use maven exec plugin to run the small project. My steps:
1. do mvn clean install on the big project, confirmed that it appears in my /.m2, local repository.
2. run mvn compile on small project
3. run mvn exec:java on small project
It fails on step 2, those import ... in the class of small project throw package xxx does not exist. maven fail with compilation error.
Then, I try to simplify the problem. I create two test projects with only 1 class, myLib and HelloWorld console application, then I add myLib dependency (pom). HelloWorld project to print a message from the class in myLib package. run step 1 to 3. It works.
public class App
{
public static void main( String[] args )
{
//SystemLog from big project, does not work
//SystemLog log = new SystemLog();
//log.setValue("test value");
//System.out.println(log.getValue());
//CustomMessage from myLib, works fine
CustomMessage cm = new CustomMessage();
cm.setTheMessage("custom message");
System.out.println(cm.getTheMessage() );
System.out.println(CustomMessage.defaultMsg);
}
}
pom.xml of small project
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>dependOnOthers</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>dependOnOthers</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>myLibrary</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com</groupId>
<artifactId>bigproject</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<includePluginDependencies>true</includePluginDependencies>
<mainClass>test.dependOnOthers.App</mainClass>
<!-- <arguments> <argument>argument1</argument> </arguments> -->
<!-- <arguments> <argument>-classpath</argument> <argument>target/lib/bigproject-1.0.1.jar</argument>
</arguments> -->
</configuration>
</plugin>
</plugins>
</build>
</project>
Then I add a reference to big project, try to print a log message using HelloWorld, it pass step 2, mvn compile, but when I do step 3, mvn exec:java, java.lang.ClassLoader.loadClass() throw ClassNotFoundException on the line where I new an SystemLog() instance, the class defined in big project.
Summarize:
Goal: try to run a console application using Maven exec plugin, which has a dependency on another project, that is installed in local repo /.m2
The SystemLog class is a model class with hibernate annotations.
1. small project depend on big project, fail on mvn compile, package does not exist.
2. HelloWorld depend on myLib, works fine.
3. HelloWorld depend on big project, fail at runtime with ClassNotFoundException.
It's a little late but i ran in the same error, migrating a project from 1.5.3 to 2.1.4
I have found a solution for this problem.
Spring Boot has changed the jar structure in version 2.0.0+, so you don't need to specify your class as <mainClass>test.dependOnOthers.App</mainClass>, you need to point JarLauncher as main entry point.
When the plugin will execute the jar, java will call the main method JarLauncher and several code of spring will be called after that he reads the manifest and call the class definied in Start-Class:. in your case test.dependOnOthers.App.
<configuration>
<!-- Since version 2 of spring, the jar is packed in
another way and has his main method here, don't worry in the MANIFEST file is described which file to boot -->
<mainClass>org.springframework.boot.loader.JarLauncher</mainClass>
The old strucutre of Spring 1.0, was the classical java way todo it, so the java classloader can load it without problems and refer to the class when it is in the classpath, with the version 2.0.0+, they copy user class files and dependency into BOOT-INF, so the java classloader cannot load it anymore, you need to use the Spring classloader to get the class instance.
I have a workaround and know what is causing the problem, but don't know all the details, hope that someone will comment on this, or elaborate the answer.
The thing that cause this problem is spring-boot-maven-plugin, which I use to run spring-boot embedded tomcat server, using mvn spring-boot:run. This plugin seems to change something on the .jar file, maybe the manifest?
The workaround is to remove this plugin, run mvn clean install, that .jar installed in local repository will work correctly. run mvn compile on the small project. Then add the plugin back to big project, run mvn spring-boot:run
I do not know what the plugin changes that result in a .jar with package not exist, does it changes package name?
My workaround is clumsy, if there is a way to choose to compile with or without spring-boot-maven-plugin by defining maven goal, so that I do not need to change the pom for different build (with/without plugin). That would be a better solution.

sigar .so files on Eclipse project using Maven

I have a Maven project in Eclipse, where i added the Sigar library using
<dependency>
<groupId>org.fusesource</groupId>
<artifactId>sigar</artifactId>
<version>1.6.4</version>
</dependency>
This was compiling and executing smoothly under eclipse. When i created an executable jar i was getting an error, that the .so file doesn't exist in the java.library.path.
DEBUG Sigar - no libsigar-amd64-linux.so in java.library.path
org.hyperic.sigar.SigarException: no libsigar-amd64-linux.so in java.library.path
After some research and reading (ok, more than some) i copied the lib folder of sigar (the one that holds all the .so files) under my project (i was not sure if I have to copy it to a specific place, so i put it under the project's root) and changed the maven dependency to that:
<dependency>
<groupId>org.fusesource</groupId>
<artifactId>sigar</artifactId>
<version>1.6.4</version>
<configuration>
<workingDirectory>${project.build.directory}/Sigar_lib</workingDirectory>
<mainClass>my.package.name.MyClass</mainClass>
<includeProjectDependencies>true</includeProjectDependencies>
</configuration>
</dependency>
Tried all different approaches to the <workingDirectory> tag, with/without the build directory, forward/back slash and so on. Every time the jar fails to execute with the same error.
Any help please? Thank you
please consider using Apache Maven Shade plugin in order to build your executable jar. You can configure what kind of resources you want to have in your final Uber jar . See details here
Example
<filter>
<artifact>*:*</artifact>
<includes>
<include>xxx/*.so</include>
</includes>
</filter>
Hope that helps.

File not found Maven

I am having some problems with simple cloud storage (simplecloud). When I run with Maven the console outputs following error :
java.io.FileNotFoundException: \var\key (The system cannot find the path specified)
Source code is here : src git
However it exists in the directory as shown here :
Any ideas?
Thanks in advance
POM :
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.pliablematter</groupId>
<artifactId>simple-cloud-storage</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Simple Cloud Storage</name>
<description>A simple wrapper around the Google Cloud Storage API</description>
<dependencies>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson2</artifactId>
<version>1.15.0-rc</version>
</dependency>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-storage</artifactId>
<version>v1beta2-rev6-1.15.0-rc</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>LATEST</version>
<scope>test</scope>
</dependency>
</dependencies>
Remove the initial \. Also, as pointed out by the others, as this is obviously a test key (judging by the name), you should place it under src/test/resources/var/key and change your code to look for just var/key/test.p12.
Make sure your \var\key directory is present in the target directory that Maven creates for the build. I'll go out on a limb and guess that it's probably not there now. If you have to have that \var\key in a non-standard place, you can use the Maven Resources Plugin to copy it into the target directory. As #Adrian Shum suggests, test\resources would be a standard place for Maven to look to find it.
EDIT:
Seems like you wanted to explore this option, so here's how you might use the Maven Resources Plugin in your Maven POM...
Inside the plugins node under build, add:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
</plugin>
Then after the plugins node again inside build, add the directory or directories you need to copy over to target, for example:
<resources>
<resource><directory>src/main/resources</directory></resource>
</resources>
<testResources>
<testResource><directory>src/var/key</directory></testResource>
<testResource><directory>src/test/resources</directory></testResource>
</testResources>
I suggest you post the related code snippet in your CreateBucketTest.
I believe in your test you are opening a file \var\key. Obviously this is going to cause problem because the file you are thinking of is not really located at \var\key
Some suggestions to you:
instead of reading from absolute path, see if you can change it to opening stream for class path resources.
Put your key file under src/main/test/resources. Assume you put it under src/main/test/resources/cloudkey/key
With the above setup, when you run your test, the key file will be under the classpath at location /cloudkey/key
Edit:
After reading a bit on your code, here are some suggestions:
First, your getStorage relies on system property which is not very test friendly. Consider writing your code in a more test-friendly way
However I believe you are not going to refactor your code anyway, here is one way you can do:
put key in /src/test/resources. By doing so, when compiled, key will be put to BASE_DIR/target/test-classes/key.
Here I assume you will have only 1 key for all your tests. What you need to do is to set the system property private.key.path with the correct path of key. You can do so by configuring surefire plugin : http://maven.apache.org/surefire/maven-surefire-plugin/examples/system-properties.html. Add a systemPropertyVariables private.key.path with value ${project.build.testOutputDirectory}/key. By doing so, when your test is running, the sys property private.key.path will be set with the correct value, so that your test should run fine.

Performing substitutions in Eclipse product configuration file with tycho

I have a Eclipse RCP product which I build with Tycho. After some smaller issues, this is working pretty fine and I have both CI and releases as wanted.
The product in question is provided both as an installable stand-alone RCP application and as an update site so the functionality can be installed in a vanilla Eclipse installation. This works fine as well.
The product have a main feature - which is used on the update site - and I would very much like the feature and the product to have the same version number. As it is today, this version number is mentioned is many places and I would really like to reduce this to just one. I currently have the version number in
the feature.xml of the main feature
the pom.xml of the same feature
the .product file for the product configuration file
the pom.xml of the project with the .product file
the categories.xml file of the update site
the about.mappings file
I have tried to use maven resource filters and that works for the POM files and about.mappings, but not for the rest. This is my current pom.xml for the main feature:
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
<modelVersion>4.0.0</modelVersion>
<artifactId>...main.feature</artifactId>
<version>${product.version}-SNAPSHOT</version>
<packaging>eclipse-feature</packaging>
<parent>
<groupId>...</groupId>
<artifactId>...parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../...parent</relativePath>
</parent>
<build>
<!-- Substitutions: product.version -->
<resources>
<resource>
<directory>.</directory>
<includes>
<include>feature.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
When running this configuration, I get the following exception from Tycho (or an exception that looks very similar to it):
[ERROR] Internal error: java.lang.IllegalArgumentException -> [Help 1]
org.apache.maven.InternalErrorException: Internal error: java.lang.IllegalArgumentException
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:168)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
Caused by: java.lang.IllegalArgumentException
at org.eclipse.equinox.internal.p2.metadata.VersionParser.parse(VersionParser.java:93)
at org.eclipse.equinox.p2.metadata.Version.create(Version.java:79)
at org.eclipse.tycho.p2.impl.publisher.FeatureDependenciesAction.getVersion(FeatureDependenciesAction.java:126)
at org.eclipse.tycho.p2.impl.publisher.AbstractDependenciesAction.perform(AbstractDependenciesAction.java:79)
... 11 more
(I have cut some lines...)
Basically, the embedded maven process seems to not perform the resource filtering at all for this type of packaging. Or??
I have tried many different things, but I cannot get it to work. My best guess is that I have to configure the lifecycle, but how...
Can anybody help me with this?
this is a known bug:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=362252
You don't need to specify versions explicitly in the categories.xml. Just specify 0.0.0 as version, and Tycho will replace it by the actual version of the included feature.

Plugin JARs are missing in an application built with Tycho

I am building an Eclipse application with Maven Tycho. I managed to create the pom files for building the plugins and features. I ran install on them and got Build successful. I have also cretaed the pom for the application (product) and set the Packaging to "eclipse-application". The application is feature-based. I ran install and got the Build successful. I got the generated folder for the application, containing the folders "plugins" and "features".
The problem is that not all the jar files, for all the plugins, can be found in the plugins folder. I can find the jar files for the plugins that are listed in the features. But the jar files for the plugins listed in the Dependencies tab of other plugins are not generated. In other words, only the plugins referenced in the features are generated as jar files, while the jar files for the ones referenced in the plugins are not generated.
Obviously, I cannot run the application without them. What am I doing wrong? How can I get all the required jar files generated?
Thank you!
Firstly, don't use eclipse-application. It has been deprecated, and, being someone that has tried to make it work with his own projects, I can tell you that it's a bad idea as it has a lot of problems. Instead, use eclipse-repository.
Secondly, the only .jar files that will show up in your products plugins directory will be ones that have compiled successfully, and are also in the dependencies section of your .product file, and not your manifest.mf.
I suspect that your problem is related to the second point, but I've seen eclipse-application do so many odd things that it alone might resolve your issue.
The first answer is on the right track... Use eclipse-repository.
To have Tycho generate a repository, you are probably using the tycho-p2-repository-plugin ... And if you're using that plugin, then you may want to add this little element to the configuration section.
<includeAllDependencies>true</includeAllDependencies>
Here's a larger sample of my pom.xml that's in my p2repository plugin.
<?xml version="1.0" encoding="UTF-8"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>my.domain.product</groupId>
<artifactId>parent</artifactId>
<version>1.1.8-SNAPSHOT</version>
<relativePath>../my.domain.product.parent</relativePath>
</parent>
<artifactId>my.domain.product.p2repository</artifactId>
<packaging>eclipse-repository</packaging>
<name>My Product - P2 Repository</name>
<build>
<plugins>
<plugin>
<groupId>${tycho-groupid}</groupId>
<artifactId>tycho-p2-repository-plugin</artifactId>
<version>${tycho-version}</version>
<configuration>
<includeAllDependencies>true</includeAllDependencies>
<createArtifactRepository>true</createArtifactRepository>
<compress>true</compress>
</configuration>
</plugin>
</plugins>
Hope this helps.