Embedding and Extending Apache Ant – testing properties

If you want to test a property from a custom task in Apache Ant 1.8, you can use the testUnlessCondition and testIfCondition in org.apache.tools.ant.PropertyHelper:

@Override
public void execute() throws BuildException
{
   final PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper(getProject());
   if(propertyHelper.testUnlessCondition(requiredPropertyName))
   {
      // property is missing
   }
}

Convert URL to filename using lambdaj

import ch.lambdaj.function.convert.Converter;
 
import java.net.URL;
 
public class ConvertUrlToFileName implements Converter<URL, String>
{
   public static ConvertUrlToFileName convertUrlToFileName()
   {
      return new ConvertUrlToFileName();
   }
 
   @Override
   public String convert(final URL from)
   {
      return from.getFile();
   }
}

Unzip with Apache VFS 2.0 (Java)

Apache VFS 2.0 is strange but super powerful. Uncompress a file at a given URI to a given output location:

<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-vfs2</artifactId>
   <version>2.0</version>
</dependency>
import java.io.File;
import java.io.IOException;
import java.net.URI;
 
import org.apache.commons.vfs2.AllFileSelector;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.VFS;
 
public class ZipfileUnpacker
{
   private final FileSystemManager fileSystemManager;
   private final URI packLocation;
 
   public ZipfileUnpacker(final URI packLocation) throws FileSystemException
   {
      this.fileSystemManager = VFS.getManager();
      this.packLocation = packLocation;
   }
 
   @Override
   public void unpack(final File outputDir) throws IOException
   {
      outputDir.mkdirs();
 
      final FileObject packFileObject = fileSystemManager.resolveFile(packLocation.toString());
      try
      {
         final FileObject zipFileSystem = fileSystemManager.createFileSystem(packFileObject);
         try
         {
            fileSystemManager.toFileObject(outputDir).copyFrom(zipFileSystem, new AllFileSelector());
         }
         finally
         {
            zipFileSystem.close();
         }
      }
      finally
      {
         packFileObject.close();
      }
   }
}

Hamcrest regexp matcher

Matches a string against a regular expression, inspired by Piotr Gabryanczyk with a couple of issues fixed.

import java.util.regex.Pattern;
 
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
 
/**
 * Matchers that use regular expressions
 *
 * @author t.wood
 */
public class RegexMatcher
{
   private static abstract class AbstractRegexpMatcher extends TypeSafeMatcher<String>
   {
      protected final String regex;
      protected final Pattern compiledRegex;
 
      private AbstractRegexpMatcher(final String regex)
      {
         this.regex = regex;
         compiledRegex = Pattern.compile(regex);
      }
   }
 
   private static class MatchesRegexpMatcher extends AbstractRegexpMatcher
   {
      private MatchesRegexpMatcher(final String regex)
      {
         super(regex);
      }
 
      @Override
      public boolean matchesSafely(final String item)
      {
         return compiledRegex.matcher(item).matches();
      }
 
      @Override
      public void describeTo(final Description description)
      {
         description.appendText("matches regex ").appendValue(regex);
      }
   }
 
   private static class ContainsMatchRegexpMatcher extends AbstractRegexpMatcher
   {
      private ContainsMatchRegexpMatcher(final String regex)
      {
         super(regex);
      }
 
      @Override
      public boolean matchesSafely(final String item)
      {
         return compiledRegex.matcher(item).find();
      }
 
      @Override
      public void describeTo(final Description description)
      {
         description.appendText("contains match for regex ").appendValue(regex);
      }
   }
 
   /**
    * Match the regexp against the whole input string
    *
    * @param regex the regular expression to match
    *
    * @return a matcher which matches the whole input string
    */
   public static Matcher<String> matches(final String regex)
   {
      return new MatchesRegexpMatcher(regex);
   }
 
   /**
    * Match the regexp against any substring of the input string
    *
    * @param regex the regular expression to match
    *
    * @return a matcher which matches anywhere in the input string
    */
   public static Matcher<String> containsMatch(final String regex)
   {
      return new ContainsMatchRegexpMatcher(regex);
   }
}

maven-enunciate-plugin java 7

It is possible to get the maven-enuniciate-plugin to work with Java 7. You might see an error like this:

[ERROR] Failed to execute goal org.codehaus.enunciate:maven-enunciate-plugin:1.24:docs (default) on project Pluto: Execution default of goal org.codehaus.enunciate:maven-enunciate-plugin:1.24:docs failed: A required class was missing while executing org.codehaus.enunciate:maven-enunciate-plugin:1.24:docs: com/sun/mirror/apt/AnnotationProcessorFactory

Looks like the tools.jar is not available in Java 7 by default. You need to add it as a dependency of the enunciate plugin. If you are using some other (non sun/oracle) JDK then the solution will be different, you may need to use maven profiles for each JDK you want to use.

You can add tools.jar as a dependency like this:

<plugin>
   <groupId>org.codehaus.enunciate</groupId>
   <artifactId>maven-enunciate-plugin</artifactId>
   <configuration>
      <configFile>src/main/doc/enunciate.xml</configFile>
   </configuration>
   <executions>
      <execution>
         <goals>
            <goal>docs</goal>
         </goals>
         <configuration>
            ...
         </configuration>
      </execution>
   </executions>
   <dependencies>
      <dependency>
         <groupId>com.sun</groupId>
         <artifactId>tools</artifactId>
         <version>${java.version}</version>
         <scope>system</scope>
         <systemPath>${java.home}/../lib/tools.jar</systemPath>
      </dependency>
   </dependencies>
</plugin>

You will now get a warning, which hopefully enunciate will fix sometime before java 8!

warning: The apt tool and its associated API are planned to be
removed in the next major JDK release.  These features have been
superseded by javac and the standardized annotation processing API,
javax.annotation.processing and javax.lang.model.  Users are
recommended to migrate to the annotation processing features of
javac; see the javac man page for more information.

Integrating guice and junit4

A JUnit4 Method rule to perform injection on your test fixture before each test case:

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
 
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
 
public class PerTestGuiceRule implements MethodRule
{
   private final Module module;
 
   public PerTestGuiceRule(final Module module)
   {
      this.module = module;
   }
 
   @Override
   public Statement apply(
            final Statement base,
            @SuppressWarnings("unused") final FrameworkMethod method,
            final Object target)
   {
      return new Statement()
      {
         @Override
         public void evaluate() throws Throwable
         {
            final Injector injector = Guice.createInjector(module);
 
            injector.injectMembers(target);
 
            base.evaluate();
         }
      };
   }
}

Use it by putting this code in you test fixture:

@Rule public PerTestGuiceRule guiceRule = 
                   new PerTestGuiceRule(new MyModule());
 
@Inject MyInjectableType myInjectableType;

You might want to check out GuiceBerry. I tried to use it, but for my case it seems very complex, or maybe impossible, to create your module per-test due to the static map of module class -> module instance used internally by guiceberry. There is a test scope included, but I don’t see a really clean way to use that if you want to test your production guice modules.

Marshalling Immutable Types in Jaxb

Unfortunately Jaxb requires any classes it creates during unmarshalling to have a default no-arguments constructor, and some way of mutating the fields. This prevents the use of types which enforce immutability using final fields.

A way to get around this is to use the @XmlJavaTypeAdapter annotation and implement custom marshalling and unmarshalling.

For example, create a class like this:

@XmlJavaTypeAdapter(value = MyValueXmlAdapter.class)
public class MyValue
{
   private final String value;
 
   private MyValue(final String value)
   {
      this.value = value;
   }
 
   @Override
   public String toString()
   {
      return value;
   }
 
   public static MyValue valueOf(final String value)
   {
      return new MyValue(value);
   }
}

and another like this:

public class MyValueXmlAdapter extends XmlAdapter<String, MyValue>
{
   @Override
   public String marshal(final MyValue value) throws Exception
   {
      return value.toString();
   }
 
   @Override
   public MyValue unmarshal(final String value) throws Exception
   {
      return MyValue.valueOf(value);
   }
}

Update Glassfish 3.0 to use Jersey 1.3

In order to update Glassfish 3.0 to use Jersey 1.3 we had to write over the Jersey files in the “modules” subfolder of the glassfish installation.

Here are some maven dependencies for the required files:

   <properties>
      <jersey.version>1.3</jersey.version>
      <jackson.version>1.5.6</jackson.version>
   </properties>
   <dependencies>
      <dependency>
         <groupId>com.sun.jersey</groupId>
         <artifactId>jersey-server</artifactId>
         <version>${jersey.version}</version>
      </dependency>
      <dependency>
         <groupId>com.sun.jersey</groupId>
         <artifactId>jersey-client</artifactId>
         <version>${jersey.version}</version>
      </dependency>
      <dependency>
         <groupId>com.sun.jersey</groupId>
         <artifactId>jersey-json</artifactId>
         <version>${jersey.version}</version>
      </dependency>
      <dependency>
         <groupId>com.sun.jersey.glassfish.v3.osgi</groupId>
         <artifactId>jersey-gf-server</artifactId>
         <version>${jersey.version}</version>
      </dependency>
     <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-xc</artifactId>
        <version>${jackson.version}</version>
     </dependency>
     <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-jaxrs</artifactId>
        <version>${jackson.version}</version>
     </dependency>
     <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-core-asl</artifactId>
        <version>${jackson.version}</version>
     </dependency>
     <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>${jackson.version}</version>
     </dependency> 
   </dependencies>

And here is a assembly plugin snippet which will rename the dependencies the way glassfish expects them to be named

   <dependencySets>
      <dependencySet>
         <outputFileNameMapping>${artifact.artifactId}.${artifact.extension}</outputFileNameMapping>
         <outputDirectory>modules</outputDirectory>
      </dependencySet>
   </dependencySets>

Serving static content and Jersey

If you want to serve static content from the same WAR as Jersey resources, it is possible to configure Jersey to run as a filter rather than a Servlet.

You can then define the property com.sun.jersey.config.property.WebPageContentRegex to exclude URLs matching the regular expression from being handled by Jersey. Instead request matching the pattern will fall through to the next filter and eventually the default Servlet, which can respond with your static content in the normal way.

   <filter>
      <filter-name>jerseyFilter</filter-name>
      <filter-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</filter-class>
      <init-param>
         <param-name>com.sun.jersey.config.property.WebPageContentRegex</param-name>
         <param-value>/static/.*</param-value>
      </init-param>
   </filter>
   <filter-mapping>
      <filter-name>jerseyFilter</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>

Testing using FEST Swing in CruiseControl

I have a CruiseControl CI build running as a windows service. Unfortunately when unit tests involving FEST Swing are run they fail as they need to actually render the UI components to a logged in user’s desktop.

My CruiseControl machines are virtual windows server 2003 machines running on vmware. So each build has its own dedicated virtual machine.

I followed the instructions for hudson builds on windows from the FEST Swing site.

Configure the server to auto login your build user:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon=1
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName=testuser
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultPassword=secret

Start CruiseControl on login by creating a batch file in the users “Start Up” start menu folder containing:

"C:\Program Files\CruiseControl\Wrapper.exe" -c "C:\Program Files\CruiseControl\wrapper.conf"

Make sure that the screen saver is disabled.