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:

<distributionManagement>
  <repository>
    <id>enfinium</id>
    <name>Enfinium Internal Repository</name>
    <url>file://mavenrepo/maven_repository</url>
  </repository>
</distributionManagement>

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

Advertisements

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

<plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.16</version>
</plugin>

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:

<dependency>
  <groupId>javax</groupId>
  <artifactId>javaee-api</artifactId>
  <version>6.0</version>
  <scope>provided</scope>
</dependency>

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:

<dependency>
  <groupId>javax</groupId>
  <artifactId>javaee-api</artifactId>
  <version>7.0</version>
  <scope>provided</scope>
</dependency>

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:

<!-- On your pom.xml -->
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <version>2.3</version>
  <configuration>
    <descriptorRefs>
      <descriptorRef>jar-with-dependencies</descriptorRef>
    </descriptorRefs>
  </configuration>
</plugin>
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:

<!-- on your pom.xml -->
<plugin>
  <artifactId>maven-dependency-plugin</artifactId>
  <version>2.8</version>
  <executions>
    <execution>
      <goals>
        <goal>copy-dependencies</goal>
      </goals>
      <configuration>
        <includeScope>runtime</includeScope>
      </configuration>
    </execution>
  </executions>
</plugin>

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)
    <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.gerrytan</groupId>
      <artifactId>jee7fiddle</artifactId>
      <version>1.0</version>
      <packaging>war</packaging>
      
      <!-- Java EE 7 dependency -->
      <dependencies>
        <dependency>
          <groupId>javax</groupId>
          <artifactId>javaee-api</artifactId>
          <version>7.0</version>
          <scope>provided</scope>
        </dependency>
      </dependencies>
    
  4. Tell Maven to compile using JDK 7, otherwise the deafault is JDK 5
      <build>
        <plugins>
          <!-- Set to compile using JDK 7 -->
          <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
              <source>1.7</source>
              <target>1.7</target>
            </configuration>
          </plugin>
    
  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
          <!-- Avoid war plugin complaining missing web.xml -->
          <plugin>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.3</version>
            <configuration>
              <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    
  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