Maven for static web project - java

I'm trying to add a wst.web facet for a multimodule maven project on eclipse. This wst.web facet is "Static web project"
You would say "why is he using maven for this?"
The point is that the whole project is a tree. I have a parent pom in the root of the project, and it has some modules, and they have their modules too. 3 levels most, for config centralising purposes and plugins and dependencies heritage.
So, one of these modules, contains 2 Static web projects, that are the UI part of other modules that are dynamic. These 2 are meant to be published in an Apache (in a Http Server within eclipse). All this already works with assembly plugin that moves stuff to target and then packs it in a tar.gz... but without the "Static web project" Eclipse does not allow me to publish it to the Http Server. I can do it by hand but that's not the point
My current config to do this is:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectFacets>
<wst.web>1.0</wst.web>
<wst.jsdt.web>1.0</wst.jsdt.web>
</additionalProjectFacets>
</configuration>
</plugin>
This is adding JavaScript 1.0 facet. But not the Static Web Project that I need
Thanks a lot for all your help.
PS: As an another reason to use maven for this, is that this tar.gz produced, is packed in a deb package, that configures the virtual host for apache, with all the AJP proxy needed to work with its backend.

Related

Why is Maven including multiple versions of the same dependency?

I have a Maven java web app (.WAR) project that includes several libraries, including the Wicket libraries (but I don't think the problem is wicket itself, but rather with maven).
Here's the problem: even tho I only include Wicket 6.20.0, the resulting .WAR contains two copies of the Wicket libraries: 6.20.0 and 6.18.0, as you can see in this screenshot:
Thinking of some conflicting imports I printed the dependency tree using the:
mvn dependency:tree
commnad... but there is no mention of Wicket 6.18.0 in the dependency tree! I also double-checked using Eclipse's "dependency hierarchy" view and I can confirm there's no trace of that import.
I even did a search for string "6.18.0" across the entire workspace with Eclipse, but it's nowhere to be found!
How can I find out what is causing the inclusion of that duplicate version of the library?
Maven doesn't work in this way.
The resolution of more than one dependency with the same artifactId and groupId but with a different version will result to a single dependency (the version used is no determinist).
The presence of two artifacts with the same artifactId and groupId but with two distinct versions in a same lib folder of the WAR is probably related to one of these :
you don't execute mvn clean package but only mvn package.
your use a bugged version of the Maven war plugin. Try to update it to check that.
you have a Maven plugin that copies Wicket jars 6.18.0 in the WEB-INF/lib folder of the target folder during the build of the component.
the maven WAR project you are building has as dependency an artifact of type WAR. In this case, the dependencies of the WAR dependency are so overlaid in the WAR project that you are building.
An interesting Maven issue about duplicated JAR because of WAR dependencies :
JARs with different versions can be in WEB-INF/lib with war as dependencies
Your answer and your comment indicate that actually you have a WAR dependency in your build.
Unfortunately, there is not really a good and long term effective solution to bypass this limitation.
As said in my comment, using the packagingExcludes property of the maven war plugin is a valid workaround for the actual issue :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<!-- ... -->
<packagingExcludes>WEB-INF/lib/wicket-*-6.18.0.jar</packagingExcludes>
</configuration>
</plugin>
But beware, using that will do your build less robust through the time.
The day where you update the version of the WAR dependency and that in its new version, it pulls again a different version of wicket, you have still a risk to have duplicate jars with two distinct versions in your built WAR.
Using the overlay feature by specifying the overlay element of the maven-war-plugin is generally better as it focuses on the overlay applied for the war dependency. It fixes the problem early.
As a result, you could define to exclude any wicket JARs from the WAR dependency :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<version>2.4</version>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<overlays>
<overlay>
<groupId>com.whatever.youlike</groupId>
<artifactId>myArtifact</artifactId>
<excludes>
<exclude>WEB-INF/lib/wicket-*.jar</exclude>
</excludes>
</overlay>
</overlays>
</configuration>
</plugin>
This way is better but this is still a workaround.
The day where the dependency WAR is updated and that it pulls new dependencies (other than Wicket) that are declared in your actual build but with different versions, you may finish with the same kind of issue.
I think that declaring a dependency on a WAR artifact should be done only as we don't have choice.
As poms and projects refactoring are possible, introducing a common JAR dependency which the two WARs depend on and that contains only common sources and resources for the two WARs makes really things simpler.
Well, I figured it out while poking around.
I had a dependency of type "war" in the project:
<dependency>
<groupId>com.whatever.youlike</groupId>
<artifactId>myArtifact</artifactId>
<version>1.0.7-SNAPSHOT</version>
<type>war</type>
</dependency>
Apparently (I wasn't aware of this, my fault here) these type of dependencies will include themselves in the classpath by copying all libs to the main WAR /libs folder, but these will NOT show app in the dependency tree / dependency hierarchy.
I solved by configuring an explicit exclusion in the WAR plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<!-- ... -->
<packagingExcludes>WEB-INF/lib/wicket-*-6.18.0.jar</packagingExcludes>
</configuration>
</plugin>
Use clean install and the double dependency will probably be gone.
Because other libs can use same libs but different version or you tried different version and didn't make mvn clean
The command mvn dependency:tree is telling you the correct information - what you are looking at here is an eclipse / build issue.
Clear out all the target and build areas in your project. If need be, check it out from source control to a new folder.
Alternatively you can build your project in IntelliJ IDEA, and see if you get the correct dependencies (most likely you will).

Netbeans Maven-based Module is not providing its dependencies

I want to accomplish what I think these directions describe.
I want to use an external, maven-based project from a rcp platform application.
I've used the new Project wizard to build a new maven-based application that include a maven-based module. I've added my external dependencies to the maven-based module.
I've also added the publicPackages section to my module's pom.
When I right-click on the module and go to ProjectProperties->PublicPackages I can see the correct packages listed with check marks.
My maven module builds just fine.
However, when I try to add the maven-module as a dependency of another module the packages listed in PublicPackages are not found.
If I peek inside the nbm I can see the jars I wanted exposed are under netbeans\modules\ext
Is there some way to build a maven-module that wraps another maven project?
The nbm-maven-plugin docs include an example which sounds alot like what I want to do:
Public packages declaration
By default all your module's packages (and classes) and private to the given module. If you want to expose any API to other modules, you will need to declare those public packages in your pom.xml. This includes not only your own classes but also any other 3rd party library classes that are packaged with your module and are to be exposed for reuse by other modules.
For example:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>nbm-maven-plugin</artifactId>
<version>3.8.1</version>
<extensions>true</extensions>
<configuration>
<publicPackages>
<publicPackage>org.foo.api</publicPackage>
<publicPackage>org.apache.commons.*</publicPackage>
</publicPackages>
</configuration>
</plugin>
there is a package org.foo.api made public (but not org.foo.api.impl package) and any package starting with org.apache.commons, so both org.apache.commons.io and org.apache.commons.exec packages are exposed to the outside
I am clearly not interpreting those doc correctly because this behavior is not what I'm seeing.

How to configure custom maven project structure

I know that typically maven structure is like this:
pom.xml
src
- main
- web
- WEB-INF
However, I have a project which has the following structure
src
- main
web
- WEB-INF
The latter of the two above currently does not use maven. I've started using maven for this project locally by making the structure conform to the maven standard. However, I now want to automatically build this project from jenkins by getting it out of the source control (svn). So I would like to just add a pom.xml which is aware of the fact that web isn't inside src
Is this possible to do with maven?
You can configure the maven-war-plugin to use another warSourceDirectory but as Jeff Storey explains in his answer it is really not recommended.
This is how you would do it:
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<warSourceDirectory>web</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
One of several problems is for example that the maven-jetty-plugin will not run out-of-the-box. It will by default look in src/main/webapp so that has to be configured.
You might not use the maven-jetty-plugin but you get the idea.
Using the maven war plugin properties, you can set the warSourceDirectory property http://maven.apache.org/plugins/maven-war-plugin/war-mojo.html (I'm not sure exactly what problems you're having, so this may or may not solve your specific problem).
However, maven is very opinionated and I would strongly recommend using the expected maven structure. Other plugins may give you unexpected problems down the road, and maven life is generally a lot easier when you follow their conventions.

GWT hosted mode in multiproject maven setup

I have a multimodule maven setup for my project, made of 5 modules, which includes a GWT webapp.
It is also an eclipse multiproject workspace, so I created an additional project, only containing a pom, which lists the other projects (sibling on the file system) as children modules.
I'm also a new maven user, so I might be doing something wrong. =)
The gwt module uses the following plugin
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>2.4.0</version>
<executions>
<execution>
<goals>
<goal>generateAsync</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<hostedWebapp>war</hostedWebapp>
<runTarget>GWT.html</runTarget>
</configuration>
</plugin>
When I run mvn package on the pom project I get the expected behaviour: projects are build in the correct order, and the war is fine.
When I run mvn gwt:run, though, maven tries to find a gwt app on each module, failing on the first one (the parent) which doesn't even declare nor manage the gwt plugin.
If I run mvn -fn gwt:run, the build fails on each other project, finally finding a gwt app on the gwt module, and displaying it.
How do I correctly run the app on hosted mode? Is this the correct behavior?
I do not want the GWT module to be the parent module (if it's possible), because the project has multiple target platforms, producing the gwt web frontend, a Java executable jar backend and in the future also an Android app, and shares most parts of the code (not only the model). Is a single pom structure recommended for such a setup, or am I failing at maven?
Are profiles what I need? If I do, should I declare the same profile id on each module? How would I prevent the trigger of gwt:run command on them anyway?
What should the setup of such a project be? Is this the correct setup?
Additional information
Modules are
pom: declares modules model, logic, analyze, gwt, tests
model: no dependencies
logic: no dependencies
analyze: depends on model, logic
gwt: depends on model, logic
tests: depends on model, logic, analyze, gwt (contains global tests,
not unit tests)
If I run gwt:run on the gwt module i get the error
Could not resolve dependencies for project
djjeck.gwt:djjeck.gwt:war:0.0.1-SNAPSHOT:
Could not find artifact djjeck.model:djjeck.model:jar:0.0.1-SNAPSHOT
This is from djjeck.gwt/pom.xml
<dependency>
<groupId>djjeck.model</groupId>
<artifactId>djjeck.model</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
A com.model-0.0.1-SNAPSHOT.jar is inside the war lib folder, both packed and unpacked, and also inside djjeck.model/target.
Go to the webapp module and then run mvn gwt:run.
You may use profiles to speed up compilation time: one profile could only gwt compile for gecko and english +draftCompile for example.
Have a look at maven GWT plugin multi-module setup if you're still having problems.
As I was also struggling with GWT dev mode and a Maven project with multiple sub-modules/projects, I created an example and uploaded it to GitHub. You can find it at:
https://github.com/steinsag/gwt-maven-example
The readme on aboves page shows how to run it via Maven. Features of this example are:
multiple modules
not using GWT's embedded Jetty, but an own Tomcat7 server
startup of Tomcat7 and GWT hosted mode possible via documented Maven commands
I hope this helps a bit to have at least a working example to start from.

Eclipse + Maven + Tomcat: testing web apps when the WAR is built with custom options

I am using Eclipse (Helios), with the "m2eclipse" plugin. I am working on a Maven-based web application project, which I test on a local Tomcat server that is setup inside Eclipse.
Generally, this works more or less great. "m2eclipse" can sometimes be flaky... but for the most part it keeps my POM and my Eclipse project settings in sync, and likewise keeps the deployed code current in Tomcat.
However, recently I've added a wrinkle. I have one JavaScript include file that needs to be different when going from the test environment to the real production environment. The differences are too significant to be cleanly handled by Maven filtering and token substitution. What I needed was to keep two separate files in my project, and only deploy the one appropriate for the build profile.
I accomplished this with some "targetPath" trickery in my Maven POM:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<webResources>
<resource>
<!-- take the stuff from a "prod" or "non-prod" subdirectory and copy it one level up -->
<directory>src/main/webapp/js/${profile.name}</directory>
<targetPath>js</targetPath>
</resource>
<resource>
<!-- now don't deploy those profile-specific subdirectories -->
<directory>src/main/webapp/js</directory>
<excludes>
<exclude>prod</exclude>
<exclude>non-prod</exclude>
</excludes>
</resource>
</webResources>
</configuration>
</plugin>
This builds a perfect WAR file, which works fine when I deploy it some external Tomcat server. However, the problem is that Eclipse does NOT use that WAR file when running Tomcat inside of Eclipse. Instead, Eclipse works with an exploded version of the application, deployed to a cryptic directory like this:
<workspace>/.metadata/.plugins/org.eclipse.wst.server.core/tmp1/wtpwebapps/MyApp
... and apparently the app's files are copied to this location PRIOR TO Maven doing the little trickery shown above. Therefore, when testing locally inside of Eclipse, no JavaScript include is present at all in the expected location.
Is there a way around this problem? Maybe an Eclipse change, or a Maven change, to pull the file from Maven's "target" directory to Eclipse's "wtpwebapps" directory? Maybe there's another approach to solving the profile-specific-include-file issue altogether?
Starting from eclipse (Helios) 3.6 , the option “Java EE Module Dependencies” is replaced by “Deployment Assembly” option . You can configure which files to be deployed to the tomcat running inside of Eclipse in this “Deployment Assembly” option (Project Properties ---> Deployment Assembly )
You could deploy to the local server using the maven-cargo-plugin instead of running from Eclipse directly. This would then use your maven generated war.
If the tests you are doing can be automated, this could then be incorporated as part of an integration test suite that would be completely run by maven.

Categories