Random Project Updates

Haven’t made any project related post since July last year, so here’s a list of little things I spent some time on:

  • While playing around with Firefox Web Developer Extension, I found out that some Maven reports generated invalid HTML which could break the reports layout with non-default vm templates. Hence MFINDBUGS-29, MCHECKSTYLE-74, and MCHANGES-83.
  • After integrating Kaptcha in SCode Plugin 0.5, I spent some time working on the Kaptcha project itself where most of the effort was on refactoring the original SimpleCaptcha code. That, and some other patches have made it to Kaptcha 2.1 and 2.2 .
  • I replaced all usages of JMock with EasyMock on all of my Java projects (I know, a stupid thing to do because EasyMock-ing is also no fun). Looking forward to giving Mockito a try at work. No, there will be no effort to replace EasyMock with Mockito regardless of the outcome.
  • As mentioned on my Slicehosted post, I rewrote Wish using Rails. I also spent more time playing with Ruby/Rails and I could see why some people love them. Personally, I’m still leaning towards Java. I think static typing is better in the long run. My take on the whole Ruby vs Java fiasco… people have different perspectives and opinions, there’s not one true programming language nirvana, Ruby and Java communities will learn to co-exist peacefully.
  • Since this blog is now using WordPress (damn, I hate upgrading WordPress everytime there’s a security fix), and because there hadn’t been any activity in Blojsom development, I decided to stop following Blojsom mailing lists for now. Nabble shows that I’ve been posting since July 2005 to February 2008, it didn’t feel that long at all :). I will still maintain the Blojsom plugins I created and I still have some patches to contribute to Blojsom core.

Going Java 1.5 With Maven2-Based Project

I recently made some simple updates to Wish by using Java 1.5 generics and autoboxing/unboxing. Making Java source changes was the easy part, while the time consuming part was on hunting for information on Maven-related changes.

I started by changing maven-compiler-plugin source and target in pom.xml:

<build>
  <plugins>
    ...
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <configuration>
        <source>1.5</source>
        <target>1.5</target>
      </configuration>
    </plugin>
    ...
  </plugins>
</build>

And got this error upon running mvn site

Caused by: net.sourceforge.pmd.ast.ParseException: Can't use generics unless running in JDK 1.5 mode!

which led me to change maven-pmd-plugin targetJdk:

<reporting>
  <plugins>
    ...
    <plugin>
      <artifactId>maven-pmd-plugin</artifactId>
      <configuration>
        <targetJdk>1.5</targetJdk>
      </configuration>
    </plugin>
    ...
  </plugins>
</reporting>

Then I found out that the angle brackets used by generics syntax resulted in checkstyle errors:

<' is not preceded with whitespace.
error	<;' is not followed by whitespace.
error	'>' is not preceded with whitespace.

which is fixed by adding these modules to checkstyle.xml .

If you don’t already have any existing checkstyle rules, create checkstyle.xml file and place it on the root directory of the project (i.e. same place as pom.xml) and add configLocation to maven-checkstyle-plugin:

<reporting>
  <plugins>
    ...
    <plugin>
      <artifactId>maven-checkstyle-plugin</artifactId>
      <configuration>
        <configLocation>checkstyle.xml</configLocation>
      </configuration>
    </plugin>
    ...
  </plugins>
</reporting>

JSP Precompilation For Maven2 Project

You can precompile JSP as part of your Maven2 project build by using Maven2 JSPC Plugin.

Follow the usage guide for copy-paste samples to add insert-fragment in web.xml file and jspc-maven-plugin + maven-war-plugin as part of build plugins in pom.xml file.

Here are some problems that I encountered while adding JSP precompilation to Wish:

Some of the JSPs use SiteMesh taglib and since the application only needed it as part of the war package, I originally set the dependency scope to be runtime. This causes JSPC to complain because it needs the library in the classpath while compiling the JSPs.

Embedded error: file:E:/tazmania/eclipse-workspace/wish/src/main/webapp/404.jsp(1,1)
The absolute uri: http://www.opensymphony.com/sitemesh/decorator cannot be resolved
in either web.xml or the jar files deployed with this application

The solution is to change the scope from runtime to compile so SiteMesh becomes available during JSP precompilation.

The next problem is with JSP API and Jasper Runtime.

E:tazmaniaeclipse-workspacewishtargetjsp-sourcejsplogin_jsp.java:[194,68]
cannot resolve symbol
symbol  : class JspTag
location: package tagext

E:tazmaniaeclipse-workspacewishtargetjsp-sourcejsp_404_jsp.java:[7,61]
package org.apache.jasper.runtime does not exist
The solution is to add the missing libraries as dependencies in pom.xml file.

<dependency>
  <groupId>tomcat</groupId>
  <artifactId>jasper-runtime</artifactId>
  <version>5.5.12</version>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>jsp-api</artifactId>
  <version>2.0</version>
  <scope>compile</scope>
</dependency>

Note that you might want to specify the library versions based on the target environment you’re going to deploy the application to.

My Maven2 Cheat Sheet

Here are some Maven2 command lines that I use most often:

To create a new project:

mvn archetype:create -DgroupId=com.mbledug.foo -DartifactId=bar

To generate Eclipse project descriptor after configuring the dependencies in pom.xml:

mvn eclipse:eclipse

To run unit tests, obviously:

mvn test

Tun run a single test by test class name:

mvn test -Dtest=FooBar

To generate site documentation without running the tests (handy while updating the APTs):

mvn -Dmaven.test.skip=true clean site

To build the package file (jar, war, etc) allowing test failure:

mvn -Dmaven.test.failure.ignore=true package

To distribute the source code:

mvn assembly:assembly -DdescriptorId=src

To install a jar file on local repo:

mvn install:install-file -Dfile=foo.jar -DgroupId=bar -Dversion=x.y -Dpackaging=jar -DartifactId=blah

To release an artifact (create a tag in the SCM and bump up SNAPSHOT version in the pom):

mvn release:prepare release:perform

Tagyu4J v0.3 and BlogMap4J v0.2 – More On Maven

Tagyu4J v0.3 and BlogMap4J v0.2 have been released. Included in this release:

  • The use of Maven2. Spent some time on figuring out the equivalent of Maven1 goals in Maven2, e.g. distribution plugin in Maven1 is now assembly plugin in Maven2.
  • Project sites (BlogMap4J, Tagyu4J) are now generated by Maven. It reminds me of the old days of using Forrest 0.6 back in 2004.
  • Lots of code refactoring, lots of ‘Why did I do it that way?’ moments.
  • More unit tests with the aim of high test coverage and low code complexity. The effort of adding unit tests leads to code refactoring, should’ve done it much earlier.

My plan is to Maven2ised the rest of my projects (Wish and the Blojsom plugins). With the recent effort on Blojsom 3 where David changed (for the better) the names of classes, methods, etc, my Blojsom plugins should now support Blojsom 2 and Blojsom 3 compatible builds. I’m thinking to use sub modules in each plugin project by pulling the plugin logic to a *-core module, which will be the dependency of *-blojsom3 and *-blojsom2 modules within the same pom.

My overall thoughts on using Maven as a build tool: I don’t see any reason of using plain Ant anymore while most of the things needed are readily available in Maven. At times you might need to do something very fancy where you need to create an Ant script or write your own Maven plugin.

I’ve heard the argument against using Maven because Maven is seen as another learning curve for the developers. My response to it is that I believe Maven is something worth learning and getting used to, really, it will simplify your life and it will help your projects (and fellow developers) in the long run.

Moreover, Maven is more than a build tool.

Corrupted Jar On Local Maven Repository

test:test:
[junit] Running
foo.bar.BlahTestCase java.util.zip.ZipException: error in opening zip file
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.&lt;init&gt;(ZipFile.java:111)
at java.util.zip.ZipFile.&lt;init&gt;(ZipFile.java:127)
at org.apache.tools.ant.AntClassLoader.getResourceURL(AntClassLoader.java:870)
at org.apache.tools.ant.AntClassLoader.getResource(AntClassLoader.java:799)

After staring blankly on why the test failed with Maven but it was ok as a stand-alone, I remembered that I had this problem before. It was caused by corrupted jar on my local maven repository. The solution was to simply destroy the repository and rebuild it.