More Apache Maven Best Practices

44
More Apache Maven Best Practices 1 Brett Porter - [email protected] 1

description

Second presentation on a collection of best practices given at ApacheCon US 2008

Transcript of More Apache Maven Best Practices

Page 1: More Apache Maven Best Practices

More Apache MavenBest Practices

1

Brett Porter - [email protected]

1

Page 2: More Apache Maven Best Practices

More Apache MavenBest Practices

1

Brett Porter - [email protected]

1

Page 3: More Apache Maven Best Practices

Welcome Back

2

This time last year...Apache Maven Best PracticesSlides are available online• http://blogs.exist.com/bporter/

But wait, there’s more!

2

Page 4: More Apache Maven Best Practices

Recap

3

3

Page 5: More Apache Maven Best Practices

EnvironmentSet up your environment in advanceA repository manager is a must

4

4

Page 6: More Apache Maven Best Practices

Keep the POM simpleWrite your build like you write your code

Keep it Simple

5

5

Page 7: More Apache Maven Best Practices

Keep it PortableKeep the build portableAvoid hard codingMake artifacts portable and minimize resource filtering

6

6

Page 8: More Apache Maven Best Practices

Keep it ReproducibleBefore releasing, make sure the build is reproducibleFirst, it must be portableLock downversionsLock downenvironmentalvariations

7

7

Page 9: More Apache Maven Best Practices

The Enforcer

8

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>1.0-alpha-4</version> <executions> <execution> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <requirePluginVersions> <banLatest>true</banLatest> <banRelease>true</banRelease> </requirePluginVersions> </rules> </configuration> ...

8

Page 10: More Apache Maven Best Practices

The Enforcer

9

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>1.0-alpha-4</version> <executions> <execution> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <requirePluginVersions> <banLatest>true</banLatest> <banRelease>true</banRelease> </requirePluginVersions> </rules> </configuration> ...

9

Page 11: More Apache Maven Best Practices

The Enforcer

9

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>1.0-alpha-4</version> <executions> <execution> <goals> <goal>enforce</goal> </goals> <configuration> <rules> <requirePluginVersions> <banLatest>true</banLatest> <banRelease>true</banRelease> </requirePluginVersions> </rules> </configuration> ...

<rules> <requirePluginVersions> <banLatest>true</banLatest> <banRelease>true</banRelease> </requirePluginVersions></rules>

9

Page 12: More Apache Maven Best Practices

The EnforcerHelp ensure build will be reproducibleBased on rules

force specific plugin versionsban snapshotsglobal exclusionsforce Maven/Java/OS versioncan write your own

10

10

Page 13: More Apache Maven Best Practices

Release Early and OftenMake sure releases are quick, easy, and automatedUse the Maven/Continuum tools to help

11

11

Page 14: More Apache Maven Best Practices

And Now...Dependency managementIntegration testingMaven sites and reportingPlugin development

12

12

Page 15: More Apache Maven Best Practices

Dependency Management

13

13

Page 16: More Apache Maven Best Practices

Dependencies EverywhereTransitive dependencies are very convenient...

... until you get bitten by bad metadataYou wind up witha tree of artifactsyou may or maynot be using

14

14

Page 17: More Apache Maven Best Practices

Troubleshoot Dependenciesmvn dependency:tree

or equivalent Eclipse integration

15

[INFO] org.example.maven:example-webapp:war:1.2-SNAPSHOT[INFO] +- junit:junit:jar:3.8.1:test[INFO] +- org.apache.struts:struts2-core:jar:2.0.5:compile[INFO] | +- opensymphony:xwork:jar:2.0.0:compile[INFO] | +- org.apache.struts:struts2-api:jar:2.0.5:compile[INFO] | +- freemarker:freemarker:jar:2.3.8:compile[INFO] | +- ognl:ognl:jar:2.6.9:compile[INFO] | \- commons-logging:commons-logging:jar:1.0.4:compile[INFO] +- org.apache.struts:struts2-sitemesh-plugin:jar:2.0.5:compile[INFO] | \- opensymphony:sitemesh:jar:2.2.1:compile[INFO] +- org.apache.struts:struts2-spring-plugin:jar:2.0.5:compile[INFO] | +- org.springframework:spring-beans:jar:2.0.1:compile[INFO] | +- org.springframework:spring-core:jar:2.0.1:compile[INFO] | +- org.springframework:spring-context:jar:2.0.1:compile[INFO] | | \- aopalliance:aopalliance:jar:1.0:compile[INFO] | \- org.springframework:spring-web:jar:2.0.1:compile[INFO] +- javax.servlet:servlet-api:jar:2.4:provided[INFO] +- javax.servlet:jsp-api:jar:2.0:provided[INFO] +- commons-fileupload:commons-fileupload:jar:1.1.1:compile[INFO] | \- commons-io:commons-io:jar:1.1:compile[INFO] +- uk.ltd.getahead:dwr:jar:1.1-beta-3:compile[INFO] +- org.example.maven:example-model:jar:1.2-SNAPSHOT:compile[INFO] \- org.example.maven:example-manager:jar:1.2-SNAPSHOT:compile

15

Page 18: More Apache Maven Best Practices

Troubleshoot Dependenciesmvn dependency:tree

or equivalent Eclipse integration

15

[INFO] org.example.maven:example-webapp:war:1.2-SNAPSHOT[INFO] +- junit:junit:jar:3.8.1:test[INFO] +- org.apache.struts:struts2-core:jar:2.0.5:compile[INFO] | +- opensymphony:xwork:jar:2.0.0:compile[INFO] | +- org.apache.struts:struts2-api:jar:2.0.5:compile[INFO] | +- freemarker:freemarker:jar:2.3.8:compile[INFO] | +- ognl:ognl:jar:2.6.9:compile[INFO] | \- commons-logging:commons-logging:jar:1.0.4:compile[INFO] +- org.apache.struts:struts2-sitemesh-plugin:jar:2.0.5:compile[INFO] | \- opensymphony:sitemesh:jar:2.2.1:compile[INFO] +- org.apache.struts:struts2-spring-plugin:jar:2.0.5:compile[INFO] | +- org.springframework:spring-beans:jar:2.0.1:compile[INFO] | +- org.springframework:spring-core:jar:2.0.1:compile[INFO] | +- org.springframework:spring-context:jar:2.0.1:compile[INFO] | | \- aopalliance:aopalliance:jar:1.0:compile[INFO] | \- org.springframework:spring-web:jar:2.0.1:compile[INFO] +- javax.servlet:servlet-api:jar:2.4:provided[INFO] +- javax.servlet:jsp-api:jar:2.0:provided[INFO] +- commons-fileupload:commons-fileupload:jar:1.1.1:compile[INFO] | \- commons-io:commons-io:jar:1.1:compile[INFO] +- uk.ltd.getahead:dwr:jar:1.1-beta-3:compile[INFO] +- org.example.maven:example-model:jar:1.2-SNAPSHOT:compile[INFO] \- org.example.maven:example-manager:jar:1.2-SNAPSHOT:compile

<exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion></exclusions>

15

Page 19: More Apache Maven Best Practices

Troubleshoot Dependenciesmvn dependency:tree

or equivalent Eclipse integration

15

[INFO] org.example.maven:example-webapp:war:1.2-SNAPSHOT[INFO] +- junit:junit:jar:3.8.1:test[INFO] +- org.apache.struts:struts2-core:jar:2.0.5:compile[INFO] | +- opensymphony:xwork:jar:2.0.0:compile[INFO] | +- org.apache.struts:struts2-api:jar:2.0.5:compile[INFO] | +- freemarker:freemarker:jar:2.3.8:compile[INFO] | +- ognl:ognl:jar:2.6.9:compile[INFO] | \- commons-logging:commons-logging:jar:1.0.4:compile[INFO] +- org.apache.struts:struts2-sitemesh-plugin:jar:2.0.5:compile[INFO] | \- opensymphony:sitemesh:jar:2.2.1:compile[INFO] +- org.apache.struts:struts2-spring-plugin:jar:2.0.5:compile[INFO] | +- org.springframework:spring-beans:jar:2.0.1:compile[INFO] | +- org.springframework:spring-core:jar:2.0.1:compile[INFO] | +- org.springframework:spring-context:jar:2.0.1:compile[INFO] | | \- aopalliance:aopalliance:jar:1.0:compile[INFO] | \- org.springframework:spring-web:jar:2.0.1:compile[INFO] +- javax.servlet:servlet-api:jar:2.4:provided[INFO] +- javax.servlet:jsp-api:jar:2.0:provided[INFO] +- commons-fileupload:commons-fileupload:jar:1.1.1:compile[INFO] | \- commons-io:commons-io:jar:1.1:compile[INFO] +- uk.ltd.getahead:dwr:jar:1.1-beta-3:compile[INFO] +- org.example.maven:example-model:jar:1.2-SNAPSHOT:compile[INFO] \- org.example.maven:example-manager:jar:1.2-SNAPSHOT:compile

<rules> <bannedDependencies> <excludes> <exclude>commons-logging:commons-logging</exclude> </excludes> </bannedDependencies></rules>

<exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion></exclusions>

15

Page 20: More Apache Maven Best Practices

Don’t Add to the ProblemBe careful with your own dependencies

Specify only what you needSpecify scopeUse optional if you must

Use dependencyManagement to:coerce Maven to use a particular versionenforce consistency within a project

16

16

Page 21: More Apache Maven Best Practices

Only What You Needmvn dependency:analyze

find out what you’re using but not declaringfind out what you’re declaring but not using

17

[WARNING] Used undeclared dependencies found:[WARNING] opensymphony:xwork:jar:2.0.0:compile[WARNING] Unused declared dependencies found:[WARNING] org.apache.struts:struts2-spring-plugin:jar:2.0.5:compile[WARNING] javax.servlet:jsp-api:jar:2.0:provided[WARNING] commons-fileupload:commons-fileupload:jar:1.1.1:compile[WARNING] javax.servlet:servlet-api:jar:2.4:provided[WARNING] org.apache.struts:struts2-core:jar:2.0.5:compile[WARNING] org.apache.struts:struts2-sitemesh-plugin:jar:2.0.5:compile[WARNING] uk.ltd.getahead:dwr:jar:1.1-beta-3:compile

17

Page 22: More Apache Maven Best Practices

Integration Testing

18

18

Page 23: More Apache Maven Best Practices

“Integration” TestingCovers any type of testing beyond unit

integration testingfunctional testing, etc.

Unfortunately, an afterthought in Maven 2.0.x

at least in the lifecycle

19

19

Page 24: More Apache Maven Best Practices

PatternsTests in a separate moduleTests in same projectUse of profiles applies to botheg. Maven

Plugin ITs are in the pluginCore ITs are separate

20

20

Page 25: More Apache Maven Best Practices

Separate ProjectMost common patternIf you are testing multiple modules, use a separate project

21

21

Page 26: More Apache Maven Best Practices

Separate Projectcreate a parallel moduleuse the regular src/test/java directoryadd a dependency on the module(s) being testedenable the module in a profile

if a profile is necessary

22

22

Page 27: More Apache Maven Best Practices

Separate Projectcreate a parallel moduleuse the regular src/test/java directoryadd a dependency on the module(s) being testedenable the module in a profile

if a profile is necessary

22

<profile> <id>run-its</id> <modules> <module>integration-tests</module> </modules></profile>

22

Page 28: More Apache Maven Best Practices

Testing in the Same ProjectGood for framework examples and small projectsTwo alternatives

separate directory, redeclare both compilation and test plugins• eg src/it

same test directory, test exclusions• eg **/selenium/**

Include the tests in a profile

23

23

Page 29: More Apache Maven Best Practices

Example: Selenium

24

24

Page 30: More Apache Maven Best Practices

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <excludes> <exclude>**/selenium/**</exclude> </excludes> </configuration></plugin>

Example: Selenium

24

24

Page 31: More Apache Maven Best Practices

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <excludes> <exclude>**/selenium/**</exclude> </excludes> </configuration></plugin>

<profile> <id>selenium</id> <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> <includes> <include>**/selenium/**/*Test.java</include> </includes> </configuration> </execution> </executions> </plugin> </plugins> </build></profile>

Example: Selenium

24

24

Page 32: More Apache Maven Best Practices

<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <excludes> <exclude>**/selenium/**</exclude> </excludes> </configuration></plugin>

<profile> <id>selenium</id> <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> <includes> <include>**/selenium/**/*Test.java</include> </includes> </configuration> </execution> </executions> </plugin> </plugins> </build></profile>

Example: Selenium

24

<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>selenium-maven-plugin</artifactId> <version>1.0-beta-1</version> <executions> <execution> <phase>pre-integration-test</phase> <goals> <goal>start-server</goal> </goals> </execution> </executions> <configuration> <background>true</background> </configuration></plugin>

24

Page 33: More Apache Maven Best Practices

Maven Sites and Reporting

25

25

Page 34: More Apache Maven Best Practices

Two technologiesreportingrendering

They aren’t the same!They work together

... but can be used independently

... and should be for different tasks

Maven Sites

26

26

Page 35: More Apache Maven Best Practices

Site TipsAvoid reports on documentation sites

some minimal project reports, like mailing lists, source repository may be relevant

Use site inheritanceUse versioning in the URL

for version specific usage documentationespecially for developer reference site

Include release notes in the versioned usage documentation

27

27

Page 36: More Apache Maven Best Practices

Set up what you’ll use!don't create reports with thousands of issues

It won’t be used if...too much informationirrelevant information

Don’t settle for thedefault settings

Report Tips

28

28

Page 37: More Apache Maven Best Practices

Report TipsUse active checks, not passive reports

fail the build!Use profiles if they are time consuming

run them in continuous integrationdevelopers can use IDE integration

Have a centralized location to deploy reports

visualize problems, and errors under the build failure threshold

29

29

Page 38: More Apache Maven Best Practices

Plugin Development

30

30

Page 39: More Apache Maven Best Practices

Don’t Fear ScriptingSometimes it is easier to use a script for short, one-off, customizations

antrun pluginjruby, groovy plugin, etc.

If you might use it twice, consider writing a plugin

31

31

Page 40: More Apache Maven Best Practices

Plugin DevelopmentIt isn’t the big deal you think it isCan be written in Java, Ruby, Groovy, ...Plugins are as easy to write as any other module

though they still lack the quick “run and test” scenario of most scripting solutions

32

32

Page 41: More Apache Maven Best Practices

Plugin TipsWrite functionality in components, with the Mojo as a “wrapper”

easier to test and reusethe theory of mojos as pojos isn’t as realistic due to the current wiring

Minimize Maven API dependencies and component exposure

eg, use maven-artifact, not maven-coreMinimize dependencies in general

all builds have to download them!33

33

Page 42: More Apache Maven Best Practices

Final WordDo as we say...

... but not as we doMaven fails to implement many of these practices in various projects

We learned the hard way!It can be really hard to find time to go back and fix it later

34

34

Page 43: More Apache Maven Best Practices

Questions?

35

Brett Porter - [email protected]

35

Page 44: More Apache Maven Best Practices

Questions?

35

Brett Porter - [email protected]

35