Open source involvement
[ vmassol ] 09:40, Wednesday, 24 October 2007

I was invited to speak about the XWiki platform at the Valtech Days 2007. It was a very interesting event, focused on Agility. I presented XWiki a bit differently than what we are used to. Whereas XWiki was an Enterprise Wiki not long ago, it's really now a development platform for writing collaborative web applications (and more specifically applications focused on content). The presentation focused on the platform and what type of applications it's possible to build on top of it.

My slides are available online.

[ vmassol ] 00:19, Saturday, 6 October 2007

Ludovic and I are in the Silicon Valley between the 6th of October to the 12th of October 2007. We've been kindly invited by Google for the Google Summer of Code Mentor Summit (Thanks Google!) and we're taking that occasion to spend some time in the valley to meet the maximum number of people and talk about wikis and XWiki.

If you're interested to meet up register on the Facebook event.

We have also organized a joint XWiki and Maven tech meetup on the 9th of October, at Terracotta. Indeed Terracotta has been extermely kind not only to lend us a room but also to cater for some pizzas and snacks :) Thanks Terraccotta!

The address is:

Terracotta Inc.
650 Townsend St. Suite 325
San Francisco, CA 94103 USA
+1 415 738 4059

Jason Van Zyl, creator of Maven will be there too!

I hope to see a lot of you there!

[ vmassol ] 18:53, Saturday, 5 May 2007

My friend Jason Van Zyl has started Sonatype, a new company focused on Maven for the Enterprise and providing support, training and consulting for Maven. He's been joined by several talented Maven committers (John Casey, Kenney Westerhof, Andrew Williams, Eric Redmond and Eirik Bjørsnøs) which make their team one of the most knowledgable team on the Maven topic on the planet. Knowing Jason's generosity and dedication to Maven you can be sure that this is the best possible move for the Maven project and it's great for the Maven ecosystem at large. As a proof, Sonatype has already delivered a great (and free) Maven book.

I'm also happy to report that XWiki (the company and open source project I work for) is a Sonatype Partner. I'd love to see Maven products built on top of XWiki. I think XWiki's flexibility makes it an ideal platform for building those products and at the same time empowering them with collaborative features. In the near future I'll work closely with Jason and his team to integrate XWiki and Maven and hopefully we'll see some cool things out of this.

Well done guys and long live Sonatype!

[ vmassol ] 10:05, Thursday, 27 April 2006

Our Maven2 is book is officially out. Here's the marketing pitch:

"Better Builds with Maven”"

  • is a comprehensive 'How-to' guide for use with Maven 2.0.4 and later
  • is available free of charge and includes supporting sample code
  • covers how to use Maven 2.0 to better manage the build, test and release cycles associated with software development
  • is written for beginning and intermediate Maven users
  • is authored by Maven experts
  • Jason Van Zyl, Chief Architect and founder of Maven
  • Vincent Massol, author of "Maven: a Developers Notebook"
  • with chapters and key content and code contributions from leading Apache Software Foundation Maven Project members: Brett Porter, John Casey and Carlos Sanchez.
  • is published by Mergere, Inc

Content Includes:

  • An introduction to Maven 2.0
  • Creating, compiling and packaging your first project
  • Best practices and real-world examples
  • Creating J2EE builds and using J2EE models
  • Extending builds through plugins
  • Monitoring source code, testing, dependencies and releases
  • Leveraging repositories, Continuum for continuous integration and transitive dependencies
  • Converting existing Ant builds to Maven

Download a free copy at http://library.mergere.com.

I hope this book will help boost Maven2's adoption.

[ vmassol ] 12:09, Thursday, 16 February 2006

I've been asking myself the following 2 questions for about 5 years now: am I good at managing an open source project and making it successful? How can I improve?

I guess it depends on the definiton of "successful". My definition of a successful OSS project is:

  1. A project that has a big user community and mindshare
  2. A project that has a big development community (i.e. committers and contributors). That is the development mailing list should be quite active with lots of contributions, improvements, ideas being discussed. All those submitted by a large number of different persons
  3. A project that lives on if the initial or main contributor leaves the project

If we go by point 1, I think that the main 2 projects I have started (Cactus and Cargo) are not doing too bad. Cargo is still new but it seems to be on track and its user base is growing very quickly.

However on points 2 and 3, I'm not so sure I'm doing well. Mind you, Cargo has quite a lot of committers (growing every week!) and they're all doing a great job. I'm just thinking about the level beyond (look at the activity on the Maven project, Spring or other projects as an example of what I mean). Cactus is a bit different as it's now a mature project, so let's focus on Cargo. Of course it could be that these project domains are narrow and thus do not interest lots of developers. This is probably true but I don't think this is the only issue. I have the feeling that some of the reasons could be:

  • Unconsciously I may be "driving" the project too much. For example if someone proposes something, I'm probably going to argue with this person in order that it fits Cargo's quality crtieria and direction. It's possible that by doing this, I'm cutting some creativity from this person and thus even if he implements the thing, maybe he'll feel it has not completely come from him and won't identify with it enough to maintain and improve it in the future. Or maybe by arguing I'm just making the life of that person harder and as this person is doing this in the little free time he has, he may not pursue it...
  • Maybe I'm answering emails asked on the list too fast, thus preventing any other contributor to answer. This is setting the tone and maybe as a consequence people are expecting me to answer all emails. Everyone "knows" that I'll answer them anyway...
  • The same could be said for applying patches and implementing things. I think this is less true though as I also have a day job and there are lots of JIRA issues accumulating in the Cargo project for example, so there's room for takers
  • Documentation of Cargo seems good at first glance (although I know there are lots of holes). I wonder if, as a consequence Cargo users who look at the web site think that Cargo is stable, mature, etc and thus may feel less inclined to participate. Who wants to participate to a project that is mostly "done"! (Note: For those reading this and interested in Cargo, it is far from true and there are tons of things to design and implement!)

On the other hand, I feel that not doing any one of these points will hamper Cargo's user adoption...

Or maybe I'm completely wrong on all points above and this is just me fantasizing!

I'm really interested to know what you think and if this is something other OSS committers/contributors have noticed too. I've given the example of Cargo but really this is a general discussion on how to best manage an OSS project.

[ vmassol ] 21:05, Tuesday, 10 January 2006

Cargo is a container-manipulation library that allows configuring, starting and stopping containers. It also deploys modules to those containers. Version 0.7 has been released last week along with version 0.1 of a Maven2 plugin. The nice thing about Cargo is that it provides a uniform API across all containers and it has several end user APIs: a Java API, Ant tasks, a Maven 1 plugin, a Maven 2 plugin, a Netbeans plugin, an IntelliJ IDEA plugin, etc. You can use any of those extensions with all the supported containers.

Note: Adding a new container is very easy and you only have to implement a small interface and your container will be made available automatically through all the existing end user APIs - Make sure to contact us if you're interested in adding a new container support.

I'd like to quickly demonstrate how to use the new Maven 2 plugin on 2 use cases (more samples can be found here):

  • Use case 1: Deploying a WAR to Tomcat 5.x and starting the container
  • Use case 2: In-place webapp deployment with Jetty 4.x

Deploying a WAR and starting Tomcat 5.x

Create a Maven 2 project and put the following configuration in your pom.xml file:

[...] <packaging>war</packaging> [...] <build> <plugins> <plugin> <groupId>org.codehaus.cargo</groupId> <artifactId>cargo-maven2-plugin</artifactId> <configuration> <container> <containerId>tomcat5x</containerId> <home>c:/apps/jakarta-tomcat-5.0.30</home> </container> <configuration> <dir>${project.build.directory}/tomcat</dir> </configuration> </configuration> </plugin> </plugins> </build>

To generate your WAR, start Tomcat and deploy the WAR in it, simply type: mvn package cargo:start . That's all! Do you want to do the same in, say, Orion 2.0.5? Simply change tomcat5x with orion2x and the home element to point to where you have installed Orion 2.0.5. You don't have Orion on the machine running the build? No issue, simply replace <home> with:

<zipUrlInstaller> <url>http://www.orionserver.com/distributions/orion2.0.5.zip</url> </zipUrlInstaller>

Orion 2.0.5 will then be automatically downloaded and installed the first time you run your build.

Inplace webapp development with Jetty

Let's imagine you're using the same project as above but this time you'd like to start Jetty and make it point to your webapp directory (i.e. src/webapp ) so that whenever you make a change to your webapp's sources Jetty automatically picks it up and serves it. See Brett's nice blog post on this. Simply modify your pom.xml as follows:

[...] <packaging>war</packaging> [...] <build> <plugins> <plugin> <groupId>org.codehaus.cargo</groupId> <artifactId>cargo-maven2-plugin</artifactId> <configuration> <!-- No container specified thus it'll default to Jetty --> <configuration> <dir>${project.build.directory}/jetty</dir> <deployables> <deployable> <!-- Override location to point to the exploded webapp. Otherwise it'll deploy the generated WAR. We want to ensure that jetty reloads any change made to the webapp source tree... --> <location>${basedir}/src/main/webapp</location> </deployable> </deployables> </configuration> </configuration> </plugin> </plugins> </build>

Then open a shell prompt and type mvn cargo:start . Jetty will start and monitor your webapp's dir for any change (Note that the same can be achieved using other containers too).

If you're interesting in learning more, check the documentation and join us on the Cargo mailing lists.

[ vmassol ] 16:25, Wednesday, 28 September 2005

Results

The Google Summer of Code is now over. I've had the pleasure of being a mentor for Codehaus. More specifically I've mentored the following projects:

  • JBoss 3.x and 4.x support in Cargo. This project was successfully implemented by Nyoman Winardi (a.k.a. Win). Win started sending patches and over the course of the programme Win became a committer proper. The full support of JBoss 3.x and 4.x will be available in the next release of Cargo (version 0.7).
  • JSR-88 support for Cargo. This project was successfully implemented by Lev Olkhovich who also became a Cargo committer. Lev implemented deployment of J2EE archives using JSR-88. In the process he started a conversation to refactor Cargo to support the notion of remote containers. There's still some refactoring going on and we need to add some more tests but we should be able to have support for remote containers and JSR-88 in Cargo 0.7.
  • Refactor Cactus to use Cargo. One more project revolving around Cargo! This one was implemented by Xuan Thang Nguyen. Xuan sent several patches and thanks to Felipe we've applied some of those. However, I have to admit I have personally not been available enough to fully help Xuan apply his patches. We still have some patches in JIRA that haven't been applied yet. Actually the plan was to have Nicolas Chalumeau to help Xuan and apply Xuan's patches. Nicolas has been working and helping on Cactus for a long time now and was voted a committer on Cactus at the beginning of the SOC programme. However, the Apache Software Foundation (ASF) is extremely slow when it comes to adding a committer to a project (it can take more than 2 months) and we've not been able to give right access to Nicolas. Thus he's not been able to apply his own patches nor Xuan's... This is really an issue that the ASF has to solve quickly lest it'll see people leaving to create their project somewhere else.
  • Faqbot project. There were 2 students on this project: Jie Tang and Harsh Puri. Harsh has had to resign from the programme because of the tragic flooding that happened in the region of Mumbai. Jie has continued alone and has done some good work. Unfortunately he's not been able to fully complete the project (which was probably the most ambitious of all the SOC projects I've mentored). The hardest part was probably starting a project from scratch. Everything had to be done. Hopefully Jie and others will continue the project and make it release-ready. I was very excited by this project and I still am.
  • Real-time collaboration editing (Oxyd). This one was implemented by Jeremi Joslin of XWiki fame. Even though it was a project started from scratch Jeremi was able to complete it and have a first usable release ready. Well done Jeremi!

Learnings

  • Open source is about collaboration with others. I don't think the SOC emphasis was enough on this point. For example it was "fordbidden" for students to work together and the main focus was to produce a working piece of software.
  • Open source is not bound by time. People do it in their free time (at least most people) and as such they can't be expected to be bothered by strong release pressure. The SOC students had to work on a given date which caused some friction as the students were not always aligned with the project's timeline. Let me give you one example; It happened that some student needed to do a refactoring to the existing code to progress. This needs to be reviewed and possibly voted by project committer. There could easily be a delay of 1 week before we get everyone's agreement/ideas, etc. In the meantime the student is under pressure to quickly progress.
  • I have taken too many students. I felt I did not do the best possible job when it came to mentoring them. Some were not autonomous enough and would have required more mentoring. I'll take fewer students next time. The hardest is really to mentor students on a new open source project started from scratch. As I'm already involved with several open source project, I did not have enough bandwidth to help on all aspects required to set up a new project.
  • Several students had not enough time to participate. Some were still passing exams, others had some other summer job. This, combined with the deadline and the nature of open source did not mix well together. I think students should have an open source project to complete on a much longer timescale (possibly with milestones to monitor progress). This would also help in having them really integrated into an open source team. In addition it'll show their real commitment over time which is really what "professional" open source is about. There's nothing worse that someone who contributes big portion of code and then leaves some time after. Then, all the bug fixing and maintenance falls on the shoulders of the committers who were not the ones with the itch in the first place...

Parting words

The SOC was good. It has boosted the open source community quite remarkably (even though it has also probably put some strain on it...). Out of all the students I've mentored I think 2 or 3 of them (out of 6 initially) will continue to work on the open source project they've participated to. That's a 30%-50% ratio and I'm very happy about it. Thanks Google for making this happen!

[ vmassol ] 08:56, Thursday, 15 September 2005

Javazone 2005 was good. It's getting more international every year but there's still a lot of Norwegian speaking there, which was a bit difficult to understand from time to time... Oh well, I had Jerome Lacoste translating for me whenever needed. Thanks Jerome. It also gave me the opportunity to learn "Hey alle semmon" ("hi everybody") and Jeff Genenger woke up his audience on thursday morning with a "I'm a loud-mouthed american, don't listen to me I don't know anything" in Norwegian! :-)

I have presented From Maven 1 to Maven 2 which went well. There were about 60-70 people in the room, all Maven 1 users (to be expected for such a talk) and a few (about 5) Maven 2 users.

Update 2005-09-28: Kito has blogged about JavaZone 2005 and has uploaded some nice pictures.

[ vmassol ] 10:48, Sunday, 1 May 2005

Cargo 0.5 has been released yesterday. One novelty is the Maven plugin. You can now start and stop a variety of containers using this plugin. This should come very handy for all of you wishing to perform integration or functional testing with Maven. The containers that are currently supported are: Resin 2.x, Resin 3.x, Tomcat 3.x, Tomcat 4.x, Tomcat 5.x, Orion 1.x, Orion 2.x, Jetty 4.x, jo! 1.x, OC4J 9.x and WebLogic 8.x.

For example, imagine that you have some integration tests in your project's test directory and that you need, say, Tomcat 5.0.30 to run them. You'll need to start the Tomcat container before the test:test goal kicks in. Do this by writing a preGoal in your maven.xml :

<preGoal name="test:test"> <ant:mkdir dir="${maven.build.dir}/tomcat"/> <attainGoal name="cargo:start"/> </preGoal>

You'll need to provide Cargo configuration data in your project.properties or build.properties file. For example a minimal configuration would be:

cargo.containers = tomcat
cargo.container.tomcat.containerKey = tomcat5x
cargo.container.tomcat.homeDir = C:/apps/tomcat-5.0.30
cargo.container.tomcat.config.hint = standalone
cargo.container.tomcat.config.dir = ${maven.build.dir}/tomcat
cargo.container.tomcat.config.standalone.servlet.port = 8180

Alternatively you can ask the plugin to automatically download and install Tomcat for you (it'll download it only once), by specifying:

cargo.containers = tomcat
cargo.container.tomcat.containerKey = tomcat5x

cargo.zipUrlInstaller.tomcatinstaller.installUrl = http://www.apache.org/dist/jakarta/tomcat-5/v5.0.30/bin/jakarta-tomcat-5.0.30.zip
cargo.zipUrlInstaller.tomcatinstaller.installDir = ${maven.build.dir}/installs
cargo.container.tomcat.zipUrlInstaller = tomcatinstaller

cargo.container.tomcat.config.hint = standalone
cargo.container.tomcat.config.dir = ${maven.build.dir}/tomcat
cargo.container.tomcat.config.standalone.servlet.port = 8180

As you may have noticed, in our example above we've reused the existing Maven Test plugin which looks for test sources in ${pom.build.unitTestSourceDirectory} . With this strategy you'll need to create a separate subproject for running your integration/functional tests in order not to interfere with pure unit tests that you may already have in ${pom.build.unitTestSourceDirectory} .

If there's a strong demand, we may consider adding a cargo:test goal in the future that you look for tests in, say, src/test/cargo by default (leaving src/test/java for unit tests).

Please note that there's also an alternative which is to start the Container directly from your unit tests.

If you find Cargo interesting, please come and help us on the Cargo mailing lists. There are lots of different ways you can help: trying Cargo on containers, implementing new containers (for example, JBoss, JOnas, WebSphere, etc), discussing new ideas, letting us know what new features you'd love to see, etc.

[ vmassol ] 10:36, Sunday, 1 May 2005

The Cargo team is pleased to announce the release of Cargo 0.5.

The major changes from Cargo 0.4 to 0.5 are:

  • New Maven plugin
  • Added support for hot deployments
  • Added support for the jo! container

Detailed release notes are available on the download page.

Here's an example of how to use Cargo from Java:

Container container = new Resin3xContainer();
container.setHomeDir("c:/apps/resin-3.0.8");

Deployable war = container.getDeployableFactory().createWAR("path/to/simple.war");
container.getConfiguration().addDeployable(war);

container.start();
// Here you are assured the container is started.

container.stop();
// Here you are assured the container is stopped.

Here's an example using the provided Ant tasks:

<cargo-orion2x homeDir="c:/apps/orion-2.0.3" output="target/output.log" log="target/cargo.log" action="start"> <configuration> <property name="cargo.servlet.port" value="8180"/> <war warfile="path/to/my/simple.war"/> <ear earfile="path/to/my/simple.ear"/> </configuration> </cargo-orion2x>

And here's an example using the Maven plugin:

// To run it:
maven cargo:start

// To configure it, add the following in a Maven properties file:
cargo.containers = myTomcat
cargo.container.myTomcat.containerKey = tomcat5x
cargo.container.myTomcat.homeDir = c:/apps/jakarta-tomcat-5.0.30
cargo.container.myTomcat.config.hint = standalone
cargo.container.myTomcat.config.dir = ${maven.build.dir}/myTomcat/config
cargo.container.myTomcat.config.standalone.servlet.port = 8180

Enjoy!

[ vmassol ] 14:23, Sunday, 6 February 2005

At last, I was able to get the svn+ssh protocol to work from both IntelliJ IDEA (Irida #3200) and Eclipse (3.1M4), using a private key! Here's how to do it:

For IntelliJ IDEA

  • Start by downloading the latest javasvn.jar from the TMate JavaSVN web site. You need version 0.8.0 or later (I've used 0.8.0). The reason is that there is a new property named javasvn.ssh2.key that has been added as a hack for getting the Subclipse plugin for Eclipse to work with svn+ssh... Drop the jar in [IDEAHOME]/plugins/svn4idea/lib , replacing the existing jar of the same name there.
  • Modify the [IDEAHOME]/bin/idea.bat file to add the javasvn.ssh2.key system property: IF "%IDEA_JVM_ARGS%" == "" set IDEA_JVM_ARGS= [...] -Djavasvn.ssh2.key=/path/to/your/private/key .
  • Make sure you use an openSSH-compatible private key. The Putty format is NOT supported by JSch. If you have a Putty private key, use Puttygen to export it as an OpenSSH key.
  • Make you sure you specify a valid username in the IDEA subversion setting, leaving the password field blank.

For Eclipse

  • Install Subclipse using the provided Eclipse update site
  • Install the JavaSVN Subclipse Extension, also using the provided Eclipse update site
  • Modify the way you start Eclipse as mentioned on the JavaSVN Subclipse Extension web page
  • Go the SVN Repository Exploring perspective, right-click on your SVN Repository, click on "properties" and make sure you enter a valid username (leave the password blank).

Enjoy! That should please all the Codehaus hausmates... :-)

[ vmassol ] 20:56, Saturday, 24 July 2004

11/08/2004 update: The project is about to start on Codehaus and is now named Cargo.

Note: There is also an article and a discussion thread on TheServerSide about this inititative

Here's a new idea for an open source project I'd like to start. It could be called CCI (Container Client Interface). It would aim at providing a simple Java API to start/stop/configure/deploy Java containers (In the first version the goal would be to support J2EE containers). This Java API could then be used by lots of other projects (Ant tasks, Maven plugins, IDE plugins, Cactus, etc).

The inspiration comes from the Cactus project, which already provides an extensive API to perform such tasks. The goal is to refactor the Cactus Ant API, remove anything related to Cactus and make it a standalone project called CCI

Here's an integraton test showing what the API could look like:

    public void testStartWithOneWarDeployed()
    {
         Container container = new Resin3xContainer();
         container.setHomeDir("/apps/resin-3.0.8");
         container.setPort(8080);
         container.setInstallDir(new File("target/resin3x"));
 
         WAR war = new WAR("src/testinput/simple.war");
         URL pingURL = new URL("http://localhost:" + PORT + "/simple/index.html"); 
         war.setPingURL(pingURL);
 
         container.addDeployable(war);
 
         ContainerRunner runner = new DefaultContainerRunner(container);
 
         runner.start();
         assertTrue("Container not started yet!", new HttpUtils().ping(pingURL));
         
         runner.stop();        
         assertFalse("Container not stopped yet!", new HttpUtils().ping(pingURL));
     }

As you can see there are several main Objects/Interfaces:

  • Container: This the main object that provides the API to start/stop the container.
  • WAR: A WAR archive to be deployed in the container. Inherits from Deployable. There will be other types later on (WAR, EAR, RAR)
  • ContainerRunner: Athough a container can be start ed without a container runner, the container runner provides advanced feature like starting the container in a different thread, verifying if the container is already started, waiting till the container is started, waiting till the container is stopped, etc.

Note that the ping URLs are the URLs that will be pinged by the ContainerRunner object to ensure the container has finished starting. Thus, after container.start() has finished executing you can be sure the container is started and the archives have been deployed and are ready for servicing requests. A better solution in the future will be to use JMX to ensure the container has finished starting. However, all containers do not yet support this feature.

A shorthand code version to start Resin 3.0.8 could look like:

        Container container = new Resin3xContainer("/apps/resin-3.0.8");
        container.setInstallDir("target/resin3x");
        container.addDeployable(new WAR("src/testinput/simple.war"));
        container.start();

This is just a taste of what he CCI API could look like. Let me know what you think!

[ vmassol ] 20:10, Sunday, 11 July 2004

I've just released a Maven plugin for Abbot. Abbot is a Swing unit testing framework. The Maven Abbot plugin supports the following:

  • Ability to start the Abbot Costello editor using either jars defined in the POM or the jars from an already installed WebStart application.
  • Ability to execute Abbot XML scripts through the Ant <junit> task
  • Ability to execute Abbot XML scripts on an already installed WebStart application (end-to-end functional testing)

You can download the Maven Abbot plugin here.

Please note that this plugin was written jointly with Christian Blavier whom I thank very much for his help!

[ vmassol ] 19:46, Sunday, 11 July 2004

Here is a list of OSS stuff I'm considering doing in some short future (note that I'm not planning to do all of them ;-))

  • Cactus v2
  • Create a container OSS project that offers a Java API to configure containers, start/stop them and deploy archives. The idea is to extract the existing API from the Cactus project (which already supports these tasks for several containers: Tomcat, Orion, Resin, JBoss, WebLogic, etc). Cactus would be refactored to use this new project. This API would be nice for any other project that requires a container.
  • Implement a Maven plugin for Clirr. Note: I have almost finished a first version.
  • Implement suppor for history reports in Maven. For example it would be nice to get Clover reports over time, Checkstyle reports over time, Dashboard reports over time, etc. I'm currently thinking to consider reports as project artifacts and store them in the Maven repository. A history plugin could provide support to save/load them. Another solution (probably better) involves using a lightweight database (e.g. Hypersonic SQL) and considering this database file as the artifact.
  • Continue adding support for RSS feeds to the existing Maven plugins, wherever it makes sense. The final idea is to offer RSS feeds to all project information so that project members can have their own Personal Project Information Portal (PPIP). Among the tools I like/use, RSS feeds are already available for: JIRA, Confluence/TWiki, FishEye, Maven Checkstyle plugin, Maven Changes plugin. Next in my list are: Maven Clover report, Maven Dashboard plugin, Maven PMD plugin, Maven XDoc plugin (for downloads).

In addition to this, I plan to continue fixing Cactus v1 bugs (albeit slowly...) and continue fixing bugs and adding enhancements to the Maven plugins I have started (changes, clover, abbot, etc).

If you're working on the same topics or if you're interested in contributing, please let me know!

[ vmassol ] 10:55, Friday, 9 April 2004

After discussing with the StatCvs-XML team, we have decided that it would be best that they host the Maven StatCvs plugin on their own site.

This will make it easier for them to improve it and keep it in sync with StatCvs-XML. This is possible thanks to the plugin:download feature of Maven 1.0 rc1/rc2 which allows users to easily install some external plugins. It is also possible to reference a plugin in your own project.xml as a dependency of type plugin .

[ vmassol ] 08:56, Monday, 5 April 2004

TheCortex (creator of Clover) has announced a new product called FishEye. It's an SCM mining tool.

They have accepted to run it on Cactus. It's very nice. The things I like particularly:

  • RSS feeds on commits, at all directory levels. For example you can subscribe to the feed that monitors changes to the xdocs files if you're interested in documentation updates.
  • Annotations (for e.g.: http://fisheye.thecortex.net/viewrep/jakarta-cactus/build.xml?r=1.69)
[ vmassol ] 18:39, Wednesday, 17 March 2004

I've just released a Maven plugin for Jetty. The Maven Jetty plugin allows easy deployment and execution of Jetty.

Features in this version includes:

  • Ability to automatically generate the Jetty XML configuration file
  • Ability to start Jetty
  • Deployment of WAR defined as dependencies and tagged with the jetty.bundle property
  • Deployment of the current project if it's a WAR project

Note that this plugin has been tested with Maven 1.0-rc2. Using it with another version of Maven is at your own risks! :-)

You can download the Jetty Maven plugin here.

[ vmassol ] 22:30, Monday, 1 March 2004

After several months of no activity, the PatternTesting project is getting alive again! Matt Smith is now taking the lead. On my side, I have not forgotten the idea of doing Pattern Tests using AOP. I am actually continuing this exploration with Cactus2, in a slightly different way.

In the meantime, please welcome Matt and let's wish him the best of success with the PatternTesting project!

[ vmassol ] 16:11, Sunday, 21 December 2003

Cactus v2 architecture

Rationale

Why a new architecture? Several reasons:

  • The existing architecture is restricted to testing Servlet components (and its variations: Taglibs, Filters, JSP). We've tried to create an SPI so that implementations for other containers can be written but it is not possible with the current architecture.
  • We'd like to make Cactus the de facto tool for performing integration unit testing (aka in-container testing) for any type of component in any type of container. See figure 1.
  • We'd like to make it easy for others to create Cactus extensions. This is not currently possible with the existing architecture.
  • We'd like to maximize the reusability of other testing tools. For example, instead of implementing in Cactus the HTTP layer that calls the server side, we'd like the user to use his favorite tool (e.g. HttpUnit). For unit testing Message-Driven Beans, the user will be able to use his favorite JMS injector (e.g. Commons Messenger), etc. This will allow leveraging all the features in those tools (for example, support for HTTPS in HttpUnit, support for Cookie handling, etc).
  • We'd like to standardize on a server side interception mechanism instead of inventing our own.
Figure 1: Scope of Cactus v2
Figure 1: Scope of Cactus v2

Architecture choices

These are the high-level architecture choices on which Cactus v2 will be built:

  • An AOP framework for server-side interception. There are 2 possible contenders: AspectJ or AspectWerkz. We are currently favorizing AspectWerkz because it allows to write test cases in Java. AspectJ extends the Java language and requires strong tool support. It will change with the advent of JDK 1.5 as the JDK will become meta-data compatible and Aspect will probably take advantage of this. However, it will take several years before everyone is on JDK 1.5 and we need a solution before this.
  • Cactus v2 will continue to be a JUnit extension. A Cactus v2 test case will be a JUnit test case and thus any JUnit test runner will work (provided the server has been started and the components and tests deployed).

High level architecture

The Cactus system is composed of 3 parts (see figure 2):

  • A Cactus test case, which is a combination of a JUnit test case (with testXXX() methods executed on the client side) and aspects used on the server side to perform interception and/or validation on the server side (see figure 3). More specifically, 3 typical uses cases for these aspects are:
    • Intercept the call to the component under test and redirect the flow of execution to a specific method to unit test it,
    • Prevent the flow of execution to call some subsystem. For example, stop the flow of execution before it goes to the database and instead return canned values.
    • Perform asserts to verify server-side expectations. For example, verify that the Servlet HTTP Session contains such and such values after executing such method, verify that the Database connection is closed as many times as it is open for such and such use case, verify that the number of SQL queries is below such number (e.g. less than 10 SQL queries per use case), etc. These are server-side expectations.
  • A Cactus runner to execute Cactus tests automatically. This involves starting the container, deploying the application and tests in the container, starting the tests and stopping the container.
  • A Cactus framework to support starting a test case on the client side and continuing it on the server side, and also to support transferring test results from the server side to the client side so that results can be displayed in the executing JUnit test runner. This framework also contains helper aspects and classes to help write test cases.
Figure 2: High-level architecture
Figure 2: High-level architecture

Cactus test case example

Here is an example of a typical Cactus test case using AspectWerkz 0.9. Please note that this example is a work in progress and is non-functional at this stage. We're also working towards simplifying the syntax for test case writers:

Figure 3: Cactus test case sample
package org.apache.cactus.sample.servlet;

import java.util.Hashtable;

import javax.servlet.http.HttpServletRequest;

import org.codehaus.aspectwerkz.attribdef.Pointcut;
import org.codehaus.aspectwerkz.attribdef.aspect.Aspect;
import org.codehaus.aspectwerkz.joinpoint.JoinPoint;
import org.codehaus.aspectwerkz.joinpoint.MethodJoinPoint;

import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;

import junit.framework.TestCase;

public class TestSampleServletAspectWerkz extends TestCase
{
     /**
      * Intercepts Servlet's doXXX calls and instead redirect the flow of
      * execution to the {@link SampleServlet#getRequestParameters} method to
      * unit test.
      * 
      * @Aspect
      */
     public static class GetRequestParametersTestAdvice extends Aspect
     {
          /**
           * @Execution * *..SampleServlet.do*(..)
           */
          Pointcut interceptServlet;
          
          /**
           * @Around interceptServlet
           */
          public Object catchGetRequestParameters(JoinPoint joinPoint) 
              throws Throwable
          {
               MethodJoinPoint jp = (MethodJoinPoint) joinPoint;
               SampleServlet servlet = (SampleServlet) jp.getTargetInstance();
               Hashtable params = servlet.getRequestParameters(
                   (HttpServletRequest) jp.getParameters()[0]);
               assertNotNull(params.get("param1"));
               assertNotNull(params.get("param2"));
               assertEquals("value1", params.get("param1"));
               assertEquals("value2", params.get("param2"));
               return null;
           }
      }
 
     /**
      * Test {@link SampleServlet#getRequestParameters} by calling the server 
      * side using HttpUnit. On the server side, our aspect will kick in and
      * the {@link GetRequestParametersTestAdvice#catchGetRequestParameters} 
      * test method will be called to unit test our method.    
      */
     public void testGetRequestParameters() throws Exception
     {
          WebConversation conversation = new WebConversation();
          WebRequest request = new GetMethodWebRequest(
              "http://localhost:8080/test/SampleServlet?param1=value1&param2=value2");
          WebResponse response = conversation.getResponse(request);
      }    
}

We would like to be able to write the following (not yet supported by AspectWerkz but we've had commitment from the AW team that they will make modifications to support it! :-)). The difference with the previous sample is the removal of the inner aspect class + the typed poincut interception.

Figure 4: Ideal Cactus test case sample
package org.apache.cactus.sample.servlet;

import java.util.Hashtable;

import javax.servlet.http.HttpServletRequest;

import org.codehaus.aspectwerkz.attribdef.Pointcut;
import org.codehaus.aspectwerkz.joinpoint.JoinPoint;
import org.codehaus.aspectwerkz.joinpoint.MethodJoinPoint;

import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;

import junit.framework.TestCase;

public class TestSampleServletAspectWerkz extends TestCase
{
     /**
      * @Execution * *..SampleServlet.do*(..)
      * @And @Target(SampleServlet)
      * @And @Args(HttpServletRequest)
      */
     Pointcut interceptServlet;
         
     /**
      * @Around interceptServlet
      */
     public void catchGetRequestParameters(SampleServlet servlet,
         HttpServletRequest request) throws Throwable
     {
          Hashtable params = servlet.getRequestParameters(request);
          assertNotNull(params.get("param1"));
          assertNotNull(params.get("param2"));
          assertEquals("value1", params.get("param1"));
          assertEquals("value2", params.get("param2"));
      }
 
     /**
      * Test {@link SampleServlet#getRequestParameters} by calling the server 
      * side using HttpUnit. On the server side, our aspect will kick in and
      * the {@link #catchGetRequestParameters} test method will be called 
      * to unit test our method.    
      */
     public void testGetRequestParameters() throws Exception
     {
          WebConversation conversation = new WebConversation();
          WebRequest request = new GetMethodWebRequest(
              "http://localhost:8080/test/SampleServlet?param1=value1&param2=value2");
          WebResponse response = conversation.getResponse(request);
      }    
}

Detailed design

The detailed design of Cactus v2 is shown in figure 5 below.

Figure 5: Detailed design
Figure 5: Detailed design

It works as follows:

  1. The Cactus tests are started by a JUnit Test Runner (any JUnit Test Runner).
  2. The Cactus framework intercepts the JUnit call to the test case runBare() method. It checks if a listener socket has been set up. If not it sets up one. It passes the test name to it (so that the server side can later on find out what test is currently being executed),
  3. It calls the test case testXXX() method. In this method the test case writer has written the logic to call the server side (using any existing framework; for example HttpUnit for calling an HTTP service),
  4. The flow of execution reaches the application to test on the server side,
  5. Somewhere during the execution of the application, the test aspect defined by the test case writer kicks in. Before that aspect is executed, the Cactus framework intercepts it,
  6. The Cactus server side interceptor then calls the listener socket set up in step 2 to get the name of the test being executed (the test that was started on the client side). It checks if the aspect matches the current test,
  7. If the aspect matches, its advice is executed, performing whatever logic the test case writer has put in it,
  8. Before the call returns to the client side, the Cactus server side interceptor calls the socket listener to pass to it the server side test result (it passes to it any exception raised on the server side; for example AssertionFailedError exceptions),
  9. After the testXXX() method finishes its execution and before the test result is communicated to the JUnit Test Runner, the Cactus client side interceptor verifies if any error has been reported by the server side execution. If so, it rethrows the server side exception to the JUnit Test Runner. Otherwise it lets the result of testXXX() bubble up to the JUnit Test Runner.

Some additional comments/ideas:

  • If one of the catchXXX() methods is not called, it should result in an AssertionFailedError being raised. This is to prevent not executing server-side test code without knowing it. As we are using interception, I guess it's easy to make a mistake when defining the join point and thus we need this safeguard.

Challenges

The following challenges await us:

  • Being able to make the Cactus test case easy to write for test case writers,
  • Make the execution of Cactus test case easily executable. Runtime code weaving would be nice but is not supported by old JVMs. We will probably have a mixed model as is being supported by AspectWerkz.
  • Find out if integration with Chad's VirtualMock is possible/desirable.

Please challenge us to improve our design! :-)

Disclaimer: Please also note that, at this point in time, this architecture and ideas are only mine and do not represent (yet!) the official view of the Cactus project. I am proposing it to the Cactus project members.

[ vmassol ] 12:29, Monday, 1 December 2003

Currently the Cactus project is a framework to help unit test J2EE components (and mostly Servlet/JSP/Taglib).

I'd like to expand its goal and make it a framework for building in-container testing solutions. Cactus would still offer an implementation for J2EE component testing but it will also open up an API for plugging other implementations. Some ideas are shown on the diagram below.

cactus_new_vision.jpg

For this to happen, the core helper classes will have to be separated from the HTTP protocol implementation and the existing Cactus TestCases. 2 SPIs will appear:

  • one for plugging in different protocol implementations (RMI, JMS, etc). Currently Cactus provides the HTTP implementation.
  • one for plugging in custom test case implementations (still looking for a good name for these). Currently Cactus provides the ServletTestCase, FilterTestCase and JspTestCase.

Moreover, the Cactus integration modules (aka front-ends) will also need to provide clearly-defined extension points to help automate the whole process of starting the container, deploying components, running the tests and shutting down the container.

I'm currently working on the Cactus code to make the 2 SPIs surface. The first test drive of these new SPIs will be to implement support for EJB TestCases.

[ vmassol ] 19:05, Sunday, 21 September 2003

I have just released version 2.0 of the StatCvs plugin for Maven.

The Maven StatCvs plugin is a plugin for StatCvs-XML that generates CVS statistic reports.

Changes in this version:

  • Migrated the plugin to use the new statcvs-xml jar (which generates XML xdoc output instead of HTML).

You can download the StatCvs Maven 2.0 plugin here.

[ vmassol ] 16:09, Friday, 30 May 2003

I have just rewritten the Checkstyle plugin for Maven (version is now 2.0) so that it supports the excellent Checkstyle 3.1 tool.

The new plugin is currently located in Maven CVS and you need to build Maven from its sources to use it. In other words, it has not been released yet.

Note this new checkstyle plugin for Maven has only been tested with Maven 1.0 beta 10 and is not expected to work with other versions (but it may...)

[ vmassol ] 22:31, Friday, 23 May 2003

I have just committed a full rewrite of the Maven Cactus Plugin. As it is a rewrite, I have increased the version to 3.0 (it was 2.1-SNAPSHOT before). Note that the 3.0 version is still in development and is not released yet. I'm waiting for more feedback before releasing it.

The new version of the Cactus plugin now relies on the newest Cactus/Ant integration which has completely changed since version 2.0 of the Maven plugin. Thanks to the new Cactus/Ant, some features have also been added. The plugin now uses the new and Ant tasks (see the Cactus/Ant Integration page for more details).

Note that version 2.1-SNAPSHOT will never get released as 1/ a bug had been introduced and 2/ the direction is to use the Cactus/Ant integration which has been changed in Cactus CVS.

Please give it a try and report any issue on the Maven mailing lists/JIRA. You can find a read-made test application in here if you wish.

[ vmassol ] 09:30, Saturday, 17 May 2003

NMock v1.0 has been released yesterday by Joe Walnes. It is a dynamic mock object library for .NET.

On a related note, I've released version 0.09 of the MockObjects.com framework yesterday too. This release contains several improvements in provided Mock Objects but little modifications to the core, apart from the introduction of a new library: the Dynamic Mock API (or DynaMock for short). It is based on dynamic proxies (same as EasyMock but I think with a more powerful and cleaner syntax), which means the mocks are created at runtime.

Warning: This first cut of the DynaMock API is not stable at all. Actually, a big refactoring has happened in the MockObjects CVS and a better API has been developed (very similar but which fixes the quircks from the first cut). Thus, if you use this DynaMok API, be prepared to refactor your applications when version 0.10 is out!

Here is a short example using DynaMock 0.09:

[...]
import com.mockobjects.constraint.Constraint;
import com.mockobjects.dynamic.C;
import com.mockobjects.dynamic.Mock;

public class TestAdminServlet extends TestCase
{
    private Mock mockRequest;
    private Mock mockResponse;
    private HttpServletRequest request;
    private HttpServletResponse response;
    private AdminServlet servlet;
    
    public void setUp()
    {
        servlet = new AdminServlet();

        mockRequest = new Mock(HttpServletRequest.class);
        request = (HttpServletRequest) mockRequest.proxy();

        mockResponse = new Mock(HttpServletResponse.class);
        response = (HttpServletResponse) mockResponse.proxy();
    }

    public void tearDown()
    {
        mockRequest.verify();
        mockResponse.verify();
    }
        
    public void testDoGet() throws Exception
    {
        mockRequest.expectAndReturn("getParameter", "command", 
            "SELECT...");

        // Verify that the result of executing the command has been
        // stored in the HTTP request as an attribute that will be
        // passed to the JSP page.
        mockRequest.expect("setAttribute", C.args(C.eq("result"), 
            C.isA(Collection.class)));

        servlet.doGet(request, response);
    }

}

Update: Thanks to Chris Lenz, fixed the testDoGet() method and removed not needed asserts

[ vmassol ] 13:06, Thursday, 15 May 2003

I've just added a RSS feed for Jakarta Cactus news. It is available at http://jakarta.apache.org/cactus/news.rdf.

The update process is quite nice too: we change the RDF file in CVS. Then every night Gump builds the Cactus project documentation (we transform the RDF file to HTML using XSLT in this process) and if the build is successful, upload it to http://jakarta.apache.org/cactus. Thus we get automated updates from CVS to your RSS feed reader!