Maven and working with legacy app - maven-3

In order to work with a legacy app framework I need to split a webapp project into 2. 1 jar needs to have the java class files, the other will have all the web stuff like jsps, css, et. al.. How can I do this with on maven-3 pom?

For this purpose you can use the configuration of the maven-war-plugin. This will create a separate jar file which contains the .class files...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
like xyz-1.0.0-SNAPSHOT-classes.jar which can be used as a separated dependency (you have to use the supplemental classifier).
If the war artifact should not contain any classes, you can achieve this by adding the packagingExcludes configuration.
<packagingExcludes>WEB-INF/classes/**</packagingExcludes>

Related

Wrong versions of jar when dockerize - Tomcat

I have a Java application that use Apache POI as dependency and also other jars, all managed by maven, and is deployed on a Tomcat server that has an old version of Apache POI and also its dependencies. My problem is, when I test the application locally it use the jars that are inside the application, the new version, when I run in a docker container it use the jars that are on the Tomcat server, the old version. How can I fix the application to run and use its jar internally and not externally when are on a docker container? I already used the shad maven plugin but it's hard because there are many jars that are old on the server, I can't shade everything.
I changed the plugin to generate jar from maven shade to maven assembly:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
In this way the application has everything that needs inside the jar and don't use old classes from the server. And also don't need to shade all the jars.

rpm-maven-plugin how to control the name under which rpm is stored in m2 repository?

Our organization has a convention for naming rpms. Typically, the rpm will have a shorter base name than the Maven project. There is also a convention around how releases are named. So we want a name like
${shortname}-${project.version}-${release}.noarch.rpm.
I want to build such rpms using the rpm-maven-plugin rather than older nmake technology.
And this is easily accomplished using the plugin's parameters. The rpm generated in the target directory has the desired name.
However, when mvn install installs this rpm into the maven repository, it insists on storing it the "maven way": ${project.artifactId}-${project.version}.rpm
I want the rpm stored in the standard maven repository directory using the name that is initially created on package.
How may I accomplish this?
Update:
I tried using the maven-install-plugin (install-file goal) and did not get the results I was after. But this was partly because I wasn't invoking it properly. It wasn't being invoked. If you define an install-file goal, it must be explicitly tied to the install phase. Doing so, ie, adding a <phase>install</phase> to the configuration at least invoked the execution of the install that I wanted but it still did not allow me to name the rpm as desired.
According to Karl Heinz Marbaise, a committer on the Apache Maven Project, what I am trying to do is impossible, and should not be attempted.
However, I need what I need, and have found a compromise that gives me most of that. The only thing I had to sacrifice was the assumption that the repository RPM must live in the same repository directory as the rest of the project. This is a very minor sacrifice. Once I make that, I can store the rpm, named as I want it to be, in a directory of the Maven repository, named with the short name.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
<executions>
<execution>
<id>install-rpm</id>
<goals>
<goal>install-file</goal>
</goals>
<phase>install</phase>
<configuration>
<file>${project.build.directory}/rpm/${rpm.name}/RPMS/noarch/${rpm.name}-${project.version}-${rpm.release}.noarch.rpm</file>
<groupId>${project.groupId}.rpms</groupId>
<artifactId>${rpm.name}</artifactId>
<version>${project.version}-${rpm.release}</version>
<classifier>noarch</classifier>
<packaging>rpm</packaging>
</configuration>
</execution>
</executions>
</plugin>
Using a groupId of ${project.groupId}.rpms rather than just ${project.groupId} allows all rpms built this way to live outside of the main branch of the repository, which is useful in our situation.
Using a version of ${project.version}-${rpm.release} rather than just ${project.version} allows the release to be incorporated into the name.
And the noarch classifier gets that into the name as well.

Custom phases for a multi-module maven project

I am currently working on a multi-module project with the following structure.
root
-module A
-module B
What I want to do is to execute module B (The main method of the module) after the compiling of module B (Module B depends on module A). But I need to do this with a customized command.
Ex -
mvn runb
I know that the exec maven plugin can be used to run a project using maven. What I don't understand is how to create a custom command (phase) in maven. Is there anyway to achieve this without writing a maven plugin?
I referred various guides such as https://community.jboss.org/wiki/CreatingACustomLifecycleInMaven trying to achieve this. But they need to create components.xml and lifecycle.xml files under src/resources/META-INF. I don't understand how to apply that file structure to my project since it is a multi-module project where each module has seperate src directories.
(I'm using maven 3)
You cannot create a custom lifecycle without writing a Maven plugin.
And without hacking Maven itself, at least as of Maven 3.0.5, it is not possible to add a custom phase to Maven through a plugin. The phases are loaded up by the core of Maven from its configuration before any plugins are processed.
If you really have your heart set on using one command to do what you want, writing a plugin is the only way. With some pluginGroup mappings in your settings.xml, this can be made simpler (you can specify mvn my:plugin rather than mvn com.mygroupid:plugin).
But if you are willing to have a slightly more verbose syntax on the command line, what you want could be achieved through profiles and the exec maven plugin.
Add a profile to module B that uses the exec plugin to run itself.
Something like this:
<project>
...
<profiles>
<!-- This profile uses local webapp security instead of the BlueCoat device, useful for testing -->
<profile>
<id>execb</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>runb</id>
<goals>
<goal>java</goal>
</goals>
<phase>verify</phase> <!-- Anything after package phase -->
<configuration>
<!-- Exec plugin configuration goes here -->
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
You'll need to configure the exec plugin depending on how you run your JAR, more info here.
What this does is run the exec plugin as part of module B's build, but only if the execb profile is activated.
Now, when you just want to build your project (without any exec), build like normal (e.g. mvn install).
When you want to build and run, use the command line:
mvn install -Pexecb
and it will do the exec as part of the build.

How to use Confluence markup language with Maven 3 site Plugin?

I'd like to use Confluence markup language to generate my site using the Maven site plugin.
As said in the doxia documentation, it seems to be possible.
Here is my file structure (as required by the site plugin documentation) :
src
+- site
+- confluence
+- index.confluence
But just like that, nothing is generated. By looking at the FAQ, I tried to include the "doxia-module-confluence" in the plugin build :
<build>
<plugins>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.1</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.doxia</groupId>
<artifactId>doxia-module-confluence</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
But it's still the same, my index page is not rendered (I've got the default one).
Does somebody know how to do ?
Actually, the file structure + the usage of that dependency (doxia-module-confluence) is OK.
The problem was I first generate the page without the dependency (so it didn't use my confluence file to generate the index), and then I added the dependency. But I didn't run mvn clean before the second mvn site so the index was directly used from the previously generated index.html !
generated maven sites does not match very well with Confluence style.
If you need to update Confluence pages at each deploy or release I have to suggest a small opensource plugin I have done called confluence-maven-plugin.
In this way, you can use maven site for other purposes...

Ant to Maven - multiple build targets

I have an Ant build that is currently being converted to Maven. However, the Ant build has 2 build targets - one that builds the entire app, and one that builds a JAR from some of those files (only a few). In Ant, it's easy to have multiple build targets to handle this, but I'm trying to determine the best way to handle this in Maven.
I could split the subset of files into a second project and it will have its own POM. Then the first project could depend on this one. However, since the subset of files is so small (less than 10), it seems like it might be overkill to have an entirely new project for that.
Are there other ways to handle this?
You could do this with profiles...
If you really wanted to use two separate profiles and customize the JAR plugin to include and exclude patterns of class and package names, you could easily do this by putting something like this in your POM:
<profiles>
<profile>
<id>everything</id>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<classifier>everything</classifier>
<includes>
<include>**/*</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>only-library</id>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<classifier>only-library</classifier>
<excludes>
<exclude>**/Main*</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Aside: If that seems like a lot of configuration, polyglot Maven's support for Groovy POMs is just about ready. It will cut the line count down considerably.
You would put this at the end of your pom.xml (withing the project element), and it adds two profiles. The first profile "everything" is really just there to demonstrate the configuration. This "everything" profile is unnecesary because it simply duplicates the behavior of the default JAR plugin jar goal execution. The second profile "only-library" excludes any class in any package that starts with the text "Main". To invoke these profiles:
mvn package -Peverything
mvn package -Ponly-library
I tested this against the sample application that ships with Chapter 6 of Maven by Example, and running either of these commands will produce a JAR file in ${basedir}/target that has a classifier. Since the JAR plugin's jar goal is bound to the package phase in the default maven lifecycle, these two profiles are going to modify the configuration for this plugin.
Or, you could do this with two JAR plugin executions...
If you need to create two JARs without using profiles. You can bind the JAR plugin's jar goal to the package lifecycle phase multiple times and use different configuration for each configured execution. If you configure two separate executions, each execution has an execution-specific configuration block so you can supply a unique identifier and include/exclude pattern for each execution.
Here is the build element you would use to add both custom JARs to the lifecycle phase "package". Doing this on a project with packaging "jar" would result in the jar goal being run three times. Once as the default lifecycle binding, and then twice for two custom, classified JARs.
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>only-library</id>
<goals><goal>jar</goal></goals>
<phase>package</phase>
<configuration>
<classifier>only-library</classifier>
<excludes>
<exclude>**/Main*</exclude>
</excludes>
</configuration>
</execution>
<execution>
<id>everything</id>
<goals><goal>jar</goal></goals>
<phase>package</phase>
<configuration>
<classifier>everything</classifier>
<includes>
<include>**/*</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
If you are not talking about including a different set of classes in each artifact, you'll want to use Maven Assemblies. If you want to know the details of assemblies, there is a chapter listed at the end of this answer from Maven: The Complete Reference. Frankly, i don't think that this particular chapter is a good introductory reference; in fact, I've had numerous reports that this chapter is nearly unreadable (and we're working to fix that). If you are looking to use assemblies, I'd recommend the Maven Assembly Plugin's documentation. In the left-hand nav menu you'll see a list of sample assembly descriptors.
Disclaimer: (Please) don't do this. If you are creating two difference JARs with two different set of classes I strongly recommend that you split the project up into two interdependent modules.
While you can do this with profiles, it is going to be easier for you to split the project into two (actually three). Longer term there are going to be challenges that you are going to face as your application scales. You will be responsible for figuring out this manual list of classes and packages to be included in each of your classified JARs.
There is minimal overhead to having a simple parent project that references two separate modules. If you look at the free Maven by Example book, we show how to make the transition between a single-module and a multi-module project. Chapters 3-5 focus on single module projects, and Chapter 6 shows you how you would combine these single module components into a larger multi-module project.
For more information:
You question involves the following topics, here are some links that will provide more details for each:
The Maven JAR Plugin: http://maven.apache.org/plugins/maven-jar-plugin/jar-mojo.html
Multi-module Maven Projects: Chapter 6 of Maven by Example and Section 3.6.2 of Maven: The Complete Reference.
The Maven Lifecycle (jar is bound to package if your packagin is "jar"): Section 3.5.2 of Maven by Example "Core Concepts" and Chapter 4 of Maven: The Complete Reference
Maven Assemblies: First, the Maven Assembly Plugin site, then Chapter 8 of Maven: The Complete Reference for some heavy (almost too heavy) details.
Your first thought is the correct one. Split the 2 pieces into 2 projects.
The maven philosophy is that each project should build one and only artifact (jar, war, whatever)
You could probably hack something together so that you only have one maven project building 2 atrifacts, but it would be a hack.
You can call ant from maven, so if you really want to do this, then I suggest you start looking at the maven ant plugin. The artifact id is "maven-antrun-plugin"
You've got 2 choices:
Profiles
Assemblies
If the subset is only a collection of resources, then I wouldn't make it a separate module.
If the project is always dependent on the subset which is packaged in a uniform way, then the subset is a good candidate to become a module.
If the subset is repackaged in multiple different "flavours", then I would define assemblies for each "flavour" and qualify the artifact names with a "classifier" see maven coordinates.
Finally, you could use profiles to determine which assemblies get produced, your default profile may only create the initial artifact "flavour" that is required during development.
A "full" profile may produce all "flavour" variants of the artifact for final deployment once development is complete.

Resources