User Tools

Site Tools


maven

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
maven [2016/06/01 14:54]
mstraub [Building an executable jar]
maven [2016/12/15 16:01]
mstraub [JBoss 7]
Line 1: Line 1:
 +====== Introduction ======
 +
 +Maven is yet another build automation tool, comparable to e.g. ant; check the [[http://​maven.apache.org/​|project homepage]] and the [[http://​en.wikipedia.org/​wiki/​Apache_Maven|wikipedia]] page.
 +===== Characteristics =====
 +
 +  * convention over configuration
 +  * tries to enforce best practices and standards  ​
 +  * tries to enforce clean dependency management.
 +
 +Directory layout of a maven project
 +
 +<​code>​
 +├── pom.xml
 +├── src
 +│   ├── main
 +│   │   ├── java
 +│   │   │   └── com.company.project.*
 +│   │   └── resources
 +│   └── test
 +│   ​    ​├── java
 +│   ​    │   └── com.company.project.*
 +│   ​    ​└── resources
 +└── target
 +</​code>​
 +
 +===== Project Object Model (POM) =====
 +
 +The POM is the heart of all Maven projects. It is an XML file containing all the information and configuration details required for a project.
 +
 +Example for a minimal pom.xml
 +
 +<code xml>
 +<​project>​
 +  <​modelVersion>​4.0.0</​modelVersion>​
 +  <​groupId>​com.mycompany.app</​groupId>​
 +  <​artifactId>​my-app</​artifactId>​
 +  <​version>​1.0.0</​version>​
 +</​project>​
 +</​code>​
 +
 +The default packaing type is jar. To build a war, just add:
 +
 +<code xml>
 +  <​packaging>​war</​packaging>​
 +</​code>​
 +
 +For more details go [[http://​maven.apache.org/​pom.html#​Quick_Overview|over there]] [[http://​maven.apache.org/​guides/​introduction/​introduction-to-the-pom.html|or there]].
 +====== Basics ======
 +===== Creating a project =====
 +<code bash>
 +mvn archetype:​generate # pick type and answer basic questions
 +</​code>​
 +
 +This creates the pom.xml and a basic directory structure.
 +
 +If you want to create it by hand instead:
 +<code bash>
 +mkdir -p src/​main/​{java,​resources}
 +mkdir -p src/​test/​{java,​resources}
 +touch pom.xml
 +</​code>​
 +===== Building =====
 +<​code>​
 +mvn verify # build, test, package, integration-test and verify ​
 +</​code>​
 +
 +see http://​maven.apache.org/​guides/​introduction/​introduction-to-the-lifecycle.html
 +===== Local Install =====
 +Install your project to the **local repository**
 +<​code>​
 +mvn install
 +</​code>​
 +
 +
 +
 +
 +===== Deploy to Maven repository =====
 +**Configure the target repository** in pom.xml:
 +<code xml>
 +  <​distributionManagement>​
 +  ​
 +    <​repository>​
 +      <​id>​internal.repo</​id>​
 +      <​name>​Internal Releases</​name>​
 +      <​url>​http://​192.168.1.10:​8081/​nexus/​content/​repositories/​releases/</​url>​
 +    </​repository>​
 +    ​
 +    <​snapshotRepository>​
 +        <​id>​internal.repo</​id>​
 +        <​name>​Internal Snapshots</​name>​
 +        <​url>​http://​192.168.1.10:​8081/​nexus/​content/​repositories/​snapshots/</​url>​
 +    </​snapshotRepository>​
 +
 +  </​distributionManagement>​
 +</​code>​
 +
 +Dont forget to **set your credentials** in ~/​.m2/​settings.xml ​ : 
 +<code xml>
 +<​settings>​
 +<​servers>​
 +  <​server>​
 +    <​id>​internal.repo</​id>​
 +    <​username>​deployment</​username>​
 +    <​password>​deployment123</​password>​
 +  </​server>​
 +</​servers>​
 +</​settings>​
 +</​code>​
 +
 +Deploy to the repository: ​
 +<​code>​
 +mvn deploy
 +</​code>​
 +
 +===== Deploy to JBoss =====
 +Note: replace /opt/jboss with /​your/​path/​to/​jboss and also make sure to use the correct server IP.
 +
 +==== JBoss / WildFly ====
 +
 +This works about the same since JBoss 7 up to (currently) WildFly 10
 +
 +=== Server Preparations ===
 +
 +If you only want to deploy to localhost no preparation is required. Just start the server.
 +
 +To connect to a remove server the management interface must be bound to an interface. This can be achieved with the startup parameter -bmanagement. In the example webservices are bound 0.0.0.0, which means everywhere (the opposite of the default, which is localhost only).
 +<code bash>
 +/​opt/​jboss/​bin/​standalone.sh -b 0.0.0.0 -bmanagement your.server.ip.address
 +</​code>​
 +
 +Additionally you should create a management user by using this script (changes /​opt/​jboss/​standalone|domain/​configuration/​mgmt-users.properties):​
 +<code bash>
 +/​opt/​jboss/​bin/​add-user.sh
 +</​code>​
 +
 +=== JBoss 7: jboss-as-maven-plugin ===
 +Add the [[jenkins&#​continuous_delivery_with_jenkins|jboss-as-maven-plugin]] to your pom.xml and also configure the management user you just created.
 +<code xml>
 +<​plugin>​
 + <​groupId>​org.jboss.as.plugins</​groupId>​
 + <​artifactId>​jboss-as-maven-plugin</​artifactId>​
 + <​version>​7.3.Final</​version>​
 + <​configuration>​
 + <​username>​user</​username>​
 + <​password>​password</​password>​
 + </​configuration>​
 +</​plugin>​
 +</​code>​
 +
 +Then you are ready to rumble:
 +
 +<code bash>
 +  mvn clean package
 +  # local deployment
 +  mvn jboss-as:​deploy
 +  # remote deployment
 +  # this seems to be buggy: if a hostname is specified in pom.xml it will be ignored at the command line!
 +  mvn -Djboss-as.hostname=your.server.ip.address jboss-as:​deploy
 +  ​
 +  # undeploy
 +  mvn jboss-as:​undeploy
 +</​code>​
 +
 +Note, that you will not find the deployment as expected in ''/​opt/​jboss/​standalone/​deployments'',​ but it is hidden away in a zip archive named with a sha1-hash in ''/​opt/​jboss/​standalone/​data/​content''​ - to avoid manual tampering. You can see and manage (disable / undeploy) all deployments in the management console on port 9990 though (e.g. http://​localhost:​9990).
 +
 +Actually an entry is added to the end of ''/​opt/​jboss/​standalone/​configuration/​standalone.xml''​ for each deployment:
 +<code xml>
 +<​deployments>​
 +  <​deployment name="​my.war"​ runtime-name="​my.war">​
 +    <content sha1="​30e075d8bf475021ecf82a2979a89c202dd31044"/>​
 +  </​deployment>​
 +</​deployments>​
 +</​code>​
 +
 +
 +Full documentation:​ https://​docs.jboss.org/​jbossas/​7/​plugins/​maven/​latest/​index.html
 +
 +=== WildFly 8 and higher: wildfly-maven-plugin ===
 +
 +Basically this works the same as the old jboss plugin.
 +
 +Documentation:​ https://​docs.jboss.org/​wildfly/​plugins/​maven/​latest/​
 +
 +==== Older JBoss Versions ====
 +
 +To deploy via JMX over HTTP
 +<code bash>
 +  mvn jboss:​deploy ​
 +</​code>​
 +
 +To copy the file directly to the deploy directory of a local server:
 +
 +<code bash>
 +  export JBOSS_HOME=/​opt/​jboss
 +  mvn jboss:​hard-deploy
 +</​code>​
 +
 +
 +
 +
 +
 +
 +====== Maven + Eclipse ======
 +  * Don't check in the Eclipse-specific config files. Maven can generate them for you!
 +  * ''​svn propedit svn:ignore .''​
 +  * add one line for .project .classpath and .settings each
 +
 +
 +===== Eclipse plugins =====
 +  * [[http://​eclipse.org/​m2e/​ | m2e Plugin]]
 +
 +
 +
 +===== Checking out a Maven project from SCM =====
 +==== Using m2e Import ====
 +With m2e installed ​
 +
 +>File --> Import.. --> Maven --> Project from SCM   
 +
 +//should// work. But the Plugin does not work very well with the Eclipse Team  provider (in Eclipse Juno): http://​stackoverflow.com/​questions/​6729511/​checkout-maven-project-from-scm-no-connectors
 +
 +=== Workaround ===
 +
 +With the m2e Plugin installed. ​
 +
 +1. Check out the project using normal Eclipse Team provider. The project will not function as java project just yet. 
 +
 +2. Close the project. Go to console and enter
 +
 +<​code>​
 +mvn eclipse:​clean
 +mvn eclipse:​eclipse
 +</​code>​
 +
 +3. Re-open the project. Right click the project:  ​
 +> Configure.. --> Convert to Maven project ​ (ignore the errors). ​
 +
 +4. Close the project. Go to console and
 +<​code>​
 +rm .classpath
 +</​code>​
 +
 +5. Re-open the project. Right click the project: ​
 +>Maven --> Update Project
 +
 +
 +===== Convert Eclipse project to Maven =====
 +
 +
 +Remove Eclipse artefacts ​
 +  * .classpath
 +  * .settings
 +  * .project
 +
 +
 +Close the project. Go to console and enter
 +
 +<​code>​
 +mvn eclipse:​clean
 +mvn eclipse:​eclipse
 +</​code>​
 +
 +Re-open the project. Right click the project:  ​
 +> Configure.. --> Convert to Maven project ​ (ignore the errors). ​
 +
 +Close the project. Go to console and
 +<​code>​
 +rm .classpath
 +</​code>​
 +
 +Re-open the project. Right click the project: ​
 +>Maven --> Update Project
 +
 +Be sure to set all Maven dependencies for your project.
 +
 +
 +===== Create new JBoss Service =====
 +
 +Create a pom.xml by adapting an already existing one (by hand)
 +
 +Create the src folder hierarchy by hand:
 +<​code>​
 +mkdir -p src/​main/​java
 +mkdir -p src/​main/​resources
 +mkdir -p src/​test/​java
 +mkdir -p src/​test/​resources
 +</​code>​
 +
 +Then import the pom.xml into Eclipse as described above. If you Eclipse has a full installation of JBoss Tools (tested with Eclipse Indigo) the created project will be a web project and can be dragged and dropped to servers within Eclipse.
 +
 +
 +====== Testing ======
 +===== Integration Tests =====
 +Often you have (hopefully) fast running unit tests and slower running integration tests. Maven provides two different goals to cleanly seperate these two: 
 +
 +  * Unit Tests 
 +    * are fast
 +    * are run using the maven-surefire-plugin during the goal "​test"​
 +    * Test classes need to be located in src/​test/​java/ ​
 +    * Class names need to end in "​Test"​ (eg. RouterTest.java ) 
 +    * run with //mvn package// ​
 +  * Integration Tests
 +    * may be slow 
 +    * are run by the maven-failsafe-plugin during the goal "​integration-test" ​
 +    * Test classes also need to be located in src/​test/​java/​
 +    * Class names need to end in "​IT"​ (eg. RouterIT.java)
 +    * run with //mvn verify//
 + 
 +==== Setting up Integration Tests ====
 +
 +  * Write a JUnit Integration Test (class name must end in "​IT"​)
 +  * Configure the maven-failsafe-plugin in pom.xml
 +<code xml>
 +<​build>​
 +
 +  <​plugin>​
 +    <​groupId>​org.apache.maven.plugins</​groupId>​
 +    <​artifactId>​maven-failsafe-plugin</​artifactId>​
 +    <​version>​2.12.3</​version>​
 +     <​executions>​
 +       <​execution>​
 +         <​goals>​
 +           <​goal>​integration-test</​goal>​
 +           <​goal>​verify</​goal>​
 +         </​goals>​
 +       </​execution>​
 +     </​executions>​
 +  </​plugin>​
 +
 +</​build>​
 +
 +</​code>​
 +
 +  * Run integration tests with //mvn verify//
 +
 +
 +
 +
 +====== Building an executable jar ======
 +
 +Use the [[https://​maven.apache.org/​plugins/​maven-shade-plugin/​usage.html|maven-shade-plugin]] to build an uber-jar with ''​mvn package''​.
 +
 +Note, that you have to care about shadowing problems yourself and handle them with transformers,​ e.g. use an AppendingTransformer to prevent SQLite and PostgreSQL overwriting META-INF/​services/​java.sql.Driver.
 +
 +<code xml>
 +<​build>​
 +  <​plugins>​
 +    <​plugin>​
 +      <​groupId>​org.apache.maven.plugins</​groupId>​
 +      <​artifactId>​maven-shade-plugin</​artifactId>​
 +      <​version>​2.4.1</​version>​
 +      <​executions>​
 +        <​execution>​
 +          <​phase>​package</​phase>​
 +          <​goals>​
 +            <​goal>​shade</​goal>​
 +          </​goals>​
 +          <​configuration>​
 +            <​transformers>​
 +              <​transformer implementation="​org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">​
 +                <​mainClass>​my.package.Main</​mainClass>​
 +              </​transformer>​
 +              <​transformer implementation="​org.apache.maven.plugins.shade.resource.AppendingTransformer">​
 +                <​resource>​META-INF/​services/​java.sql.Driver</​resource>​
 +              </​transformer>​
 +            </​transformers>​
 +            <!-- in case a signed jar is contained in the dependences -->
 +            <​filters>​
 +              <​filter>​
 +                <​artifact>​*:​*</​artifact>​
 +                <​excludes>​
 +                  <​exclude>​META-INF/​*.SF</​exclude>​
 +                  <​exclude>​META-INF/​*.DSA</​exclude>​
 +                  <​exclude>​META-INF/​*.RSA</​exclude>​
 +                </​excludes>​
 +              </​filter>​
 +            </​filters>​
 +          </​configuration>​
 +        </​execution>​
 +      </​executions>​
 +    </​plugin>​
 +  </​plugins>​
 +</​build>​
 +</​code>​
 +
 +The hint on dealing with signed jars is from http://​zhentao-li.blogspot.co.at/​2012/​06/​maven-shade-plugin-invalid-signature.html.
 +
 +
 +The deprecated way is to use the maven-assembly-plugin:​
 +
 +<code xml>
 +
 +<​build>​
 +  <​plugins>​
 +  ​
 +  <!-- Package as Executable jar -->
 +    <​plugin>​
 +      <​groupId>​org.apache.maven.plugins</​groupId>​
 +      <​artifactId>​maven-assembly-plugin</​artifactId>​
 +      <​version>​2.2.1</​version>​
 +      ​
 +      <​configuration>​
 +        <​appendAssemblyId>​true</​appendAssemblyId>​
 +        <​descriptorRefs>​
 +          <​descriptorRef>​jar-with-dependencies</​descriptorRef>​
 +        </​descriptorRefs>​
 +        <​archive>​
 +          <​manifest>​
 +            <​mainClass>​com.company.my.MainClass</​mainClass>​
 +          </​manifest>​
 +        </​archive>​
 +      </​configuration>​
 +      ​
 +      <!-- To automatically build the jar-with-dependencies ​
 +      during the package phase, add the next section -->
 +      <​executions>​
 +        <​execution>​
 +          <​id>​package-jar-with-dependencies</​id>​
 +          <​phase>​package</​phase>​
 +          <​goals>​
 +            <​goal>​single</​goal>​
 +          </​goals>​
 +        </​execution>​
 +      </​executions>​
 +      ​
 +    </​plugin> ​               ​
 +
 +  </​plugins>​
 +</​build>​
 +
 +</​code>​
 +
 +
 +If the execution goal is not enabled, the executable jar can be built manually using
 +
 +<code bash>
 +mvn clean verify assembly:​single # must be all in one command. otherwise it does not work. no idea why.
 +</​code>​
 +
 +
 +====== Dependency Management ======
 +
 +
 +
 +===== Declaring Dependencies =====
 +In your **pom.xml**
 +
 +<code xml>
 +  <​dependencies>​
 +  <​dependency>​
 +  <​groupId>​junit</​groupId>​
 +  <​artifactId>​junit</​artifactId>​
 +  <​version>​4.10</​version>​
 +                <​scope>​test</​scope>​
 +  </​dependency>​
 +  </​dependencies>​
 +</​code>​
 +
 +
 +===== Dependencies in an internal repository =====
 +Assuming your company builds a library which is available from an internal maven repository you can specify that dependency same as above, but you also have to tell maven about your local repo. There are two ways to do this
 +
 +* Enter the repository in your pom.xml
 +
 +<code xml>
 +<​repositories>​
 + <​repository>​
 + <​id>​local-maven-repo</​id>​
 + <​url>​http://​192.168.1.10:​8081/​nexus/​content/​groups/​public/</​url>​
 + <​snapshots>​
 + <​updatePolicy>​always</​updatePolicy>​
 + </​snapshots>​
 + <​releases>​
 + <​updatePolicy>​always</​updatePolicy>​
 + </​releases>​
 + </​repository>​
 +</​repositories>​
 +</​code>​
 +
 +* enter the repository in your ~/​.m2/​settings.xml
 +<code xml>
 +
 +<​settings>​
 +
 +  <​profiles>​
 +    <!-- Define a profile which knows the local repo -->
 +    <​profile>​
 +      <​id>​default</​id>​
 +      <​activation>​
 +        <​activeByDefault>​true</​activeByDefault>​
 +      </​activation> ​
 +      <​repositories>​
 +        <​repository>​
 +          <​id>​local-maven-repo</​id>​
 +          <​name>​Local Repo</​name>​
 +          <​releases>​
 +            <​updatePolicy>​always</​updatePolicy>​
 +          </​releases>​
 +          <​snapshots>​
 +            <​updatePolicy>​always</​updatePolicy>​
 +          </​snapshots>​
 +          <​url>​http://​192.168.1.10:​8081/​nexus/​content/​groups/​public/</​url>;​
 +        </​repository>​
 +      </​repositories>​
 +    </​profile>​
 +  </​profiles>​
 +
 +</​settings>​
 +
 +</​code>​
 +
 +
 +==== Version ====
 +When declaring a "​normal"​ version such as 4.10 for JUnit, internally this is represented as "allow anything, but prefer 4.10"
 +
 +
 +=== Version Ranges ===
 +You can specify a range of versions that would satisfy a given dependency:
 +
 +
 +^ Range        ^ Meaning ​ ^
 +|(,​1.0] ​       | x < = 1.0 |
 +|1.0           | "​Soft"​ requirement on 1.0 (just a recommendation - helps select the correct version if it matches all ranges) |
 +|[1.0] ​        | Hard requirement on 1.0 |
 +|[1.2,​1.3] ​    | 1.2 < = x < = 1.3 |
 +|[1.0,​2.0) ​    | 1.0 < = x < 2.0 |
 +|[1.5,​) ​       | x > = 1.5 |
 +|(,​1.0],​[1.2,​) | x < = 1.0 or x > = 1.2. Multiple sets are comma-separated |
 +|(,​1.1),​(1.1,​) |This excludes 1.1 if it is known not to work in combination with this library |
 +
 +Default strategy: Of the overlapping ranges, the highest soft requirement is the version to be used. If there are no soft requirements inside the prescribed ranges, the most recent version is used. If that does not fit the described ranges, then the most recent version number in the prescribed ranges is used. If the ranges exclude all versions, an error occurs.
 +
 +
 +
 +
 +  * http://​docs.codehaus.org/​display/​MAVEN/​Dependency+Mediation+and+Conflict+Resolution#​DependencyMediationandConflictResolution-DependencyVersionRanges
 + 
 +==== Scope ====
 +Valid scopes are
 +
 +  * **compile** - the default. Makes the dependency available in all classpaths of a project. Propagated to dependent projects.
 +  * **provided** - indicates you expect the JDK or a container (eg. JBoss) to provide the dependency at runtime. --> Dependency is only available on the compilation and test classpath, and is not transitive.
 +  * **runtime** - dependency is not required for compilation,​ but is for execution. --> Dependency is in the runtime and test classpaths, but not the compile classpath.
 +  * **test** - dependency is not required for normal use of the application,​ and is only available for the test compilation and execution phases.
 +   * **system** - This scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository.
 +   * **import** - used on a dependency of type pom in the <​dependencyManagement>​ section. It indicates that the specified POM should be replaced with the dependencies in that POM's <​dependencyManagement>​ section.
 +
 +===== Transitive Dependencies =====
 +
 +Transitive dependencies are a new feature in Maven 2.0. This allows you to avoid needing to discover and specify the libraries that your own dependencies require, and including them automatically.
 +
 +This feature is facilitated by reading the project files of your dependencies from the remote repositories specified. In general, all dependencies of those projects are used in your project, as are any that the project inherits from its parents, or from its dependencies.
 +
 +
 +===== Unmanaged Dependencies =====
 +A clean way to handle unamanaged dependencies is described here: https://​devcenter.heroku.com/​articles/​local-maven-dependencies
 +
 +This is also useful in the case not all people working with a maven project can resolve all dependences (because some dependencies are only available on internal repositories). The internal-only dependencies can be published with this method.
 +
 +  * Use ''​mvn''​ to deploy the library to a local repository. This will create the correct directory structure plus meta files. ​
 +
 +<code bash>
 +mvn deploy:​deploy-file \
 +    -Durl=file:​my_repository \
 +    -Dfile=mylib-1.0.jar \
 +    -DgroupId=com.example \
 +    -DartifactId=mylib \
 +    -Dpackaging=jar \
 +    -Dversion=1.0
 +</​code>​
 +
 +
 +  * Add the local repository to you pom.xml
 +<code xml>
 +<​repositories>​
 +    <​!--other repositories if any-->
 +    <​repository>​
 +        <​id>​project.local</​id>​
 +        <​name>​project</​name>​
 +        <​url>​file:​${project.basedir}/​my_repository</​url>​
 +        <​snapshots>​
 +           <​updatePolicy>​always</​updatePolicy>​
 +        </​snapshots>​
 +        <​releases>​
 +           <​updatePolicy>​always</​updatePolicy>​
 +        </​releases>​
 +    </​repository>​
 +</​repositories>​
 +</​code>​
 +
 +  * Add the dependency like you normally would:
 +<code xml>
 +<​dependency>​
 +    <​groupId>​com.example</​groupId>​
 +    <​artifactId>​mylib</​artifactId>​
 +    <​version>​1.0</​version>​
 +</​dependency>​
 +</​code>​
 +
 +===== Useful Links =====
 +
 +  * http://​maven.apache.org/​guides/​introduction/​introduction-to-dependency-mechanism.html
 +====== Release Management ======
 +**Use Case:** you are developing on a version like "​2.1.5-SNAPSHOT"​. Once the version is stable you want to make a 2.1.5 release, tag it in SVN and start working on the next version (2.1.6-SNAPSHOT or something like that). The [[http://​maven.apache.org/​plugins/​maven-release-plugin/​ | Maven Release Plugin]] supports this. 
 +
 +
 +
 +===== Set-Up =====
 +
 +==== Configure SCM ====
 +Make sure your pom.xml contains a valid SCM section (more info [[http://​maven.apache.org/​pom.html#​SCM]]
 +
 +
 +=== SVN ===
 +
 +The typical directory hierarchy with trunk, tags and branches must be used and created manually.
 +If e.g. the directory tags is missing release:​perform will fail.
 +
 +<code xml>
 +<scm>
 +    <!-- Base URL of repository (trunk/​tags/​branches independent)-->​
 +    <​url>​scm:​svn:​http://​svn.my.company.com/​repository</​url>​
 +    <!-- Current working url (NOT TAG) - read-only, used for e.g. update -->
 +    <​connection>​scm:​svn:​http://​svn.my.company.com/​repository/​trunk/​my-project</​connection>​
 +    <!-- Current working url (with write privileges) -->
 +    <​developerConnection>​scm:​svn:​http://​svn.my.company.com/​repository/​trunk/​my-project</​developerConnection>​
 +</​scm>​
 +</​code>​
 +
 +=== Mercurial ===
 +
 +The whole project just resides in one directory. Separate directories for trunk/​tags/​branches are not required, this is done automatically via the tagging and branching functionality of mercurial.
 +
 +The urls are therefore always the same (and must not be a subdirectory of the project)
 +
 +<code xml>
 +<scm>
 +    <​url>​scm:​hg:​https://​hg.my.company.com/​repository</​url>​
 +    <​connection>​scm:​hg:​https://​hg.my.company.com/​repository</​connection>​
 +    <​developerConnection>​scm:​hg:​https://​hg.my.company.com/​repository</​developerConnection>​
 +</​scm>​
 +</​code>​
 +
 +Also the <​build>​-part of your pom.xml should add a dependency to the maven-scm-provider-hg.
 +(Probably that's optional .. test this in the future)
 +
 +<code xml>
 +<​pluginManagement>​
 + <​plugins>​
 + <​plugin>​
 + <​artifactId>​maven-release-plugin</​artifactId>​
 + <​version>​2.4.1</​version>​
 + <​dependencies>​
 + <​dependency>​
 + <​groupId>​org.apache.maven.scm</​groupId>​
 + <​artifactId>​maven-scm-provider-hg</​artifactId>​
 + <​version>​1.8.1</​version>​
 + </​dependency>​
 + </​dependencies>​
 + </​plugin>​
 + </​plugins>​
 +</​pluginManagement>​
 +</​code>​
 +
 +
 +==== Optional: Specify a custom location for the tags ====
 +
 +<code xml>
 +<​build>​
 + <​plugin>​
 +      <​groupId>​org.apache.maven.plugins</​groupId>​
 +      <​artifactId>​maven-release-plugin</​artifactId>​
 +      <​configuration>​
 +            <​tagBase>​http://​svn.my.company.com/​repository/​tags</​tagBase>​
 +      </​configuration>​
 + </​plugin>​
 +</​build>​
 +</​code>​
 +
 +
 +==== Optional: Specify deployment location ====
 +see [[maven#​deploy_to_maven_repository]]
 +
 +==== Handling SCM credentials ====
 +
 +This should work both for SVN and mercurial:
 +
 +Either handle them externally: ensure you DON't have to enter your SCM login each time (i.e. your login information is stored somewhere by SVN) 
 +
 +**OR**
 +edit  ~/​.m2/​settings.xml and add a section
 +<​code>​
 +  <​server> ​                                                                     ​
 +    <​id>​server-hostname-or-IP</​id> ​                                                     ​
 +    <​username>​username</​username> ​                                          
 +    <​password>​mellon</​password> ​                                              
 +  </​server> ​                                                                    
 +</​code> ​              
 +**OR** add the credentials explicitly
 +<code bash>
 +mvn release:​perform ​ -Dusername=user -Dpassword=password
 +</​code>​
 +===== Release Workflow =====
 +
 +**Commit changes & check Javadoc**
 +  * Make sure everything is committed to your VCS
 +  * Check for javadoc errors with mvn site (mvn javadoc:​javadoc does not seem to build everything) - this avoids annoying problems at the very end (mvn release:​perform))
 +    * In case your site build takes ages due to errors like "​[ERROR] Unable to determine if resource batik:​batik-util:​jar:​1.6-1:​compile exists in https://​repository.jboss.org/​nexus/​content/​groups/​public/"​ simply run mvn site -Ddependency.locations.enabled=false ([[https://​whatiscomingtomyhead.wordpress.com/​2011/​04/​20/​if-your-maven-site-build-is-too-slow/​|source]])
 +
 +**Verify the build**
 +  * Verify all files in your project are committed
 +  * Verify your project has no SNAPSHOT dependencies
 +  * Verify <​version>​ of your project'​s pom.xml is a SNAPSHOT version
 +  * Verify the project
 +<​code>​
 +mvn verify
 +</​code>​
 +
 +
 +**Prepare the release information**
 +  * Confirm what the project'​s next RELEASE version will be
 +  * Confirm what the project'​s SVN tag for the next release version will be
 +  * Confirm what the project'​s next SNAPSHOT version will be
 +
 +** Dry run **
 +Since the Release Plugin performs a number of operations that change the project, it may be wise to do a dry run before a big release or on a new project. To do this, commit all of your files as if you were about to run a full release and run:
 +<​code>​
 +mvn release:​prepare -DdryRun=true # then check the generated files 
 +mvn release:​clean # Removes all of the files created above, and the project will be ready to execute the proper release
 +</​code>​
 +
 +** Prepare the release **
 +<code bash>
 +mvn release:​prepare ​ # answer the questions maven asks
 +</​code>​
 +
 +** Check ** the generated release.properties. ​
 +
 +If something is not right the release can be rolled back with: //"mvn release:​rollback"//​
 +
 +
 +**CAUTION**:​ rollback [[http://​maven.apache.org/​maven-release/​maven-release-plugin/​examples/​rollback-release.html|currently does NOT remove already created tags in your SCM]]. You have to delete the tag yourself.
 +
 +
 +**Perform the release ** if everything looks alright:
 +<code bash>
 +mvn release:​perform
 +</​code>​
 +
 +**Note**: When deploying a new **release** to a Nexus repository fails, make sure that there'​s **not already an artifact of the same name & version there**. If you are deploying to a release Nexus repository, you cannot overwrite an existing file.
 +
 +
 +===== Staging a release =====
 +tbd
 +
 +===== Deploy release to production JBoss =====
 +
 +To make production deployments really easy, here is a script that does 
 +
 +  * get the war file that shall be deployed
 +  * starting the jboss-cli
 +  * deploy my.war  ​
 +
 +<code python>
 +#​!/​usr/​bin/​env python
 +
 +#
 +# Usage: ​ ./deploy.py <​artifact_version>​
 +# Example: ./deploy.py 0.0.1
 +#
 +
 +import os
 +import sys
 +import logging
 +logging.basicConfig(filename="​deploy.log",​ level=20, format="​%(asctime)-15s %(levelname)s\t(%(filename)s:​%(lineno)d) -  %(message)s"​)
 +
 +artifact_id = "​fancy-services"​
 +warname = "​fancy.war"​
 +nexus_repo="​http://​nexus:​port/​nexus/​content/​repositories/​releases/​path/​to/​artifact/"​ +artifact_id+ "/"​
 +jboss_base_cmd = """/​opt/​jboss/​bin/​jboss-cli.sh --connect --controller=127.0.0.1:​9999 --user=elder --password=secret """​
 +
 +
 +def jboss(command_text,​ raise_on_error=True):​
 + cmd = jboss_base_cmd + """​ --command="​%s"​ """​ % command_text
 + returncode=os.system(cmd)
 + if raise_on_error and returncode != 0:
 + raise Exception("​command %s failed"​ % command_text)
 +
 +def downloadArtifact():​
 + url = nexus_repo + release_version + "/"​ + versioned_artifact
 + os.system("​rm {0}"​.format(warname))
 + logging.debug("​Getting artifact from " + url)
 + returncode = os.system("​wget {url} -O {war}"​.format(url=url,​ war=warname))
 + if returncode!=0:​
 + raise Exception("​Download Failed: " + url)
 +
 +def showDeployments():​
 + print "​Currently deployed on host:​\n"​
 + jboss("​deploy -l", raise_on_error=False) # list deployments
 +
 +
 +release_version = sys.argv[1]
 +versioned_artifact = artifact_id+"​-"​+release_version + "​.war"​
 +
 +logging.info("​Attempting to deploy " + versioned_artifact)
 +try:
 + downloadArtifact()
 + jboss("​undeploy {0}"​.format(warname),​ raise_on_error=False ) # undeploy old version
 + jboss("​deploy {0}"​.format(warname),​ raise_on_error=True) # deploy new version
 +
 + logging.info("​SUCCESS:​ " + versioned_artifact + " deployed."​)
 + print "​\n\nSUCCESS\n"​
 + showDeployments()
 +except Exception, e: 
 + logging.exception("​ERROR:​ Deployment of %s failed " % versioned_artifact)
 + print "​\n\nERROR:​ Deployment failed\n\n"​
 + print e
 +
 +</​code>​
 +
 +
 +====== Misc ======
 +
 +===== Create archetypes from existing projects =====
 +
 +Using an existing project (preferrably a stable release) you can simply create and locally install an archetype:
 +
 +<code bash>
 +# cd <​wherever the pom.xml of the project of your choice resides>
 +mvn archetype:​create-from-project
 +cd target/​generated-sources/​archetype/​
 +mvn install
 +</​code>​
 +
 +Afterwards the newly created archetype will be listed here and can be used to create a new project
 +<code bash>
 +mvn archetype:​generate
 +</​code>​
 +
 +Or only list locally installed archetypes:
 +<code bash>
 +mvn archetype:​generate -DarchetypeCatalog=local
 +</​code>​
 +
 +
 +See also: [[http://​maven.apache.org/​archetype/​maven-archetype-plugin/​advanced-usage.html|official documentation]]
 +
 +===== Export source code of dependencies =====
 +To get a directory with xxx-src.jar dependencies of your project do
 +
 +<code bash>
 +mvn dependency:​copy-dependencies -Dclassifier=sources -DincludeArtifactIds=jmapmatcher-core,​ariadne-core
 +
 +# ls target/​dependency
 +</​code>​
 +
 +
 +see [[http://​maven.apache.org/​plugins/​maven-dependency-plugin/​copy-dependencies-mojo.html]]
 +
 +===== Maven and J2EE =====
 +there are some useful Maven plugins for J2EE (and JBoss). Have a look at [[Maven J2EE]]
 +====== Useful Links ======
 +  * http://​www.java-tutorial.ch/​maven/​maven-release
 +  * http://​maven.apache.org/​plugins/​maven-release-plugin/​index.html
 +
  
maven.txt · Last modified: 2016/12/15 16:01 by mstraub