Enterprise Java Development@TOPIC@
Follows a standard layout by convention
Can be customized
Root directory stays fairly clean
|-- pom.xml |-- src | |-- main | `-- test `-- target |-- classes |-- ex1-1.0-SNAPSHOT.jar |-- surefire-reports `-- test-classes
src
Source tree for all developed code
target
Build tree for artifacts created by the build
pom.xml
Defines the build
Managed by CM along with src tree
Related artifacts normally placed in src/compile, etc.
Managed by CM
Should not contain any auto-generated artifacts
src |-- main | |-- java | | `-- myorg | | `-- mypackage | | `-- ex1 | | `-- App.java | `-- resources `-- test |-- java | `-- myorg | `-- mypackage | `-- ex1 | `-- AppTest.java `-- resources `-- log4j.xml
main
Contains production artifacts for module
Built artifacts from this tree are generally placed in the produced archive
jar tf target/ex1-1.0-SNAPSHOT.jar META-INF/ META-INF/MANIFEST.MF myorg/ myorg/mypackage/ myorg/mypackage/ex1/ myorg/mypackage/ex1/App.class ...
test
Contains test artifacts for module
Built artifacts from this tree are not generally placed in the produced archive
A separate archive of built test artifacts can be optionally generated for reuse
[main or test]/java
Contains Java classes
Placed in a directory that matches the Java package for the class
[main or test]/resources
Contains property or other data files
Generally copied to target tree as-is or optionally filtered by the build
Resource filtering is when substitution ${placeholder}s in source files are replaced by their declared property values in the target tree. This is quite useful in customizing URLs, credentials, and other properties that might be unique to the current build environment. Properties can be defined in the pom.xml, settings.xml or injected into the build through various plugins (e.g., inject current date).
Not managed by CM
Contains auto-generated artifacts
Can be deleted at any time
target |-- classes | `-- myorg | `-- mypackage | `-- ex1 | `-- App.class |-- ex1-1.0-SNAPSHOT.jar |-- log4j-out.txt |-- surefire-reports | |-- myorg.mypackage.ex1.AppTest.txt | `-- TEST-myorg.mypackage.ex1.AppTest.xml `-- test-classes |-- log4j.xml `-- myorg `-- mypackage `-- ex1 `-- AppTest.class
classes
An exploded directory tree for built artifacts to be placed into the module archive
Mixture of Java and resource artifacts
test-classes
An exploded directory tree for built artifacts used for test
Mixture of Java and resource artifacts
Part of the test classpath
*-reports
Results of unit and integration testing
surefire-reports
unit test results
failsafe-reports
integration test results
Locate details of test pass/failures within this directory
$ mvn clean test ... Failed tests: testFail(myorg.mypackage.ex1.AppTest): app didn't return 0 Tests run: 2, Failures: 1, Errors: 0, Skipped: 0 [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ ... $ more target/surefire-reports/*.txt ------------------------------------------------------------------------------- Test set: myorg.mypackage.ex1.AppTest ------------------------------------------------------------------------------- Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.608 sec <<< FAILURE! testFail(myorg.mypackage.ex1.AppTest) Time elapsed: 0.019 sec <<< FAILURE! java.lang.AssertionError: app didn't return 0 at org.junit.Assert.fail(Assert.java:93) at org.junit.Assert.assertTrue(Assert.java:43) at myorg.mypackage.ex1.AppTest.testFail(AppTest.java:28) ...
{artifactId}-{version}.jar
Results of unit and integration testing
Archive with contents of target/classes
Can be installed into local Maven repo by build
log4j-out.txt
An example output file of the build/tests written to the target directory
Produced by log4j based on configuration in src/test/resources/log4j.xml or log4j.properties
Defines the artifact for dependents
Defines the build of the local module
<?xml version="1.0"?>
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>myorg.myproject</groupId>
<artifactId>ex1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>My First Simple Project</name>
...
<properties>
...
</properties>
<dependencies>
...
<dependencies>
<build>
<plugins>
...
</plugins>
</build>
</project>
Defines the type of module and automatically enacts a profile of plugs (default=jar)
packaging=jar - primary artifact is a Java archive
packaging=ejb - primary artifact is a JavaEE EJB
packaging=war - primary artifact is a JavaEE WAR
packaging=ear - primary artifact is a JavaEE EAR
packaging=pom - parent pom, used primarily for grouping leaf modules
packaging=... - custom extensions
Value assigned relates to dependency type
element
<dependency> <groupId>${project.groupId}</groupId> <artifactId>ejbsessionBankEAR</artifactId> <version>${project.version}</version> <type>ear</type> <scope>compile</scope> </dependency>
Used to uniquely identify the module
<groupId>myorg.myproject</groupId>
<artifactId>ex1</artifactId>
<version>1.0-SNAPSHOT</version>
groupId
Hierarchical name used to group a set of one or more artifacts
Represented as a directory structure in repositories
myorg/ `-- myproject `-- ex1 |-- 1.0-SNAPSHOT | |-- ex1-1.0-SNAPSHOT.jar | |-- ex1-1.0-SNAPSHOT.pom ...
artifactId
Base name for the artifacts produced by this module
1.0-SNAPSHOT/ |-- ex1-1.0-SNAPSHOT.jar |-- ex1-1.0-SNAPSHOT.pom |-- ex1-1.0-SNAPSHOT-tests.jar
version
Version ID for the artifact
Release: 1.0
Snapshot: 1.0-SNAPSHOT
Timestamped release that does not change name
Useful for active development not yet ready for release
Dependents poll for new snapshots and get the latest version
Easy to use during development but nearly impossible to manage changes
-SNAPSHOT suffix added to version
<version>1.0-SNAPSHOT</version>
1.0-SNAPSHOT/ |-- ex1-1.0-SNAPSHOT.jar
Locations where Maven stores and locates artifacts
Each user has a local repository referenced by ${settings.localRepository}
.
This defaults to $HOME/.m2/repository
<settings 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/settings-1.0.0.xsd">
<localRepository>c:/jhu/repository</localRepository>
...
MAVEN_HOME/conf/settings.xml defines a core set of remote repositories
Maven poms can define extensions to the remote repository list
<repositories>
<repository>
<id>jboss-nexus</id>
<name>JBoss Nexus Repository</name>
<url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
</repository>
</repositories>
Maven will first look for a dependency artifact in the local repository
Maven will then look for a dependency artifact in a remote repository like ibiblio
Maven will search all known repositories until the artifact is found or all repositories have been checked
Maven will install module artifacts into the local repository during the install
phase of the build
$ mvn install ... [INFO] --- maven-install-plugin:2.3.1:install (default-install) @ ex1 --- [INFO] Installing /home/jcstaff/proj/ejava-javaee/solutions/ex1/target/ex1-1.0-SNAPSHOT.jar to /home/jcstaff/.m2/repository/myorg/myproject/ex1/1.0-SNAPSHOT/ex1-1.0-SNAPSHOT.jar [INFO] Installing /home/jcstaff/proj/ejava-javaee/solutions/ex1/pom.xml to /home/jcstaff/.m2/repository/myorg/myproject/ex1/1.0-SNAPSHOT/ex1-1.0-SNAPSHOT.pom [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------
-U
to force an update checkMaven will limit its search of a remote repository to
expressed time limits. If it attempts and fails to locate
an artifact from a remote repository it will not re-attempt
to query that repository until the time limit expires.
Sometimes the failure has nothing to do with the repository
not having the artifact (e.g., wireless network down) and
when you clear the error you can force Maven to retry before
the timeout period expires by adding a -U
to the command line.
-o
offline flag to eliminate repository checksMany times Maven will be too aggressive searching for artifacts you already know are not of value to the current build. You can tell Maven to work in an offline mode to bypass the work involved. This is helpful when you are disconnected from the network but will fail if you are truly missing a required artifact. You can activate/deactivate the offline more consistently using an element in the settings.xml
<offline>false</offline>
dependency:go-offline
prior to network/repo outageMaven will lazily download required artifacts on-demand as different
plugins are executed. If you know you will be separated from the network or
a key repository will have an upcoming outage -- you can prepare your local
environment by having Maven eagerly resolve and download all dependencies
using the dependency:go-offline
goal.
$ mvn dependency:go-offline
[INFO] Scanning for projects...
Provide a means to define behavior of the build
Provide a means to define values once and re-use across the build
Promotes consistency
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
<java.source.version>1.8</java.source.version>
<java.target.version>1.8</java.target.version>
</properties>
Properties can also be expressed using -Dkey=value
system properties
Modules depend on artifacts from other modules
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
...
</dependencies>
GAV
Must provide its groupId, artifactId, and version for each dependency
scope
Defines when the dependency applies (default=compile)
scope=compile - classpath of src/main, src/test, and dependents
scope=provided - classpath of src/main, src/test but not dependents
scope=test - classpath of src/test but not src/main and dependents
scope=runtime - classpath of src/test and dependents but not of src/main
scope=import - used to replace locally declared dependencyManagement dependencies with the contents from another pom. Useful when declaring complex dependencies and want to make easy wholesale changes in dependency versions.
scope=system - used to declare a direct reference to a local archive. Not portable.
type
Defines the artifact type of ther module (default=jar)
type=jar - java archive
type=ejb - javaee EJB archive
type=war - javaee WAR archive
type=ear - javaee EAR archive
type=... - custom type
Value directly relates to the project packaging element of the dependency
|-- ejbsessionBankImpl | |-- ejbsessionBankImpl-3.0.2013.2-SNAPSHOT.jar |-- ejbsessionBankEJB | |-- ejbsessionBankEJB-3.0.2013.2-SNAPSHOT.jar |-- ejbsessionBankWAR | |-- ejbsessionBankWAR-3.0.2013.2-SNAPSHOT.war |-- ejbsessionBankEAR | |-- ejbsessionBankEAR-3.0.2013.2-SNAPSHOT.ear
classifier
Defines a special type of artifact/custom from a module
classifier=tests - java archive containing test artifacts
classifier=sources - java archive containing module source code
classifier=... - custom classifiers
`-- target ... |-- txHotelDAO-3.0.2013.2-SNAPSHOT.jar |-- txHotelDAO-3.0.2013.2-SNAPSHOT-sources.jar `-- txHotelDAO-3.0.2013.2-SNAPSHOT-tests.jar
Provides specific instructions for build
Usually does the right thing by default when possible
Default rules based on pom packaging type
<groupId>myorg.myproject</groupId>
<artifactId>ex1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging> <<== determines default build
All actions of the build are directed by plugins
Even the simplest commands will result in plugin downloads when you first start
Specific plugins are wired into the build by the module packaging type
Plugins have goals (analogous to public methods)
Plugins may have default phases for the goals to be executed
Plugins can be configured
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>${java.source.version}</source>
<target>${java.target.version}</target>
</configuration>
</plugin>
<!-- surefire.argLine is set in debugger profile -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22</version>
<configuration>
<argLine>${surefire.argLine}</argLine>
</configuration>
</plugin>
...
New plugins can be added, but will need to be wired into a specific lifecycle phase of the build.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<configuration>
<argLine>${surefire.argLine}</argLine>
</configuration>
<executions>
<execution> <!-- run the tests here -->
<id>integration-tests</id>
<phase>integration-test</phase>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution> <!-- delay failures to after undeploy -->
<id>verify</id>
<phase>verify</phase>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
The above example shows the failsafe plugin being configured to share some properties with surefire and have specific goals wired into the integration-test and verify lifecycle phases.
Maven build broken into phases
Plugins are added to the build and their goals execute during a specific phase
Build invoked using the mvn
command
$ mvn (phase) (plugin:goal) -D(system-property) -P(profile)
phase
clean
Remove contents of target tree
test
Build the src/main and src/test tree and execute the unit tests as defined by the surefire plugin
pre-integration
Perform unit tests and perform any steps required to ready for integration test
integration-test
Perform integration tests as defined by the failsafe plugin
post-integration-test
Tear down anything required to perform integration tests
verify
Evaluate results of integration tests
install
Install module artifacts into local repository
(plugin:goal)
Manually trigger a plugin goal without a specific build lifecycle
ex. jetty:run, dependency:tree, or dependency:help
-D(system-property)
Manually define a system property key or key and value to be used as a property in the build
Must configure surefire/failsafe to promote these as properties Junit -- these are system properties of the maven build and not of the JVM tasks kicked off by the maven build.
-P(profile)
Manually trigger build configurations latched by a profile
e.g., which DB driver to use
-P!(profile)
Manually turn off a profile
e.g., turn off a profile activated by a rule or settings.xml
The bash shell requires the bang ("!") character to be escaped. Use -P\!(profile) when using the bash shell.