Hybrid JDK 1.7 Server 1.6 Client Maven Build of Artifacts - maven

I have a Maven project with both server back-end modules and client front-end modules. The goal is to take advantage of performance improvements in JDK 7 for the server back-end modules but build the client modules in JDK 6 only. The client modules run in Tomcat while the server modules are separate Java applications.
I am aware of the Maven configuration to target specific JDK:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerVersion>1.6</compilerVersion>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
One caveat to this approach is that there are common modules that are used by both the server modules and client modules necessitating two different binaries (JDK 6 and 7) for each module.
How can one compile one set of artifacts for a JDK 6, and another set of artifacts for JDK 7, and a third set of artifacts (used by both) for both JDK 6 and 7 all belonging to the same project? Would it be necessary to divide the modules up into three separate projects?

If you <target> 1.6, the resulting Jar will work perfectly fine in 1.6 and 1.7. No need to compile twice.
There is no perfo benefit (except perhaps in some very obscure cases) from using the 1.7 compiler or targetting 1.7 byte code. All the perfo lives in the JVM. Just make your common code be target 1.6. Unless you yourself can measure a speed advantage of compiling for 1.7, don't bother.

The answer of bmargulies is very pertinent.
Anyway, if you really want to build different versions of some module (1.6 and 1.7) I suggest you to use 2 profiles, profile1 targeting jdk6, profile2 targeting jdk7. So both profiles will redefine the maven-compiler-plugin.
Both profiles can also redefine the maven-jar-plugin with a different classifier so that each module will be available in 2 versions (and use the classifier in your dependencies so that client use jdk6 and server use jdk7).
Here is another question with more details about the way you can do this: How to manage artifactory / maven artifact using different profiles

Related

Java 11 Eclipse finds automatic module, Maven does not

I'm attempting to upgrade a 15 year old Maven multimodule project to Java 11, and the module system that was introduced in Java 9. Since the project is built using Maven, all dependencies are pretty clear. First I want to do this using the automatic module names, in order not to also introduce upgraded artifacts (if not absolutely required).
Eclipse is pretty helpful in this process, autocompleting the automatic module names in the module-info.java. For example:
requires dom4j;
But if I compile with Maven, I get errors about that it cannot find the modules Eclipse just autocompleted in there.
module-info.java:[29,18] module not found: dom4j
I am using Maven's compiler plugin 3.7.0 (3.8.0 gives a NullPointerException as per https://jira.apache.org/jira/browse/MCOMPILER-355) I suspect Maven is setting the jars up on the classpath instead of on the modulepath, but the compiler's plugin debug output does not log that.
How can I make Maven correctly handle those modules?
I was running into the same issue. Adding
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
</plugins>
</build>
to my pom solved the problem for me...
Maven version 3.9.0 seems to be buggy and will not find the module although the dependency is using an Automatic-Module-Name. Downgrading to version 3.8.1 helps.

I want maven to use JRE system Library [JavaSE 1.8] always while creating new maven quickstart project

I have jdk/jre 1.8 installed on my windows system. In Eclipse whenever I create a quick-start maven project, the project gets created with JRE System Library[J2SE 1.5]. I am fed up of this problem tried to change the execution environment by doing right click on above JRE library-properties and changing the execution environment to 1.8 but again if I update this maven project, the JRE system library goes back again to J2SE 1.5, I also tried changing the compiler compliance to 1.8 which was earlier set to java 10 and also did adding the source and target tag with version 1.8 inside plugin tag of pom.xml but this was also a temporary solution. As when I create a new maven project it sets the default JRE system Library[J2SE 1.5]. Please Provide me with a permanent fix where whenever i create a new maven project, it should be created with JRE System Library[JavaSE 1.8].
Add the following to pom.xml to configure which JDK version you would want to use:
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
or the followings:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
It is because when you do Maven --> Update Project in Eclipse , Eclipse 's maven plugin will use what you define in pom.xml to update the setting of the eclipse project. If you don't specify above settings , the default is to use JDK 1.5 (before maven-compiler-plugin version 3.8.0) or JDK 1.6 (3.8.0+)
Basically I want maven to use JDK 1.8 by default. So that i wont need
to change pom.xml contents again and again while making a new project
If you do not want to change any settings related JDK version in pom.xml after creating a project , you may consider to create your own archetype to fully customize what pom.xml looks like after creating an project. Or a more simple way is to search some Java8 archetype created by others and simply use it such as this.
Refer this for how to create a Maven project with an specific archetype using Eclipse. You may probably need to click "Add Archetype" to configure the require information when you use that archetype for the first time. For example , for this archetype, you have to configure the following for the 1st time:
archetypeGroupId=pl.org.miki
archetypeArtifactId=java8-quickstart-archetype
archetypeVersion=1.0.0

Confusion on maven compiler plugin

I am quite confused about maven compiler plugin and what it does. I have a project that has several modules. In my top pom.xml I have a section
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
My understanding is this specifies the JDK compiler version used to compile the code, and this section get inherited by all the modules. What I don't get is in my IntelliJ IDEA I can still specify project JDK in the settings and it seems like that setting overrides this. When I run maven install in the IDE I can confirm that it is using javac from JDK 8 to compile. So what does this section do exactly?
You are correct; maven-compiler settings should be inherited by child modules.
I don't know about IntelliJ, but I can tell you that Eclipse picks&chooses whatever it wants from maven config, and for all the rest it uses its own settings.
Therefore, I'd expect IntelliJ may do something similar?
The simplest way to test this is to run a mvn clean install via command line, and see which "wins". If you get artifact compiled with 1.8 then it means you're missing something in Maven config which causes those settings not to propagate to children. If you get artifact compiled with 1.7 then it is IntelliJ who does it and not maven-compiler-plugin.

Rollback on Continuous Deployment with Hudson and Maven

In continuous deployment world, rollback is a tough topic.
I need to rollback to my latest version.
I use Hudson and Maven, and I want to deploy to a Java EE application server like JBOSS.
Eg.
<build>
[...]
<plugins>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.6.Final</version>
</plugin>
</plugins>
</build>
Any idea?
It depends from the technology and from the CD tool used.
For instance, Weblogic has the option to mark the replaced package as "retitred" and to reactivate it.
mvn com.oracle.weblogic:weblogic-maven-plugin:redeploy
-Dadminurl=t3://myhost:7001 -Duser=weblogic -Dpassword=mypassword
-Dtargets=AdminServer -Dname=sample.war
but the version (in the Manifest) must be different.
Generaly speaking when you build an application you will assign a version number, then you can restore the latest version storing the history of your versions.
In your case (Hudson-CI with Maven) you may use a DB (MySQL of MantisBG in my case) to store the version of the packages just released, then you are able to rollback easily.
A little explaination can be found here Maven Build Cuistomization.
Sometime, we do not deploy only one application but several packages with a "Parent Version":
MyProject Release 1.0.1
MyApp.ear 1.3
MyBatch.jar 2.0
then you need a more complex CD system; in my case I use the hierarchy proposed by my Bug Tracker (MantisBT), but there are a lot of tools more professional see also Continuous Delivery Scenario - implementing Rollback

jdk version for compiling java code: jenkins vs pom.xml

We are using jdk 6 to compile our code (specified in jenkins), I am trying to specify jdk 7 to compile the projects from now on. I noticed some of the projects have specified jdk 6 in their pom.xml. I am not sure which one takes precedence when jenkins specifies jdk 7 but pom.xml speicifies jdk 6. Any idea which one takes the final precedence to compile the code?
In JDK you can specify the generated class files that target a specified version of the VM. For example if JDK 1.7 is used you can specify the target class file version as 1.7 or lower version.
In maven compiler plugin you can specify the source and target version as follows.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${sourceVersion}</source>
<target>${targetVersion}</target>
</configuration>
</plugin>
</plugins>
</build>
In your case if you want the class to be compiled to java 1.7 then you have to specify ${sourceVersion} to 1.7 and the ${targetVersion} to 1.7
I am not sure which one takes precedence when jenkins specifies jdk 7 but pom.xml speicifies jdk 1.6
If JDK 7 is used in Jenkins and the target version in the pom is 1.6 then the classes will be compiled to jdk 1.6 version.
Check the following links for more information.
http://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html
http://docs.oracle.com/javase/7/docs/technotes/tools/windows/javac.html#options

Resources