Saturday, 21 January 2012

Unit tests with embeded tomcat artifacts

In the 7.x releases of Apache Tomcat, some maven artifacts are now published which include a nice and fluent embeded api to run a Tomcat instance.

So it's a nice opportunity to use it writing units to test servlets, rest api etc..
But until 7.0.25 it was only possible to do it with using a barcoding port which can cause some issues on ci servers where you are not sure ports are not used by something else running.

I have personally sended a RFC to ITEF to have port allocation for only my personal use on my birthday year or zip code port but strangely this RFC was never approved :-).

Now you can use the java ServerSocket port 0 feature to use any free port available on the machine.
It has been fixed with the issue 52028.

So now you can write a unit test as it (here a test with a REST service provided by Apache CXF).



@Before
public void startTomcat()
throws Exception
{
tomcat = new Tomcat();
tomcat.setBaseDir( System.getProperty( "java.io.tmpdir" ) );
tomcat.setPort( 0 );

Context context = tomcat.addContext( "", System.getProperty( "java.io.tmpdir" ) );

A context param in your web.xml:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:META-INF/spring-context.xml</param-value>
</context-param>

In the code

ApplicationParameter applicationParameter = new ApplicationParameter();
applicationParameter.setName( "contextConfigLocation" );
applicationParameter.setValue( "classpath*:META-INF/spring-context.xml" );
context.addApplicationParameter( applicationParameter );

A listener class in your web.xml:

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

In the code

context.addApplicationListener( ContextLoaderListener.class.getName() );

CXF servlet declaration in your web.xml:

<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/restServices/*</url-pattern>
</servlet-mapping>

In the code:

tomcat.addServlet( context, "cxf", new CXFServlet() );
context.addServletMapping( "/restServices/*", "cxf" );

tomcat.start();

port = tomcat.getConnector().getLocalPort();

System.out.println("Tomcat started on port:"+port);
}



So now you can test/consume you REST services on localhost with the port.

Don't miss to shutdown the tomcat instance on tearDown or @After

@After
public void stopTomcat()
throws Exception
{
tomcat.stop();
}


If you use Maven you need the following dependencies:

<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<scope>test</scope>
<version>7.0.25</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-juli</artifactId>
<scope>test</scope>
<version>7.0.25</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
<scope>test</scope>
<version>7.0.25</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<scope>test</scope>
<version>7.0.25</version>
</dependency>


As samples talks more than long docs ("Code talks, bullshit walks" :-) ).
The tomcat maven archetype has been improved with a sample. (see previous post)

Have Fun!

Friday, 13 January 2012

Tomcat Maven plugin archetype. Sample talks more than long documentation :-)

As code sample talks more than long and borying documentation (or maybe because I don't like to write too long documentation :-) ), I have writen an archetype for the Apache Tomcat Maven Plugin.

Some features describe in this post are now implemented.

As it's not yet released but soon !, just use :

mvn archetype:generate \
-DarchetypeGroupId=org.apache.tomcat.maven \
-DarchetypeArtifactId=tomcat-maven-archetype \
-DarchetypeVersion=2.0-SNAPSHOT \
-DarchetypeRepository=https://repository.apache.org/content/repositories/snapshots/
....
[INFO] Using property: groupId = org.apache.tomcat.maven
Define value for property 'artifactId': : tomcat-sample (project will be created in ./tomcat-sample )
...
cd tomcat-sample


You can run your webapp with: mvn tomcat6:run or mvn tomcat7:run (depends on tomcat version you want)
And hit your browser to http://localhost:9090 and you will use a very complicated hello world webapp sample :-)

Now you can try: mvn clean install .
You will see a selenium test running (by default firefox), use -Pchrome for using chrome should work too with -Piexplore (not tested :-) ).

Note you have now an executable war.
Try it !

cd basic-webapp-exec/target/
java -jar basic-webapp-exec-1.0-SNAPSHOT-war-exec.jar -httpPort 9191


And hit your browser to http://localhost:9191.
So you have a tomcat7 running our fabulous application and without installing nothing !

More details on the project



This archetype build a simple project with some maven modules. IMHO it's nice layout to use.

basic-api (service interface)
basic-api-impl (service default impl)
basic-webapp (our webapp module)
basic-webapp-exec (module to generated executable war)
basic-webapp-it (module to run selenium tests with generated war)


The application is exposing a REST service called HelloService (in basic-api module)


@Path( "HelloService" )
public interface HelloService
{
@Path( "sayHello/{who}" )
@GET
@Produces( { MediaType.TEXT_PLAIN } )
String sayHello( @PathParam( "who" ) String who );
}


The implementation is in the module basic-api-impl.
Note we use Apache Cxf to provide REST services (for more details have a look at the various spring files).

The webapp is a simple page based on jquery and twitter bootstrap.

So have fun !

Saturday, 26 November 2011

From a pull request to a jira issue

After the generate a patch and attach it to a jira issue, it's now the time to have a tool to create an issue from a patch request (the current implementation works only for github pull request).

So the Patch Tracker plugin has now a new goal called to-issue. This goal will read a github pull request and create an issue in your issue tracker (currently only supported for jira).

It's simple :-).
As sample see pull request : https://github.com/jenkinsci/jenkins/pull/320 and the created issue in jira: https://issues.jenkins-ci.org/browse/JENKINS-11883
I have just used the cli:

mvn patch-tracker:to-issue -Dpatch.request.id=320 -B

For easy configuration see the properties in the jenkins pom.

<project.patchManagement.system>github</project.patchManagement.system>
<patch.request.organisation>jenkinsci</patch.request.organisation>
<patch.request.repository>jenkins</patch.request.repository>
<project.patchManagement.url>https://api.github.com</project.patchManagement.url>

<patch.tracker.serverId>jenkins-jira</patch.tracker.serverId>


entry in settings:

<server>
<id>jenkins-jira</id>
<username>uid</username>
<password>password</password>
</server>


And that's it :-).

BTW if you need more features, patch (or pull requests) are welcome.

This maven plugin is in the maven sandbox @asf and not released, so if you want to try it you must have asf maven snapshot repo in your settings or buid it manually.
Sources are here:

  • https://github.com/apache/maven-sandbox (path plugins/maven-patch-tracker-plugin) yup no sparse checkout with git :P

  • http://svn.apache.org/repos/asf/maven/sandbox/trunk/plugins/maven-patch-tracker-plugin/



Some docs has been started here http://maven.apache.org/plugins/maven-patch-tracker-plugin (maybe not yet in sync so wait a bit)

Have fun !

Monday, 21 November 2011

Life is too short to waste time uploading a patch or Maven Patch Tracker plugin

Life is too short and you don't want to waste time contributing to a project (creating a patch, a entry in the jira issue tracker then upload the patch).
So the Maven Patch Tracker plugin is for you !



You will be able with a maven plugin to do all of this in one command line !
Without any configuration you have to write :

mvn patch-tracker:create
-Dpatch.summary="foo summary"
-Dpatch.serverUrl=http://localhost:8080/browse/MNG -B
-Dpatch.user=uid -Dpatch.password=pwd


If you find that boring or too long no problem, there is a solution for that (yes good developer are lasy developers they use tool to automate tasks :-) ).
So configure you pom, with the issue tracker id

<issueManagement>
<system>jira</system>
<url>http://host:ip/browse/projectKey</url>
</issueManagement>


Add a server entry in you settings.xml


<server>
<id>jira-maven</id>
<username>olamy</username>
<password>very complicated password for paranoiac security folks</password>
</server>


Reference this jira server in your pom:


<properties>
....
<patch.tracker.serverId>jira-maven</patch.tracker.serverId>
....
</properties>


Et voilĂ , just run and save fingers:

mvn patch-tracker:create -Dpatch.summary="foo summary" -B


NOTE: without -B the plugin will use a prompt mode to ask you confirmation on the values

An other mojo called update can add/update an issue with an other patch:

mvn patch-tracker:update -Dpatch.description="update of the issue with an other patch" -Dpatch.patchId=MNG-5203 -B

This command will update the issue MNG-5203 with an other patch.

NOTE: currently only jira is supported

The plugin will use the configured scm client configured tru your scm url to generate the patch/diff file.
So your project is configured with svn but for some reasons you use git svn.
No problem add the parameter: -Dscm.providerType=git

Other improvement I think: load the patch to review board.

Something else ?
Ideas and patches are welcome :-)

You can test it using the snapshot repo: https://repository.apache.org/content/groups/snapshots-group/ or build it yourself: http://svn.apache.org/repos/asf/maven/sandbox/trunk/plugins/maven-patch-tracker-plugin/

Have Fun and good hacking!

Wednesday, 26 October 2011

Archiva 1.4-M1 released

The Apache Archiva 1.4-M1 has been released.
Some nice features added:

  • It is now possible to create a staging repository for any managed repository and later merge the results.

  • You can now use REST services to control Archiva or search for artifacts. See REST Services for more information.

  • Database storage for repository metadata has been replaced with a JCR repository based on Apache Jackrabbit by default (other options such as a flat-file storage may be made available in the future).

  • The search interface provide now the capability to search on OSGI metadata (based on the update of the Apache Maven Indexer library).

  • You can now download Maven index content from remote repositories to include artifacts which are not present locally in your search results



Full release notes available here: http://archiva.apache.org/docs/1.4-M1/release-notes.html

Download page: http://archiva.apache.org/download.html

Have Fun and some nice new features will come soon :-)

Apache Archiva, Archiva, Apache Maven, Maven, Apache are trademarks of The Apache Software Foundation.

Friday, 21 October 2011

Apache Tomcat Maven Plugin Features

Recently I posted some informations regarding the move from codehaus to ASF of the Tomcat Maven plugin and about the support of tomcat7 in trunk code.

So now in this post, I'd like to talk of the features I prefer.

Run goal in multi modules with Maven3


Usually with Apache Maven, your application code is splitted in some modules to respect the Separation Of Concern paradigm.
Something like :

root
pom.xml
foo-api
pom.xml
foo-impl
pom.xml
foo-webapp
pom.xml

So to test your webapp module you have to install all other modules first which is time/io consuming.
Now with Apache Maven 3 and the Tomcat Maven Plugin (from Codehaus version 1.1 or now the 2.0-SNAPSHOT from Apache), you can simple use the goal run from the root directory and the plugin will see various modules build output and include those automatically in the embeded tomcat in the webapp class loader.

Build a standalone executable war/jar


You can now build a standalone jar which will contains Apache Tomcat needed classes and your wars.
See documentation.
This will produce a similar jar as for the Jenkins distribution.
At the end you will be able to run the produced jar with a simple:

java -jar yourjar


And that's will start Apache Tomcat without need of any installations !

NOTE: it's very recent feature based on my need :-)
So all issues/feedback or some RFE are really welcome!

Have Fun!
--
Olivier



Apache Maven, Maven, Apache Tomcat, Tomcat, Apache are trademarks of The Apache Software Foundation.

Sunday, 9 October 2011

Tomcat Maven Plugin now supports tomcat7

Hello,
After moving the Tomcat Maven Plugin from Codehaus to Apache in the Tomcat land (see previous post), I have found some time to start hacking on it.
The first feature I wanted to add was support of Apache Tomcat 7.x. So it's now implemented in trunk.
You can test it see how to configure that in your poms: http://tomcat.apache.org/maven-plugin-2.0-SNAPSHOT/snapshot-test.html.

NOTE the important changes with the move to Apache and the support of Apache Tomcat 7.x:

  • You know have two "mojos": tomcat6:* and tomcat7:$

  • The groupId is now: org.apache.tomcat.maven

  • All goals are not supported: I will work on that :-)



So you can know use tomcat7 in embedded way within your Apache Maven build with: tomcat7:run.

Feel free to report any issues: https://issues.apache.org/jira/browse/MTOMCAT

Have Fun!

Apache Maven, Maven, Apache Tomcat, Tomcat, Apache are trademarks of The Apache Software Foundation.