11.3. Modifying an Existing Maven Project
Overview
If you already have a Maven project and you want to customize it to generate a FAB, perform the following steps:
Ensure that the package type is JAR
A FAB is packaged as a regular JAR file, which is the default package type in Maven. Ensure that the
packaging
element in your project's pom.xml
file contains the value, jar
, as shown in the following example:
<project ... >
...
<packaging>jar</packaging>
...
</project>
Customize the JDK compiler version
It is almost always necessary to specify the JDK version in your POM file. If your code uses any modern features of the Java language—such as generics, static imports, and so on—and you have not customized the JDK version in the POM, Maven will fail to compile your source code. It is not sufficient to set the
JAVA_HOME
and the PATH
environment variables to the correct values for your JDK, you must also modify the POM file.
To configure your POM file, so that it accepts the Java language features introduced in JDK 1.6, add the following
maven-compiler-plugin
plug-in settings to your POM (if they are not already present):
<project ... > ... <build> <defaultGoal>install</defaultGoal> <plugins> ... <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build> ... </project>
Configure class sharing
Any dependencies on standard artifacts already provided by the container should be declared as
provided
, to prevent the FAB runtime from unnecessarily installing those dependencies again. This typically includes artifacts whose names match the patterns, camel-*
, cxf-*
, activemq-*
, and fabric-*
.
For example, if you have an existing dependency on the
camel-http
artifact, you should modify the dependency by adding the scope
element as follows:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-http</artifactId>
<version>2.12.0.redhat-610379</version>
<scope>provided</scope>
</dependency>
Note
All dependencies with Maven group ID
org.apache.camel
, org.apache.cxf
, or org.apache.activemq
are shared by default (equivalent to provided
scope), so that the value of the scope
element is ignored by default. This behavior changes, however, if the FAB-Provided-Dependency
manifest header is specified explicitly—see the section called “Sharing dependencies” for details.
If you have a large number of dependencies to manage, it might be easier to share the standard container artifacts by adding a FAB manifest header. For details, see Example 11.1, “Configuring FAB Manifest Headers in the POM”.
Mark test artifacts with the test scope
Any artifacts needed only for testing must be marked with the test scope, as in the following example:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j-version}</version>
<scope>test</scope>
</dependency>
Of course, this is the standard convention in POM files. But it is particularly important to observe this convention with FAB projects. For any test artifacts that are not marked as such, the FAB runtime will attempt to download and install the test artifact into the container at run time.
Important
Because the test-only artifacts are not intended to be installed in the container, it is quite likely that a FAB will fail to deploy properly if test artifacts are not marked with the
test
scope.
Specify the requisite dependencies for WS applications
Make sure that you declare all of the requisite dependencies for an Apache CXF application and declare these dependencies with
provided
scope. For example, a basic Apache CXF application that uses the JAX-WS frontend needs the following Maven dependencies:
<project> ... <dependencies> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-frontend-jaxws</artifactId> <version>2.7.0.redhat-610379</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http</artifactId> <version>2.7.0.redhat-610379</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-http-jetty</artifactId> <version>2.7.0.redhat-610379</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>3.0.6.RELEASE</version> <scope>provided</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
Prefer Blueprint over Spring
If your project uses dependency injection or XML configuration, you should prefer the Blueprint framework over the Spring framework.
Because Blueprint is more tightly integrated with OSGi, it is usually able to find whatever dependencies it needs dynamically at deploy time. By contrast, dependencies introduced by a Spring XML file are more likely to lead to
ClassNotFound
exceptions at deploy time (FAB is not capable of parsing a Spring XML file to discover the dependencies it introduces).
Optionally configure JAR manifest headers
Although the FAB runtime obtains most of its deployment metadata by scanning the
pom.xml
file embedded in the JAR, you can also specify FAB-specific configuration settings by adding headers to the JAR's manifest. For example:
FAB-Version-Range-Digits: 2 FAB-Provided-Dependency: org.acme.foo:* org.apache.camel:* org.apache.cxf:* org.apache.activemq:*
For detailed explanations of all the FAB manifest headers, see Section 11.4, “Configuring a FAB”.