Tag Archives: maven

Obtaining Maven Version Programatically On Runtime

This is my favorite way of reading Maven project version from runtime.

First on your pom, declare that all files on src/main/resources will be filtered — meaning any placeholder (eg: ${project.version}) will be substituted by Maven.


  ...
  
    
      src/main/resources
      true
    
  

Then create a properties file (eg: myapp.properties) with key-value pair containing the Maven project version

myapp.version=${project.version}

Ensure the file above is configured on your Spring container either using xml:


Or Java annotation:


("classpath:/myapp.properties")
public class TheConfig {
  ...
}

The key-value entry can then be injected on any Java beans living in the container:


public class MyClass {
  ("${myapp.version}") private String version;
  ...
}

Or even spring xml config:


  

Beware that if you have more than 1 Spring container (eg: root and servlet), you need to declare on both, otherwise the injection will fail.

Creating Self Executing Tomcat Jar

The tomcat maven plugin comes with handy exec-war-only goal that will bundle a standalone tomcat server in an executable jar. Add following configuration to your pom file:


  org.apache.tomcat.maven
  tomcat7-maven-plugin
  2.0
  
    
      tomcat-run
      
        exec-war-only
      
      package
      
        /
      
    
  

And when you run the package goal, another artifact called myapp-x.y-war-exec.jar will be created. To run this simply execute java -jar myapp-x.y-war-exec.jar on a terminal shell.

The jar also comes with several options of which you can view by giving –help flag. The -httpPort is often useful to setup few testing environments:

C:\myapp>java -jar myapp-1.0-war-exec.jar --help
usage: java -jar [path to your exec war jar]
 -ajpPort                      ajp port to use
 -clientAuth                            enable client authentication for
                                        https
 -D                                key=value
 -extractDirectory    path to extract war content,
                                        default value: .extract
 -h,--help                              help
 -httpPort                    http port to use
 -httpProtocol            http protocol to use: HTTP/1.1 or
                                        org.apache.coyote.http11.Http11Nio
                                        Protocol
 -httpsPort                  https port to use
 -keyAlias                    alias from keystore for ssl
 -loggerName                logger to use: slf4j to use slf4j
                                        bridge on top of jul
 -obfuscate                   obfuscate the password and exit
 -resetExtract                          clean previous extract directory
 -serverXmlPath          server.xml to use, optional
 -uriEncoding              connector uriEncoding default
                                        ISO-8859-1
 -X,--debug                             debug

Spring xercesImpl SAXParseException Problem

Found a really tricky and obscure problem. Whenever running my Spring MVC project it fail at startup with this exception:

org.xml.sax.SAXParseException: cos-all-limited.1.2: An ''all'' model group must appear in a particle with '{'min occurs'}'='{'max occurs'}'=1, and that particle must be part of a pair which constitutes the '{'content type'}' of a complex type definition.

Thanks to this Graham Hacking’s blog article, I figured out this was because commons-dbcp pulling and older version of xercesImpl.

The solution was to add newer version of xercesImpl on pom:


  xerces
  xercesImpl
  2.11.0

Debugging Maven Unit Test

I don’t trust debugging Maven unit tests straight using Eclipse’s JUnit plugin, sometime it’s buggy and the classpath don’t match with Maven.

Here’s how you can attach eclipse debugger straight from Maven process. First setup few breakpoints of the suspicious code as per normal, and setup a Maven run configuration like this:

maven-debug-runconfig

When you run this configuration, Maven will halt right before unit tests are run:

maven-debug-console

Now create a Remote Java Application Debug configuration pointing to localhost port 5050

maven-debug-debugconfig

Happy debugging!

Using File Protocol to Deploy Maven Project To Windows Shared Folder

Our development team is fairly small and we’re not at the point where we need Nexus yet, so I decided we can try using a simple Windows server share as our internal Maven repository.

On each of our shared Maven project pom.xml we add following distributionManagement configuration:


  
    enfinium
    Enfinium Internal Repository
    file://mavenrepo/maven_repository
  

Where //mavenrepo/maven_repository is the Windows server share we’ve setup. We’ve made sure each team member has correct read/write permission.

However every time we deploy Maven would say everything is successful but the file is nowhere to be found on the remote repository. (We’re using Maven 3.1.0

Turns out with file protocol and Windows server share, this is the syntax that works for us (yes Maven just fail silently and said everything was SUCCESSFUL)

file:////mavenrepo/maven_repository

Debugging Maven Unit Test in Eclipse / STS

Maven unit tests (run by surefire plugin) can be debugged with eclipse. Firstly check you’re using surefire plugin version 2.16 or newer. Observe / add following in your pom.xml


  maven-surefire-plugin
  2.16

Ensure you’ve set some breakpoints to debug the faulty codes. Then on your run configuration, add -Dmaven.surefire.debug=true parameter:

maven-debug1

When this run configuration is executed, maven will wait for you to attach the remote debugger instead of launching the tests:

maven-debug2

Now open eclipse debug configuration, create a Remote Java Application config with your source code and set the port to 5005:

maven-debug3

When the debugger attaches the unit test will proceed and when any breakpoints hit you can debug it like a normal java/eclipse application

Using Maven to Include All Java EE API Into Classpath

If you use full Java EE container such as JBoss or Glassfish — and you (are fortunate enough) to use Maven. Here’s a simple way to pull all Java EE dependencies into your classpath. Add following dependency into your pom.xml:


  javax
  javaee-api
  6.0
  provided

Notice the scope is set to provided, this is important because on runtime all those classes will be provided by your container.

Also the above is for Java EE 6. You can use following for Java EE 7:


  javax
  javaee-api
  7.0
  provided

Deploying Standalone Java Project

There are two common approaches to deploy a Java program in a standalone environment:

Single (Uber Jar) Approach

“Uber Jar” is a single jar with all dependent classes and resources are dumped inside. This can be done easily using Maven assembly plugin:



  org.apache.maven.plugins
  maven-assembly-plugin
  2.3
  
    
      jar-with-dependencies
    
  

mvn clean package assembly:single

However this method could be faulty. Multiple dependency jars could have configuration file with the same path and they will overlap each other. For example both spring-context.jar and spring-beans.jar has META-INF/spring.handlers file:

spring-context-3.2.3.RELEASE.jar/META-INF/spring.handlers
spring-beans-3.2.3.RELEASE.jar/META-INF/spring.handlers

Exploded Deployment Approach

This slightly take more effort, but saver approach. Instead of dumping everything in a Uber Jar, deploy in an exploded fashion. You can get all runtime dependencies (that is “runtime”, “compile” and “provided” maven scope) placed inside target/dependency folder by configuring maven-dependency-plugin:



  maven-dependency-plugin
  2.8
  
    
      
        copy-dependencies
      
      
        runtime
      
    
  

Then deploy your jar in production server in directory structure similar like following

C:myscript
  +-- dependency
        +-- dep1.jar
        +-- dep2.jar
        +-- dep3.jar
  +-- myjar.jar
  +-- run.bat

The run.bat script is a simple java program to run your code (assuming MainClass name of com.mycompany.MainClass)

java -jar "./*;dependency/*" com.mycompany.MainClass

Creating New Java EE 7 Maven Eclipse Project

Still on the Java EE 7 hype, here’s a quick cheat sheet on how to create a minimal Java EE 7 ready maven project:

  1. Ensure you have Eclipse Indigo installed with m2e (maven connector). If not you can drag and drop this logo into running Eclipse instance

    (thanks m2e team)
  2. Create new maven project, tick Create a simple project (skip archetype selection), on the next screen provide Group Id, Artifact Id, and set Packaging to war. Hit Finish
    new maven proj cut
  3. Open pom.xml, switch to source view. Add Java EE 7 dependency. Set the scope to provided so that it is included at compile time, but not on the war bundle (because it should be provided by container)
    
      4.0.0
      com.gerrytan
      jee7fiddle
      1.0
      war
      
      
      
        
          javax
          javaee-api
          7.0
          provided
        
      
    
  4. Tell Maven to compile using JDK 7, otherwise the deafault is JDK 5
      
        
          
          
            maven-compiler-plugin
            3.1
            
              1.7
              1.7
            
          
    
  5. And finally prevent maven-war-plugin from complaining because of missing web.xml. New Java EE 7 style provides good annotation support, web.xml can be omitted for a simple project
          
          
            maven-war-plugin
            2.3
            
              false
            
          
        
      
    
    
  6. Right click on the project -> Maven -> Update Project… -> OK. This will cause m2e to synchronize with all changes we made
  7. Test your new project by running clean package
    maven run cut
    You should end up with a war bundle with your project name under target directory