brainbaking/content/wiki/code/build/maven.md

18 KiB

+++ title = "maven" draft = false tags = [ "", "Users", "jefklak", "Downloads", "pages", "code", "build", "maven" ] date = "2013-06-05" +++

Maven2 Build stuff

properties guide: http://docs.codehaus.org/display/MAVENUSER/MavenPropertiesGuide

javascript files automatisch minify-en

	<profiles>
		<profile>
			<id>minify</id>
			<build>
				<plugins>
					<plugin>
						<groupId>org.apache.maven.plugins</groupId>
						<artifactId>maven-war-plugin</artifactId>
						<version>2.1.1</version>
						<configuration>
							<warSourceExcludes>**/js/**</warSourceExcludes>
						</configuration>
					</plugin>
					<plugin>
						<groupId>net.tqh.plugins</groupId>
						<artifactId>uglifyjs-maven-plugin</artifactId>
						<version>1.0</version>
						<configuration>
							<sourceDirectory>src/main/webapp/js</sourceDirectory>
							<outputDirectory>target/${project.name}-${version}/js</outputDirectory>
						</configuration>
						<executions>
							<execution>
								<phase>prepare-package</phase>
								<goals>
									<goal>uglify</goal>
								</goals>
							</execution>
						</executions>
					</plugin>
				</plugins>
			</build>
		</profile>
	</profiles>

Bron: https:*github.com/mishoo/UglifyJS - maven plugin gebruikt Rhino om dit uit te voeren. Kan ook met node uitgevoerd worden - gebruik bij voorkeur r.js (zie http:*requirejs.org/docs/optimization.html)

Argumenten als system property meegeven aan testen

Maven forkt by default dus -Dbla=blie gaat niet werken, dit is een property voor het maven java commando, maar niet voor de test zelf.

Oplossing: mvn test -DargLine######"-Dsystem.test.propertytest"

argLine gebruiken. Zie:

  1. http://www.cowtowncoder.com/blog/archives/2010/04/entry_385.html
  2. maven properties guide

Een single-deps jar mekan met maven assembly

 <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>fully.qualified.MainClass</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </plugin>
    </plugins>

En dan met mvn assembly:single uitvoeren. Dit maakt in uw target dir een file genaamd bla-1.0-SNAPSHOT-jar-with-dependencies.jar. java -jar [jar] werkt dan.

Een test jar maken met maven assembly

Met maven assembly kan je files packagen na het compileren van tests maar voor het runnen. Op die manier kunnen we dus bvb class files in een jar packagen (of resources in een zip). Daarna manueel installeren in de repository ofzoiets.

Plugin:

			<plugin>
				<artifactId>maven-assembly-plugin</artifactId>
				<version>2.2-beta-2</version>
				<executions>
					<execution>
						<id>create-test-dependency</id>
						<phase>process-test-classes</phase>
						<goals>
							<goal>single</goal>
						</goals>
						<configuration>
							<finalName>gatecontrol</finalName>
							<attach>false</attach>
							<descriptors>
								<descriptor>test-assembly.xml</descriptor>
							</descriptors>
						</configuration>
					</execution>
				</executions>
			</plugin>

De externe assembly file:

<assembly>
  <id>testjar</id>
  <formats>
    <format>jar</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  ```ets
    ```et
      <directory>target/test-classes</directory>
      <outputDirectory>/</outputDirectory>
      <includes>
        <include>**</include>
      </includes>
    </fileSet>
  </fileSets>
</assembly>

test jars zijn precies niet transitief qua dependencies?

Als je een test-jar (die dus op scope test staat) wil includen in je eigen assembly:single jar, kan je classifier tests gebruiken:

<dependency>
  <groupId>be.bla</groupId>
  <artifactId>bla-blie</artifactId>
  <scope>test</scope>
  <classifier>tests</classifier>
</dependency>

Dan wordt die test jar mee gepackaged, maar zijn dependencies blijbkaar niet?

Profiles en properties

activeByDefault

Zie http://java.dzone.com/articles/maven-profile-best-practices - nooit gebruiken! Waarom?

This flag activates the profile if no other profile is activated. Consequently, it will fail to activate the profile if any other profile is activated. This seems like a simple rule which would be hard to misunderstand, but in fact it's surprisingly easy to be fooled by its behaviour. When you run a multimodule build, the activeByDefault flag will fail to operate when any profile is activated, even if the profile is not defined in the module where the activeByDefault flag occurs.

In plaats daar van:

<profile id="nofoobar">
    <activation>
        <property>
            <name>!foo.bar</name>
        </property>
    </activation>
</profile>

JAXB generatie

Genereer endpoints vanaf WSDL

			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>jaxws-maven-plugin</artifactId>
				<version>${org.codehaus.mojo.jaxws.maven.plugin.version}</version>
				<executions>
					<execution>
						<goals>
							<goal>wsimport</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<wsdlDirectory>src/resources/wsdl</wsdlDirectory>
					<packageName>com.x.interfaces.ws</packageName>
					<sourceDestDir>${project.build.directory}/generated-sources/jaxws</sourceDestDir>
				</configuration>
				<dependencies>
					<dependency>
						<groupId>com.sun.xml.ws</groupId>
						<artifactId>jaxws-tools</artifactId>
						<version>${com.sun.xml.ws.jaxws.version}</version>
					</dependency>
				</dependencies>
			</plugin>

Zie http://rphgoossens.wordpress.com/2011/02/20/developing-a-contract-first-jax-ws-webservice/

Genereer de code met mvn jaxws:wsimport goal.

Genereer JAXB Java objecten vanaf XSD

Zelfde pincipe, andere goal:

			<plugin>
				<groupId>org.jvnet.jaxb2.maven2</groupId>
				<artifactId>maven-jaxb2-plugin</artifactId>
				<version>${org.jvnet.jaxb2.maven2.maven.jaxb2.plugin.version}</version>
				<executions>
					<execution>
						<id>crm_generation</id>
						<goals>
							<goal>generate</goal>
						</goals>
						<configuration>
							<schemaDirectory>src/main/schema</schemaDirectory>
							<schemaIncludes>
								<include>y.wsdl</include>
							</schemaIncludes>
							<schemaLanguage>WSDL</schemaLanguage>
							<generatePackage>com.x.interfaces</generatePackage>
						</configuration>
					</execution>
				</executions>
			</plugin>

Integratie met Ant

Maven kan ook ant tasks uitvoeren. Dit door ant code te embedden in de pom.xml op de volgende manier:

		   <plugin>
		    <groupId>org.apache.maven.plugins</groupId>
		    <artifactId>maven-antrun-plugin</artifactId>
		     
		    <configuration>
		     <tasks>
		      <property name######"target.war" value"bla.war" />
		      <property name######"zip.name" value"bla.zip" />
		      
		      <ant antfile######"build.xml" inheritRefs"true" inheritAll="true">
		      	<target name="buildZip" />
		      </ant>
		     </tasks>
		    </configuration>
		    
		    <goals>
		     <goal>install</goal>
		    </goals>
		   </plugin>

Binnen de configuration tag zit ant code, met de ant tag roep ik een externe build xml aan. Op die manier kan je dus een ant buildfile volledig naast een pom.xml maven2 file plaatsen, en properties doorgeven! Die ant task wordt uitgevoerd met het commando mvn antrun:run of bij bepaalde geconfigureerde goals.

Voorbeeld: http://maven.apache.org/plugins/maven-antrun-plugin/

Aan bepaalde phase hangen

Zie http://www.avajava.com/tutorials/lessons/what-are-the-phases-of-the-maven-default-lifecycle.html

Om nog rap een property file te kopiëren, best aan prapare-package phase hangen (maven 2.1+):

	 <profiles>
	   <profile>
	     <id>env</id>
	     <activation>
	     	<property>
	     		<name>env</name>
	     	</property>
	     </activation>
	     <build>
	       <plugins>
	         <plugin>
	           <artifactId>maven-antrun-plugin</artifactId>
	           <executions>
	             <execution>
	               <phase>prepare-package</phase>
	               <goals>
	                 <goal>run</goal>
	               </goals>
	               <configuration>
	                 <tasks>
						<echo message="Env property detected, copying ${env} to output directory..." />
                   		<copy file######"src/main/resources/template/env.${env}.properties" tofile"${project.build.outputDirectory}/env.properties"/>
	                 </tasks>
	               </configuration>
	             </execution>
	           </executions>
	         </plugin>
         </plugins>
        </build>
       </profile>
     </profiles>

Javadoc genereren

Deze plugin nodig:

		    <plugin>
		        <groupId>org.apache.maven.plugins</groupId>
		        <artifactId>maven-javadoc-plugin</artifactId>
		        <version>2.7</version>
		        <configuration>
		          <reportOutputDirectory>release/doc</reportOutputDirectory>
		          <destDir>javadoc</destDir>
		          <doctitle>API for ${project.name} ${project.version}</doctitle>
		          <windowtitle>API for ${project.name} ${project.version}</windowtitle>
		        </configuration>
		   </plugin>

output dir = ${reportOutputDirectory}/${destDir}

Voorbeeld: http://maven.apache.org/plugins/maven-javadoc-plugin/examples/output-configuration.html

Deployen met maven

Jetty integratie en auto-deploy

jetty run

Integratie met jetty en maven2: gebruik mvn jetty:run om automatisch de jetty server op te starten.

Het is ook mogelijk om die te laten scannen voor resource changes met scanIntervalSeconds - server start automatisch (normaal gezien...)

			<plugin>
				<groupId>org.mortbay.jetty</groupId>
				<artifactId>maven-jetty-plugin</artifactId>
				<version>6.1.26</version>
				<configuration>
					<stopPort>9966</stopPort>
					<stopKey>comeet</stopKey>
					<scanIntervalSeconds>5</scanIntervalSeconds>
					<connectors>
						<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
							<port>8089</port>
						</connector>
					</connectors>
				</configuration>
			</plugin>

Vanaf Jetty plugin 7 zijn packages hernoemd en zo, zie http://wiki.eclipse.org/Jetty en de migratie van 6->7->...9

Debug poort instellingen

Gebruikt MAVEN_OPTS JVM parameters (omdat het proces niet geforked wordt?): http://docs.codehaus.org/display/JETTY/Debugging+with+the+Maven+Jetty+Plugin+inside+Eclipse

-Xdebug -Xnoagent -Djava.compiler######NONE -Xrunjdwp:transportdt_socket,address######4000,servery,suspend=y
JNDI Datasources definiëren

Kan in webapp/WEB-INF/jetty-env.xml:

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-*Mort Bay Consulting*DTD Configure*EN" "http:*jetty.mortbay.org/configure.dtd">

<Configure class="org.mortbay.jetty.webapp.WebAppContext">

	<New id######"partnerwerkingDataSource" class"org.mortbay.jetty.plus.naming.Resource">
		<Arg>jdbc/partnerwerkingDataSource</Arg>
		<Arg>
			<New class="oracle.jdbc.pool.OracleDataSource">
				<Set name="URL">${database.url}</Set>
				<Set name="user">${database.user}</Set>
				<Set name="password">${database.password}</Set>
			</New>
		</Arg>
	</New>

</Configure>

wordt dan automatisch door jetty:run opgepikt.

auto-start bij integratie testen (failsafe plugin)

Als we aan bovenstaande plugin ook nog executions opgeven, start jetty automatisch bij pre-integration-test en stopt hij automatisch bij -post-integration-test:

				<executions>
					<execution>
						<id>start-jetty</id>
						<phase>pre-integration-test</phase>
						<goals>
							<goal>run</goal>
						</goals>
						<configuration>
							<scanIntervalSeconds>0</scanIntervalSeconds>
							<daemon>true</daemon>
						</configuration>
					</execution>
					<execution>
						<id>stop-jetty</id>
						<phase>post-integration-test</phase>
						<goals>
							<goal>stop</goal>
						</goals>
					</execution>
				</executions>

daemon moet op true staan omdat de bovenstaande plugin (jetty6) geen fork doet en dan natuurlijk geen testen gedraaid worden...

Tomcat deploy

Op verschillende omgevingen deployen kan door verschillende profielen aan te maken in de pom.xml file, en dan als env. parameter -Denv=[gewenste env value] de te deployen mee te geven:

	<profiles>
		<profile>
			<activation>
				<property>
					<name>env</name>
					<value>test</value>
				</property>
			</activation>

			<properties>
				<server.url>http://blatomcat:8888/manager</server.url>
				<server.username>user</server.username>
				<server.password>pass</server.password>
			</properties>
		</profile>
	</profiles>

Die properties die hierboven staan worden dan in deze plugin ingevuld:

			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>tomcat-maven-plugin</artifactId>
				<version>1.0-beta-1</version>
				<configuration>
					<url>${server.url}</url>
					<username>${server.username}</username>
					<password>${server.password}</password>
				</configuration>
			</plugin>

Uitvoeren met mvn tomcat:deploy [-Denv=x]

Voorbeelden en meer uitleg: http://mojo.codehaus.org/tomcat-maven-plugin/

War name veranderen

Staat default op ${project.build.finalName} wat neerkomt op artifactId-version.war.

Te veranderen door <warName>blar</warName> in <configuration/> te plaatsen in de maven-war-plugin.

Zonder .war ext. dus. Zie http://maven.apache.org/plugins/maven-war-plugin/war-mojo.html#warName

Jar source code downloaden

mvn dependency:sources

Ook mogelijk in de pom door per dependency downloadSources op true te zetten, of via de eclipse:eclipse goal plugin:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-eclipse-plugin</artifactId>
            <configuration>
                <downloadSources>true</downloadSources>
                <downloadJavadocs>true</downloadJavadocs>
                ... other stuff ...
            </configuration>
        </plugin>
    </plgins>
</build>

Vergeet niet dan als property -DdownloadSources=true mee te geven.

eclipse:eclipse genereert ook de .project file

Library dependencies worden daar automatisch aan toegevoegd, maar alles staat onder M2_REPO/org/.../bla.jar en Eclipse moet weten waar lokaal de repository staat. Zie ook http://maven.apache.org/guides/mini/guide-ide-eclipse.html - Dit commando uitvoeren & eclipse herstarten:

mvn -Declipse.workspace=<path-to-eclipse-workspace> eclipse:add-maven-repo

Automatisch source files encoden

Je kan met die plugin ook extra configuratie meegeven die de .java files qua encoding goed zet:

<additionalConfig>
	```
		<name>.settings/org.eclipse.core.resources.prefs</name>
			<content>
           				<![CDATA[eclipse.preferences.version######1${line.separator}encoding/<project>${project.build.sourceEncoding}${line.separator}]]>
			</content>
	```
</additionalConfig>

Dependency tree tonen

mvn dependency:tree > deptree.out

Produceert rommel in het volgend formaat:

[INFO] [dependency:tree {execution: default-cli}]
[INFO] be.--api:jar:2.21-SNAPSHOT
[INFO] +- be.-support:jar:7.21-SNAPSHOT:compile
[INFO] |  +- org.easytesting:fest-assert:jar:1.2:test (scope managed from compile)
[INFO] |  |  <br/>- org.easytesting:fest-util:jar:1.1:test
[INFO] |  +- com.thoughtworks.xstream:xstream:jar:1.3.1:compile
[INFO] |  |  <br/>- xpp3:xpp3_min:jar:1.1.4c:compile
[INFO] |  +- javax.ws.rs:jsr311-api:jar:1.1.1:compile
[INFO] |  +- org.objenesis:objenesis:jar:1.2:compile
[INFO] |  +- net.sf.ehcache:ehcache:jar:1.6.0:compile
[INFO] |  +- log4j:log4j:jar:1.2.15:compile
[INFO] |  |  <br/>- javax.mail:mail:jar:1.4:compile
[INFO] |  +- commons-codec:commons-codec:jar:1.3:compile
[INFO] |  +- jmimemagic:jmimemagic:jar:0.1.2:compile
[INFO] |  |  +- oro:oro:jar:2.0.8:compile
[INFO] |  |  <br/>- commons-logging:commons-logging:jar:1.1.1:compile (version managed from 1.0.4)
[INFO] |  +- commons-io:commons-io:jar:1.4:compile
[INFO] |  +- org.htmlcleaner:htmlcleaner:jar:2.1:compile
..

Een bepaalde test draaien via Maven

mvn test -Dtest=[testClass] -P [profile]

Waarbij profile het profiel is die de surefire plugin heeft - bijvoorbeeld:

<profile>
	<id>endtoend</id>
	<activation>
		<property>
			<name>endtoend</name>
		</property>
	</activation>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<executions>
					<execution>
						<phase>integration-test</phase>
						<goals>
							<goal>test</goal>
						</goals>
						<configuration>
							<testFailureIgnore>true</testFailureIgnore>
							<skip>false</skip>
							<argLine>-Xms128M -Xmx512M -XX:MaxPermSize=512M</argLine>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</profile>

Als een bepaalde jar nog deployed moet worden (naar Jetty bvb) voor het runnen van de test (scenario testen zoals selenium en webdriver), moet de install in plaats van test goal uitgevoerd worden.

Het kan ook zijn dat nog zaken geïnstalleerd moeten worden in de lokale Maven repository (het root project) -> eerst mvn clean install op het root project doen (voor vac is dit zo). Dit is omdat het endtoend project daarop afhangt, en de compile dan faalt.

Een jar manueel in de repository installeren

Gebruik het volgende commando:

mvn install:install-file -Dfile######x.jar -DgroupIdcom.group -DartifactId######jarName -Dversion1.0.0 -Dpackaging=jar

Wens je dit in de remote repository te installeren, gebruik dan mvn deploy:deploy-file met als extra parameter de url van de repository via de -Durl=repoUrl optie.

De maven java compiler versie goed zetten

Gebeurt in een plugin in de build fase:

	<build>
		<finalName>test</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<encoding>UTF-8</encoding>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>