How to automatically create specific files via Maven to deploy from each container?

Asked

Viewed 1,128 times

3

I am working on a rather 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 myself on the subject because it has been around 5 years that I do not program for JEE, beyond cited, I know there are others who do not remember the name now.

How can I parameterize the Maven to create proprietary Deployment files such as jboss-web.xml. Beyond the context.xml for Tomcat type containers?

Recalling that there are two types of application, purely WEB (Client), EAR (Client+Agents).

  • Exactly, where does the spring boot come in this story? As for packaging specific to each container, there are some forms with Maven, as using Filters, profiles, move specific files by profile, etc. Soon I include an answer for you.

  • @Brunocésar, the Spring Boot, is an option, there may be smaller customers, who will run the application in only a single station, unfortunately there are customers who do not want the application running completely remote because they fear that their data will be used without authorization, I will soon be opening this application for further discussion on client development options, as soon as the core is working and approved (if approved) :D (will be Open Source, but not Free)

  • In this case is already another context, spring boot is a guy Coc to avoid Boiler Plate and put the application to run as soon as possible, so it is another project that can use common objects, nothing prevents. Say that "the production environment can use both Jboss and Glassfish or even Spring-Boot" is quite erroneous, since the boot is not container. It got a bit confused your question, even more after you quoted spring, run a container spring in a jee container full profile is not trivial.

  • Then I remove the Spring Boot, we only have Jboss and Glasfish to simplify the answer.

  • Delfino, completed the response to a functional example with multiple types of profiles and generating specific packages by container. See if this helps you.

  • @Brunocésar, I’m leaving, but I’ll be back today, then take a look. For now thank you.

  • I received a negative vote and I would like to know why to improve the question.

  • To record my research on the subject, since I have not yet reached the ideal model, and have not had a number of answers to determine the best, follow the link: https://developer.jboss.org/wiki/HowToConfigureJavaEApplicationToApplyDifferentSettingsinWebxmlEtcForVariousEnvironsByMaven

  • Basically the same approach as the answer, no?

Show 4 more comments

1 answer

1

There are several ways to organize the project with Maven modules in order 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 mixed Filters and profiles in a project without any behavior, just to demonstrate this organization.

However, there is something (so far I haven’t found any) that creates container-specific Scriptor, such as jboss-web.xml or the 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 profile chosen, using only the plugin maven-resources-plugin and the resources of the build itself.

I will divide the answer/suggestion into two parts:

  1. creation of the modules, including an EAR that will have both war;
  2. creation of profiles and Filters. Profiles will be in the module Parent, not because it has to be so, but because it is personal taste.

Then we will have the following design structure:

Estrutura do Projeto

Below is the summary of each module, with its respective pom.xml containing strictly what is necessary at this time. I will assume the following premises:

  • jar-project will be dependent on the two projects of package war;
  • ear-project contains the two projects of package 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 go to the construction of profiles and Filters, you can use only profiles with the properties, but I use both only as exercise. As we are considering three containers we will have 3 profiles and I assume the following:

  • jboss-web.xml shall be included only in the build when the profiles for jboss;
  • glassfish-web.xml shall be included only in the build when the profiles for glassfish;
  • context.xml shall be included only in the build when the profiles for tomcat;
  • tomcat is the profile pattern;

As said before, the profiles are all on pom.xml of the grouper project, below are just the stretches of them.

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 didn’t exemplify any project with package of the kind ejb, but you can do this (you probably won’t use, because you’re considering Tomcat as well), ie you can package, for example, the package jar in the ejb and make the deploy of it along with the EAR, as said at the beginning, there are N ways to organize the project.

The part of build 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, then include this in the pom.xml of 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 be called filter-glassfish.properties, filter-jboss.properties and filter-tomcat.properties:

webapp-1-context=app-1
webapp-2-context=app-2

For example everyone has the same content, you can customize as needed.

Another thing is that you can customize the configuration files the way you want, from using Filters, up to properties in profiles, by command line, is at your discretion.

To perform 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 *-web.xml in other constructions, by the other containers would not understand it even and this service for all others Descriptors specific to each container.

Other ways to be made 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, may decide to write one for you in order to create the specific files by container.

I don’t know if I could answer your question exactly, but I hope I helped =)

  • I’ll take a closer look at your response in the morning. But so far I have to reformulate my question, because I have not informed the fact that I will have to use an IDE like Eclipse. And there’s no way I can create a sub-project for each container.

  • 1

    @Delfino nowhere says you need to create "sub-project" per container, are Maven profiles for each container. In addition, tools like Maven are agnostic about environments like IDE. The solution demonstrates (and suggests other means) for specific container constructions, which is something else.

  • so I said that I will analyze more calmly, now the evening will not be able to give an adequate feedback the answer, but for now will my vote for the effort as thanks.

  • Bruno, I’m not feeling very comfortable with the proposal presented, this week that enters I will study alternatives using plugins, if someone wants to help me with a proposal. But I think my need may be at this link: https://maven.apache.org/components/plugins/maven-assembly-plugin/

  • 1

    @Delfino yes, another alternative is using this plugin, including referenced in the reply, it also uses the excludes and includes to just go the specific artifacts and you can have several Descriptors also, or even a combination of them with the maven-antrun-plugin. Anyway, there are several ways to do it :)

  • Thanks Bruno, I see it will be a good journey.

  • @Delfino ok, anything let me know that I update the response with an example.

  • Bruno I think the answer ended up getting long due to the examples what scared me, and I didn’t read everything, since at the point I interrupted the reading was not following what I expected to be possible with Maven.

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.