How to automatically create specific files via Maven to deploy each container?
I am working on a very complex JEE project, which involves the possibility of deploying the application to each client in a different container.
In my development environment I use JBoss, but the production environment can use both JBoss and GlasFish, or even just Tomcat.
I am updating on the subject because it is around 5 years that I do not Program for JEE, in addition to the mentioned, I know that there are others that do not remember the name now.
How can I parameterize Maven to create the proprietary deployment files like jboss-web.xml
. Beyond context.xml
for Tomcat type containers?
Remembering that there are two types of application, purely WEB (client), EAR (client+agents).
1 answers
There are several ways to organize your project with maven modules to do what you need. As already in the comments, you can use filters, profiles , move specific files by profile, etc. I will use a mixture of filters and profiles in a project without any behavior, just to demonstrate this organization.
However there is something (so far I have not found any) that creates specific descriptors by container, such as jboss-web.xml
or glassfish-web.xml
. So, since there is nothing like this, we will make the changes by modifying properties and copying specific files according to the chosen profile , using only the plugin maven-resources-plugin
and the resources
of the build itself.
I will divide the answer / suggestion into two parts:
- creating the modules, including an EAR that will have both
war
; - creation of profiles and filters . O profiles will be in the parent module, not because it has to be like this, but because it is personal taste.
Then we will have the following project structure:
Below is the summary of each module, with its respective pom.xml
containing strictly what is needed at this time. I will assume the following premises:
-
jar-project
will be dependent on the two projects ofpackage
war
; -
ear-project
contains the two projects ofpackage
war
;
Parent-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>com.brunocesar</groupId>
<version>0.0.1-SNAPSHOT</version>
<artifactId>parent-project</artifactId>
<packaging>pom</packaging>
<build>
<finalName>${project.artifactId}</finalName>
</build>
<modules>
<module>jar-project</module>
<module>web-project-1</module>
<module>web-project-2</module>
</modules>
</project>
Jar-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>
<parent>
<groupId>com.brunocesar</groupId>
<artifactId>parent-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>jar-project</artifactId>
</project>
Web-project-1:
<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>
<parent>
<groupId>com.brunocesar</groupId>
<artifactId>parent-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>web-project-1</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jar-project</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
Web-project-2:
<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>
<parent>
<groupId>com.brunocesar</groupId>
<artifactId>parent-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>web-project-2</artifactId>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jar-project</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
Ear-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>
<parent>
<groupId>com.brunocesar</groupId>
<artifactId>parent-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<packaging>ear</packaging>
<artifactId>ear-project</artifactId>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>2.10</version>
<configuration>
<version>7</version>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<outputDirectory>${project.build.directory}/dist</outputDirectory>
<modules>
<webModule>
<groupId>${project.groupId}</groupId>
<artifactId>web-project-1</artifactId>
</webModule>
<webModule>
<groupId>${project.groupId}</groupId>
<artifactId>web-project-2</artifactId>
</webModule>
</modules>
<fileNameMapping>no-version</fileNameMapping>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>web-project-1</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>web-project-2</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
</dependencies>
</project>
Now let's build the profilesand filters, you can use only profiles with the properties, but I use both only as an exercise. As we are considering three containers we will have 3 profiles and assume the following:
-
jboss-web.xml
will only appear in build when profiles isjboss
; -
glassfish-web.xml
will only appear in build when profiles isglassfish
; -
context.xml
will only appear in build when profiles istomcat
; -
tomcat
is the default profile ;
As said before, the profiles are all in the pom.xml
of the Pooling Project, below are only the snippets of.
Profile jboss :
<profile>
<id>jboss</id>
<properties>
<container>jboss</container>
</properties>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/context.xml</exclude>
<exclude>**/*-web.xml</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<overwrite>true</overwrite>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/</outputDirectory>
<resources>
<resource>
<filtering>true</filtering>
<directory>${project.basedir}/src/main/resources/WEB-INF</directory>
<excludes>
<exclude>**/glassfish*</exclude>
</excludes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<modules>
<module>ear-project</module>
</modules>
</profile>
Profile glassfish :
<profile>
<id>glassfish</id>
<properties>
<container>glassfish</container>
</properties>
<build>
<!-- esta é a parte que iremos dizer para o maven em quais arquivos ele deve usar as propriedades que estão nos filters -->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/context.xml</exclude>
<exclude>**/*-web.xml</exclude>
</excludes>
</resource>
</resources>
<plugins>
<!-- usaremos este plugin para incluir os arquivos *-web.xml no lugar correto -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<overwrite>true</overwrite>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/</outputDirectory>
<resources>
<resource>
<filtering>true</filtering>
<directory>${project.basedir}/src/main/resources/WEB-INF</directory>
<excludes>
<exclude>**/jboss*</exclude>
</excludes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<modules>
<module>ear-project</module>
</modules>
</profile>
Profile tomcat :
<profile>
<id>tomcat</id>
<properties>
<container>tomcat</container>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<!-- esta é a parte que iremos dizer para o maven em quais arquivos ele deve usar as propriedades que estão nos filters -->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*-web.xml</exclude>
</excludes>
<includes>
<include>**/context.xml</include>
</includes>
</resource>
</resources>
</build>
</profile>
I haven't exemplified any project with package
of type ejb
, but you can do this (you probably won't use it, because you're considering tomcat too), i.e. you can package, for example, the package
jar
in ejb
and deploy it along with EAR
, as said at the beginning, there are N ways to organize the project.
The build part of pom.xml
should also be changed, to something like this:
<build>
<!-- a construção terá um nome específico por container (ex.: web-project-1-tomcat) -->
<finalName>${project.artifactId}-${container}</finalName>
<!-- execução padrão, por isto basta mvn para o tomcat -->
<defaultGoal>clean package</defaultGoal>
<!-- aqui é onde estão os filters com as propriedades que serão substituidas nos arquivos xml -->
<filters>
<filter>${filter.path}/src/filters/filter-${container}.properties</filter>
</filters>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
</plugin>
</plugins>
</pluginManagement>
</build>
Another thing is a property to reference our filter , so include this in the pom.xml
of the project-parant
:
<properties>
<filter.path>${project.basedir}</filter.path>
</properties>
And this in the rest pom.xml
:
<properties>
<filter.path>${project.basedir}/..</filter.path>
</properties>
This is an example of filter. They should call themselvesfilter-glassfish.properties
, filter-jboss.properties
e filter-tomcat.properties
:
webapp-1-context=app-1
webapp-2-context=app-2
For the example all have the same content, you can customize as necessary.
Another thing is that you can customize the configuration files the way you want, from using filters, to properties in profiles, by the command line, it is at your discretion.
To run you must do something like the following:
- for
tomcat
:mvn
- for
jboss
:mvn clean install -P jboss
- for
glassfish
:mvn clean install -P glassfish
One last observation is: there is nothing to go the *-web.xml
in the other constructions, for the others containers would not even understand it and this service for all other descriptors specific to each container.
Other ways to be done is by using the maven-antrun-plugin
(this is pretty cool, personally I like it more because it is less "verbose"), the maven-assembly-plugin
or even develop your own plugin , you may decide to write one for you in order to create the specific files by container.
No I know if I was able to answer your question exactly, but I hope I helped=)