how to integrate Angular 2 + Java Maven Web Application - java

I have created a Angular 2 front-end Application.and i have created one Java Rest WS Back-end Application which is connected to DB.
My Folder structure for Angular 2 App is below-
Angular2App
confg
dist
e2e
node_modules
public
src
app
favicon.ico
index.html
main.ts
system-config.ts
tsconfig.json
typings.d.ts
tmp
typings
.editorconfig
.gitignore
angular-cli.json
angular-cli-build.js
package.json
README.md
tslint.json
typings.json
And My Java Maven Web Application Structure is below-
JerseyWebApp
src
main
java
Custom Package
java classes
resources
webapp
WEB-INF
web.xml
index.html
pom.xml
I want to know how to integrate these two applications into one application which will produce only one war file.

Here is what I did:-
Install Nodejs v6.9+
Run npm install #angular/cli –g for Angular CLI
Install Apache Maven or use any Maven friendly IDE
Use your required Maven configuration, I used simple webapp (WAR).
Directory Stucture (Except for ngapp folder rest is standard Maven structure.)
ngfirst
├── pom.xml
├── src
│   └── main
│   ├── java
│   ├── resources
│   ├── webapp
│   └── ngapp
Angular Part
Open ngapp folder in terminal and type ng init command to initialize node and npm configuration, the result will be a simple Angular2 example application will the following directory structure inside ngapp folder:-
├── angular-cli.json
├── e2e
├── karma.conf.js
├── node_modules
├── package.json
├── protractor.conf.js
├── README.md
├── tslint.json
├── src
├── app
├── assets
├── environments
├── favicon.ico
├── index.html
├── main.ts
├── polyfills.ts
├── styles.css
├── test.ts
└── tsconfig.json
This structure is Angular equivalent of Maven project structure and src directory is Angular Application's source, just like maven build command generates its output in target folder, ng build command generates its output in dist folder.
In order to package the generated Angular application within Maven generated WAR modify the build configuration to change the output folder from dist to webapp, open angular-cli.json file and modify its outDir as below:-
"outDir": "../webapp/ng"
At this point ng build command will generate built Angular Application inside ng directory of ngfirst/src/main/webapp folder.
Maven Part
Open pom.xml and configure following three maven plugins:-
compiler-plugin: No Java stuff to compile in /src/main/ngapp folder, exclude it.
war-plugin: /src/main/ngapp is Angular project folder and it should not be packaged in WAR, exclude it.
exec-plugin: Execute NPM Install and Angular-CLI Build commands to generate Angular Application in webapp folder for final packaging. Note --base-href argument, it is required to load Angular resources from webapp's context path.
Here is how it should look like:-
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<excludes>
<exclude>ngapp/**</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<excludes>
<exclude>ngapp/**</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<executions>
<execution>
<id>exec-npm-install</id>
<phase>generate-sources</phase>
<configuration>
<workingDirectory>${project.basedir}/src/main/ngapp</workingDirectory>
<executable>npm</executable>
<arguments>
<argument>install</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
<execution>
<id>exec-npm-ng-build</id>
<phase>generate-sources</phase>
<configuration>
<workingDirectory>${project.basedir}/src/main/ngapp</workingDirectory>
<executable>ng</executable>
<arguments>
<argument>build</argument>
<argument>--base-href=/ngfirst/ng/</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Building Maven Project (and Angular App too)
Open Terminal in project root folder ngfirst and run mvn package command, this will generate a WAR file (ngfirst.war) in target folder.
Deploy ngfirst.war in a container, open http://localhost:8080/ngfirst/ng/index.html in Browser. (adjust your hostname and port if required)
If everything went right, you should see app works! in browser, that is Angular Application at work!!
JSP Pre-Processing
We can leverage dynamic configuration and page rendering capabilities of JSP technology with Angular application, Angular SPA is served by the Java container as regular HTML page, index.html in this case, if we configure JSP Engine to pre-process html files too, then all JSP magic can be included inside Angular SPA Page, just include the following inside web.xml
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
Save, rebuild maven project, deploy WAR and voila!!

My side I have a maven module for angular sources called prj-angular, and anoter one for war application called prj-war.
first prj angular is built:
it uses maven-exec-plugin to call npm install and ng build (thanks to #J_Dev!)
change resource default directory to dist/
skip jar MANIFEST generation
maven module result: a jar with generated angular dist/ content only!
then, second prj_war is build:
has prj angular as dependency
use unpack phase to unzip the previous jar into web app destination
this module build you app war with fresh angular dist.
Follow under the corresponding plugin configuration I used:
prj angular (pom.xml extract)
<build>
<resources>
<resource>
<directory>dist</directory>
</resource>
</resources>
<plugins>
<!-- skip compile -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase />
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>exec-npm-install</id>
<phase>generate-sources</phase>
<configuration>
<workingDirectory>${project.basedir}</workingDirectory>
<executable>npm.cmd</executable>
<arguments>
<argument>install</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
<execution>
<id>exec-npm-ng-build</id>
<phase>generate-sources</phase>
<configuration>
<workingDirectory>${project.basedir}/src</workingDirectory>
<executable>ng.cmd</executable>
<arguments>
<argument>build</argument>
<argument>--no-progress</argument>
<argument>--base-href=/app/ng/</argument> <== to update
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
<manifest>
<addClasspath>false</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
prj war (pom.xml extract)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack angular distribution</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.myapp</groupId> <== to update
<artifactId>prj-angular</artifactId> <== to update
<overWrite>true</overWrite>
<includes>**/*</includes>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/prjwar/ng</outputDirectory> <== to update
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>

Funnily enough, I did just this last week!
Using Netbeans 8.1 and a Tomcat servlet version 8.0.27
Angular and Java project file structure.
Java Project is called Foo. Angular Project is Bar
Foo (Java Maven Project)
|__ src
| |__ main
| | |__ webapp (This folder contains the entire Angular Project)
| | | |__ META-INF
| | | | \__ context.xml
| | | |__ WEB-INF
| | | | \__ web.xml
| | | |__ includes
| | | | |__ css
| | | | |__ images
| | | | \__ js
| | | |
| | | | ## Bar project files are located here ##
| | | |
| | | |__ app
| | | | \__ All .ts and compiled .js files are located here
| | | |__ node_modules
| | | | \__ any dependencies used for Bar are located here
| | | |__ typings
| | | | \__ typings for Typescript located here
| | | |
| | | |__ README.txt
| | | |__ index.jsp
| | | |__ package.json
| | | |__ systemjs.config.js
| | | |__ tsconfig.json
| | | |__ typings.json
| | | \ ## Bar project files end here
| | |
| | |__ resources
| | | |__META-INF
| | | | \__ persistence.xml
| | |__ java
| | | |__ hibernate.cfg.xml
| | | |__ com
| | | | |__ orgName
| | | | | |__ packageName
| | | | | | \__ .java files are here
|__ pom.xml
\__ nb-configuration.xml

I recommend let the two applications separated, this way you have modularity.
This way you can change the Angular App without affect your service, and vice versa. For second, your apache/nginx are faster to deliver your js and html from Angular instead Tomcat (for example). But if you still want put the Angular application inside the war, the pattern is that all web resources are in src/main/webapp.

I want to share how I set my Angular/Java projects. Some important things:
There's only a single Maven project and it allows me to build the entire project. In this way, I can build the entire project or build client and backend separately.
My project is based on Spring Boot framework. However, you can easily adapt my solution to your situation. I generate the output code of Angular project is put under the `META-INF' folder. You can obviously change it if you don't use Spring Boot.
In my project, I want to publish the angular project in the public folder.
When I develop, I run the Angular project and the backend project separately: Angular with ng serve and the backend project (the Java part) in the IDE (Eclipse).
Ok, let's start. The entire project structure is represented in the following picture.
As you can see, I put the Angular project in the 'src\main\ngapp' folder. For the Java project (the backend) I used Eclipse IDE, for the Angular project I used Webstorm. You can choose your preferred IDE to manage the project. The important thing: you will need two IDE to manage the entire project.
To build the Angular project with Maven, I used the following maven profile definition.
<profile>
<id>build-client</id>
<build>
<plugins>
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.3</version>
<configuration>
<nodeVersion>v10.13.0</nodeVersion>
<npmVersion>6.4.1</npmVersion>
<workingDirectory>src/main/ngapp/</workingDirectory>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
</execution>
<execution>
<id>npm run build-prod</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
<execution>
<id>prod</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run-script build</arguments>
</configuration>
<phase>generate-resources</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
As you can see, I used the com.github.eirslett:frontend-maven-plugin plugin to install node and run npm to build the Angular project. In this way, when I run the maven profile build-client The plugin is used to:
Check and install, if it is needed, the node version v10.13.0 in the Angular project folder src/main/ngapp/
Run the command npm run build. In the Angular project is defined the build alias in the package.json
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json",
"build": "ng build --configuration=production",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
}
The Angular client must be place in public folder of the web application. To do this, the Angular project is configured to have the baseHref=/public. Moreover, the builded project must be place in src/main/resources/META-INF/resources/public. In angular.json you will find:
"build": {
"builder": "#angular-devkit/build-angular:browser",
"options": {
"baseHref":"/public/",
"outputPath": "../resources/META-INF/resources/public",
...
In a no-Spring Boot project you probably need to put the builded angular project directly in src/main/webapp/public folder. To do this, just modify the angular.json file as you need.
You can find all the project's code in my github project. The plugin project is here.

Solution based on command line building of angular project with
npm install --verbose
npm run ng build
given
src/main/frontend
src/main/webapp
maven-war-plugin + exec-maven-plugin
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<webResources>
<resource>
<directory>src/main/frontend/dist</directory>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>npm-install</id>
<phase>generate-sources</phase>
<configuration>
<workingDirectory>src/main/frontend</workingDirectory>
<executable>npm</executable>
<arguments>
<argument>install</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
<execution>
<id>npm-ng-build</id>
<phase>generate-sources</phase>
<configuration>
<workingDirectory>src/main/frontend</workingDirectory>
<executable>npm</executable>
<arguments>
<argument>run</argument>
<argument>ng</argument>
<argument>build</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
maven-war-plugin + maven-antrun-plugin (failed to run npm directly on my machine, hence OS dependent build)
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<webResources>
<resource>
<directory>src/main/frontend/dist</directory>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>exec-gen-sources</id>
<phase>generate-sources</phase>
<configuration>
<target name="Build Frontend">
<exec executable="cmd" dir="src/main/frontend" failonerror="true">
<arg line="/c npm install --verbose" />
</exec>
<exec executable="cmd" dir="src/main/frontend" failonerror="true">
<arg line="/c npm run ng build" />
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>

<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.3</version>
<configuration>
<nodeVersion>v10.13.0</nodeVersion>
<npmVersion>6.4.1</npmVersion>
<workingDirectory>src/main/ngapp/</workingDirectory>
</configuration>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
</execution>
<execution>
<id>npm run build-prod</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
<execution>
<id>prod</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run-script build</arguments>
</configuration>
<phase>generate-resources</phase>
</execution>
</executions>
</plugin>

Related

Maven: How to extract specific files from a dependency and include them in your own project's generated jar?

I have a project that needs specific xml files contained in a dependency to be included in the root of the jar for my own project.
To better illustrate. MyProject has a dependency DependencyA.jar with the following structure:
DependencyA.jar
|
+-- folder1
| |
| +-- file11.xml
| |
| +-- file12.xml
|
+-- folder2
| |
| +-- file21.xml
|
+-- Other contents
I'm trying to generate MyProject.jar so that it has the following structure
MyProject.jar
|
+-- file11.xml
|
+-- file12.xml
|
+-- file21.xml
|
+-- Other contents
I'm not aware of any maven plugin I can use to create this structure. My idea is to hook to the process-resources phase of maven, extract the xml files from the DependencyA.jar, and copy them to ${project.build.directory}/classes so that it's packaged in the root of the MyProject.jar. Not sure if that would work or what plugin I can use to do the extraction.
I was able to get the desired behavior with the maven dependency plugin's unpack goal:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>unpack</id>
<phase>generate-sources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.example</groupId>
<artifactId>DependencyA</artifactId>
<version>1.0</version>
<includes>
folder1/*.xml,
folder2/*.xml
</includes>
<fileMappers>
<fileMapper implementation="org.codehaus.plexus.components.io.filemappers.FlattenFileMapper"/>
</fileMappers>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
The FlattenFileMapper took care of removing the folder structure and placing all the xml files in the root of my project's jar file.
One way to achieve this would be to use the Maven Assembly Plugin to create a custom assembly that includes the XML files from the DependencyA.jar in the root of your MyProject.jar. The assembly plugin allows you to specify the files you want to include in the assembly, and where they should be placed in the final JAR.
You can add the following to your MyProject's pom.xml to configure the assembly plugin:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptors>
<descriptor>src/main/assembly/xml-files.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
</build>
Then create a file called xml-files.xml in the src/main/assembly directory with the following contents:
<assembly>
<formats>
<format>jar</format>
</formats>
<fileSets>
<fileSet>
<directory>path/to/dependencyA/folder1</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
<fileSet>
<directory>path/to/dependencyA/folder2</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
This will create a custom assembly that includes the files in the folder1 and folder2 of the DependencyA.jar in the root of your MyProject.jar.
You can run the following command to create the jar with the custom assembly:
mvn clean package
The jar file will be in the target folder.

Vaadin: How to add META-INF/services to the war?

I have a Vaadin 7 maven web project that has some annotations that create service definition on META-INF/services.
I added this to the pom so the annotations are processed:
<!-- Run annotation processors on src/main/java sources -->
<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>3.3.1</version>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>generate-sources</phase>
</execution>
</executions>
</plugin>
The files show within target/classes/META-INF/services but don't make it to the final war.
I tried adding the folder to the maven-war-plugin like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<packagingIncludes>target/classes/*</packagingIncludes>
</configuration>
</plugin>
But then most of the Vaadin files don't make it into the war and it doesn't work. Any idea?
Please see https://maven.apache.org/plugins/maven-war-plugin/usage.html
It looks like your META-INF folder is in src/main/resources directory.
Normally when creating a WAR you would create a directory src/main/webapp where you can have your WEB-INF, META-INF and other required folders.
|-- src
| `-- main
| |-- java
| | `-- com
| | `-- example
| | `-- projects
| | `-- SampleAction.java
| |-- resources
| | `-- images
| `-- webapp
| |-- META-INF
| |-- WEB-INF
Everything from your webapp folder will be copied over to the root dir in the WAR.
The path to your webapp can also be configured using warSourceDirectory property
For your scenario - generated sources
Obviously you don't want to keep your generated sources in your src/* folder and don't want to version it.
You can get around this by either adding an ignore filter to your version control metadata; or by creating a symlink; or using copy-resources as some previous answers said, but not recommended.
You can achieve this by adding a webResources configuration to copy the generated sources from target folder by
Please see http://maven.apache.org/plugins/maven-war-plugin/examples/adding-filtering-webresources.html
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webResources>
<resource>
<directory>${project.build.directory}/target/generated-sources</directory>
<targetPath>META-INF</targetPath> <!-- introduced in plugin v 2.1 -->
<includes>
<include>*.class</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
I ended up using the approach from this unrelated answer: Maven: include folder in resource folder in the war build.
Here's what I ended up doing:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<webResources>
<resource>
<directory>target/classes/META-INF/services</directory>
<includes>
<include>*.*</include>
</includes>
<targetPath>META-INF/services</targetPath>
</resource>
</webResources>
</configuration>
</plugin>
Basically added the services folder as a resource and placed it on the right place of the final war.
You can try this:
<execution>
<id>process</id>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<finalName>${projectId}</finalName>
<outputDirectory>relative project directory</outputDirectory>
<includes>
<include>path</include>
</includes>
</configuration>
</execution>

Maven building for different environments

I have a Java project that currently builds nicely with Maven. But, I'm using an Ant script to do other tasks that I think Maven could also do. To simplify the build workflow, I'd like to get Maven doing everything I need. All this is automated with Jenkins.
The challenge is that I want Maven to build a single artifact and deploy it to multiple environments on-demand via command line. Currently, I do this by building with Maven, then using an Ant script that will create a copy of the WAR artifact with some files changed depending on the environment I chose. This adapts for things like JDBC connection strings, properties files, etc. that are different in each environment.
I understand Maven can use profiles, as explained in this answer. However, I'm stuck on figuring out how to make a secondary WAR file for the environment. e.g. I start with "myproject.war" created from the build step, and I want to create "myproject-dev.war", then deploy it to the dev Tomcat server. I figure I can use the antrun maven plugin to make the file changes, but I don't know how to hook it into the lifecycle. Then, I'd need to use the tomcat plugin to deploy.
Any suggestions on how this could be configured?
Let us assume you have a structure like the following (just as an example)
.
|-- pom.xml
`-- src
|-- main
| |-- java
| |-- resources
| |-- environment
| | |-- test
| | | `-- database.properties
| | |-- qa
| | | `-- database.properties
| | `-- production
| | `-- database.properties
| `-- webapp
You can define a assembly descriptor like the following:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>test</id>
<formats>
<format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<useProjectArtifact>true</useProjectArtifact>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<outputDirectory>WEB-INF</outputDirectory>
<directory>${basedir}/src/main/environment/test/</directory>
<includes>
<include>**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Furthermore you need a maven-assembly-plugin configuration like the following:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>test</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/test.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</project>
If you add a separate assembly-descriptor for each environment and add a line with the descriptor you can create with a single call the packages for each environment.
One drawback of this you have several assembly-descriptors which are aside from a few lines identical.
So going more you can use the iterator-maven-plugin to reduce the configuration and mainenance hassle like this:
<plugin>
<groupId>com.soebes.maven.plugins</groupId>
<artifactId>iterator-maven-plugin</artifactId>
<version>0.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>iterator</goal>
</goals>
<configuration>
<items>
<item>test</item>
<item>prod</item>
<item>dev</item>
</items>
<pluginExecutors>
<pluginExecutor>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
</plugin>
<goal>single</goal>
<configuration>
<descriptors>
<descriptor>src/assembly/iterator.xml</descriptor>
</descriptors>
</configuration>
</pluginExecutor>
</pluginExecutors>
</configuration>
</execution>
</executions>
</plugin>
So furthermore you need an appropriate assembly descriptor like this:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>${item}</id>
<formats>
<format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<useProjectArtifact>true</useProjectArtifact>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<outputDirectory>WEB-INF</outputDirectory>
<directory>${basedir}/src/main/environment/${item}/</directory>
<includes>
<include>**</include>
</includes>
</fileSet>
<fileSet>
<outputDirectory>WEB-INF</outputDirectory>
<directory>${project.build.directory}/environment/${item}/</directory>
<includes>
<include>**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
This makes it simple and convenient to maintain such a build. A full working example can looked at the integration tests of iterator-maven-plugin.

Copy all maven dependencies from children pom to directory

I'm trying to copy all the dependencies of a project and its sub-modules to a specific folder (lets say parent/target/lib)
the project is something like this:
parent
|- module1
|- module2
|- module3
|- module3.1
|- module3.2
|- module4
in my understanding the only way to do so is by using maven copy-dependency in each sub-module as so:
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<outputDirectory>${parent.dir}/target/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<excludeGroupIds>xerces</excludeGroupIds>
<excludeArtifactIds>junit,testng,easymock</excludeArtifactIds>
</configuration>
</execution>
I'm having multiple issues with this however:
the lib folder will contain all versions of an artifact (i want only latest)
for each include/exclude rule all the poms need to be updated (there are a lot)
Isn't there something that works together with dependency:list to get all dependencies, keep the latest and copy them to my /lib folder?
I ended up using the assembly plugin in a new sub-project as follows:
parent
|- module1
|- module2
|- module3
|- module3.1
|- module3.2
|- module4
|- assembly-module
The assembly-module calls the maven-assembly-plugin (pom.xml):
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptor>src/assembly/bin.xml</descriptor>
<finalName>module-assembly</finalName>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
finally my assembly file looks like this (assembly-module/src/assembly/bin.xml)
<id>bin</id>
<formats>
<format>dir</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<scope>runtime</scope>
<useProjectArtifact>false</useProjectArtifact>
<includes/>
<excludes>
<exclude>org.eclipse.jdt:core</exclude>
</excludes>
</dependencySet>
</dependencySets>

multiple src/main/resources folders without profiles (I wish to build multiple versions at once)

I'm working on trying to have my project automatically build two different versions of a project. What I have done is I have added two different plug-in executions as follows
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>exploded</goal>
</goals>
</execution>
</executions>
<configuration>
<resources>
<resource>
<directory>src/main/resources/first</directory>
</resource>
</resources>
<webappDirectory>${webappDirectory}</webappDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>war</goal>
</goals>
</execution>
</executions>
<configuration>
<resources>
<resource>
<directory>src/main/resources/second</directory>
</resource>
</resources>
<webappDirectory>${project.build.directory}/deployment</webappDirectory>
</configuration>
</plugin>
It builds both webappDirectories and it created the war file as expected, but the resources doesn't get included correctly (it seems to ignore the resource definitions above).
I am guessing its because I am doing this in the wrong phase, at what phase do I need to override the default resources directory?
(please notice, I do not wish to have two different profiles, I want to have both done at once)
I have wrote an blog entry exactly about that problem but the essence is about to have the maven project (in your case the war module) with the following structure:
.
|-- pom.xml
`-- src
|-- main
| |-- java
| |-- resources
| |-- environment
| | |-- test
| | | `-- database.properties
| | |-- qa
| | | `-- database.properties
| | `-- production
| | `-- database.properties
| `-- webapp
The most important thing is to create the different configuration via the maven-assembly-plugin with a configuration like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>test</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/test.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>qa</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/qa.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>production</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/production.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
what you also need are assembly descriptors like the following:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>test</id>
<formats>
<format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<useProjectArtifact>true</useProjectArtifact>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<outputDirectory>WEB-INF</outputDirectory>
<directory>${basedir}/src/main/environment/test/</directory>
<includes>
<include>**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Of course you have to name them accordingly and obviously you have to change the directory within the descriptor as well. Based on that it is now possible to create multiple artifacts (in your case war files) with different configurations during the package cycle. So you simply call your project build via:
mvn clean package
Finally i recommend not to use the src/main/resources folder, cause that folder should be used for production information which does not change for the different configuration. Furthermore the src/test/resources will be used for the test resources.

Categories

Resources