June 11, 2011

Capture an Argument Matcher

More than once I've found myself writing unit test code for a class that internally constructs an object which is then passed along to another method. A common pattern would be to introduce a factory for this internally created object, but at times this feels too heavy weight. I'd still like to make a few assertions about the object but this can get tricky when using lots of mock objects. Enter a little utility class called CaptureArgument. It is a type safe matcher that, wait for it, captures the argument it matched which allows you to inspect it. You can grab a copy of the class at GitHub. Below is a sample usage:

final MBeanServer mBeanServer = context.mock(MBeanServer.class);
final Object objectToRegister = new Object();
final CaptureArgument<ObjectName> captureArgument = new CaptureArgument<ObjectName>();
context.checking(new Expectations() {{
        oneOf(mBeanServer).registerMBean(with(same(objectToRegister)), with(captureArgument));
    }});
unitUnderTest.doSomething(objectToRegister);
assertEquals("BeanDomain", captureArgument.getArgument().getDomain());

Tags: java junit

February 20, 2010

PKIX path building failed

Recently this error message started showing up in one of our log files and needless to say was causing a few issues:

[org.apache.commons.httpclient.HttpMethodDirector] -

Turns out the process had been running long enough that while trying to perform an HTTPS based operation the certificate in the JVM for the certificate authority the target site was using had expired. A quick update of the cacerts file and everything was happy again. Yet another software rot angle to keep in mind.

Tags: https java jvm ssl

March 24, 2009

JUnit, Jetty, HtmlUnit, and Automated Testing

I'm a firm believer in automated testing. The more testing you can automate the less work you need to do to be sure you didn't break stuff each time you make a change. While most people think of unit testing when talking about automated testing, the higher up the interaction chain you can go while not making your tests brittle the better off you will be. On my current project unit test coverage is great, but given that ultimately all of the services get exposed as a web application, being able to automate testing at that level would be beneficial. Below is the approach I took to automate testing our web application.

The key ingredients to the approach are JUnit (testing framework), HtmlUnit (web request handler), and Jetty (integrated application server). Each automated test is written as a JUnit test with a call to a centralized function to startup the web application. To fully isolate each test method you could switch this to an @Before annotation. I've found though that the automated tests are most accurately defined as integration tests. Having a single instance running for all tests simulates the ultimate environment better so I only ever startup one server. Each test method is responsible for setting up the environment (.i.e. test data) to match what it needs so that the order of test methods never matters.

public class SampleTest {
    @BeforeClass
    public static void startServer() throws Exception {
        ObjectMother.startServer();
    }
}

The startServer() call in ObjectMother is responsible for starting the server if not already running. I startup the server on a random port to test that the configuration isn't port specific. The base URL for the web application is exposed so that tests making requests know what URL to start the call at. One issue I ran into is that you might need to play with the physical directory passed to WebAppContext as running from Eclipse versus Ant might have you starting in different working directories. To get around this issue there is a a little directory helper that searches for the target directory based on current, parent, and a couple other locations it could be found out.

import org.mortbay.jetty.Server;
import org.mortbay.jetty.webapp.WebAppContext;
public class ObjectMother {
    public static String baseUrl;
    private static Server server;

    public static void startServer() throws Exception {
        if (server == null) {
            server = new Server(0);
            server.addHandler(new WebAppContext("build/testapp", "/sample-server"));
            server.start();

            int actualPort = server.getConnectors()[0].getLocalPort();
            baseUrl = "http://localhost:" + actualPort + "/sample-server";
        }
    }
}

The creation of the "build/testapp" referenced above is done by Ant. When running within Eclipse an external tool builder is called to stage the web application like it would if it were to package it as a war. In particular the staging done for unit testing adjusts any deployment parameters so that they tuned for the test environment.

Now that the server is running requests can be made against it. This is where HtmlUnit gets used. A typical test looks something like this:

@Test
public void testBasic() throws FailingHttpStatusCodeException, IOException
{
    List<NameValuePair> parameters = new ArrayList<NameValuePair>();
    parameters.add(new NameValuePair(SampleCommand.CUSTOMER, ObjectMother.CUSTOMER));
    parameters.add(new NameValuePair(SampleCommand.URI, ObjectMother.URI));
    WebRequestSettings webRequestSettings = new WebRequestSettings(new URL(ObjectMother.baseUrl + "/sample/"));
    webRequestSettings.setRequestParameters(parameters);
    WebClient webClient = new WebClient();
    webClient.setThrowExceptionOnFailingStatusCode(false);
    Page page = webClient.getPage(webRequestSettings);

    assertEquals(HttpServletResponse.SC_OK, page.getWebResponse().getStatusCode());
    // additional request specific assertions
}

Frequently the response is XML based, so for these the XmlPage wrapper is used instead.

assertEquals(ServerUtil.XML_CONTENT_TYPE, page.getWebResponse().getContentType());

XmlPage xmlPage = (XmlPage) page;
NodeList nodeList = xmlPage.getXmlDocument().getElementsByTagName(ObjectMother.FAILURE_ELEMENT_NAME);
assertTrue(nodeList.getLength() > 0);

Since Jetty is starting up within the JVM, instead of as a separate process, using Eclipse's debug as JUnit test just works. The web application startup catches Spring configuration errors quickly and ensures that all paths are what they should be.

Tags: htmlunit java jetty junit testing

March 24, 2009

SimpleDateFormat is not thread safe

It has always felt counter intuitive that there are classes which are not thread safe in the Sun JDK, but that is the case. One that I frequently see people trip up on is SimpleDateFormat. From the documentation:

Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

UPDATE

While SimpleDateFormat is not thread safe, as pointed out in the comments below, Spring seems to create new binders per request removing the need for this approach. In reviewing the documentation it isn't immediately clear that this is the case.

I recently had to create a custom editor for a Spring Web MVC command and ran into this issue. One possible fix, without introducing a ThreadLocal, is to just create a SimpleDateFormat every time. Hence this simple ThreadSafeSimpleDateFormat wrapper.

import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ThreadSafeSimpleDateFormat extends DateFormat {
    private String pattern;

    public ThreadSafeSimpleDateFormat(String pattern) {
        this.pattern = pattern;
    }

    @Override
    public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
        return new SimpleDateFormat(pattern).format(date, toAppendTo, fieldPosition);
    }

    @Override
    public Date parse(String source, ParsePosition pos) {
        return new SimpleDateFormat(pattern).parse(source, pos);
    }
}

Then to setup that as the editor handler for a command that has a date field, in my controller that uses the command I added the following:

@Override
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
    super.initBinder(request, binder);
    binder.registerCustomEditor(Date.class, DATE_TIME, new CustomDateEditor(new ThreadSafeSimpleDateFormat(DATE_TIME_FORMAT), false));
}


Tags: date java spring

March 24, 2009

Velocity and Spring Web MVC

The combination of Spring Web MVC with Velocity makes for easy view handling. One of the things that I'm confused about though is getting the configuration up an running. I've been very happy with this configuration so I thought I'd share it.

First part is to let the system know where to find Velocity templates. I store them all in a directory called velocity which is part of the web application.

<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
    <property name="resourceLoaderPath">
        <value>/WEB-INF/velocity/</value>
    </property>
</bean>

Next up is letting Spring know that Velocity is the default View that will be used. This configures a few handy defaults that represent the common case response. That being is will be an XML response, the template name has no prefix and a .vm suffix, and we configure some custom tools to be available in the macros.

<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
    <property name="exposeSpringMacroHelpers">
        <value>true</value>
    </property>
    <property name="contentType">
        <value>text/xml</value>
    </property>
    <property name="prefix">
        <value></value>
    </property>
    <property name="suffix">
        <value>.vm</value>
    </property>
    <property name="toolboxConfigLocation">
        <value>/WEB-INF/toolbox.xml</value>
    </property>
</bean>

The toolbox configuration file defines some handy tools and in particular defaults the format that dates should be in when converted to a String. In this case the format is what ActionScript 3 expects, since this is the back end for a Flex project.

<toolbox>
    <tool>
        <key>esc</key>
        <scope>application</scope>
        <class>com.neophi.util.NullEscapeTool</class>
    </tool>
    <tool>
        <key>exceptionTool</key>
        <scope>application</scope>
        <class>com.neophi.util.ExceptionTool</class>
    </tool>
    <tool>
        <key>dateTool</key>
        <scope>application</scope>
        <class>org.apache.velocity.tools.generic.DateTool</class>
        <parameter name="format" value="EEE MMM dd HH:mm:ss 'UTC'Z yyyy"/>
    </tool>
</toolbox>

I've always felt like I'm missing some obvious configuration setting with Velocity that will make null values just show up as empty strings instead of being left as $model.attribute. Since I've not found that setting yet, the NullEscapeTool wraps the standard Velocity EscapeTool and sends back an empty string if the value was null.

@Override
public String xml(Object string) {
    String result = super.xml(string);
    if (result == null) {
        return "";
    }
    return result;
}

The ExceptionTool exposes one method stackTrace() that converts the stack trace associated with an exception to a string so that it can be included in the view. Not necessarily something you want to expose in a production environment, but very handy when debugging.

public String stackTrace(Exception exception) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    PrintStream printStream = new PrintStream(byteArrayOutputStream);
    exception.printStackTrace(printStream);
    printStream.close();
    // Closing a ByteArrayOutputStream has no effect, so don't do it which avoids the need to try/catch the IOException
    return byteArrayOutputStream.toString();
}

Lastly if you want to have Velocity also handle certain exceptions that your web application may throw the exception resolver facility is great for handling that. In this case the exception value that ServerException refers to is a Velocity template that incorporates the ExceptionTool mentioned above.

<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="warnLogCategory">
        <value>com.neophi.exception</value>
    </property>
    <property name="defaultStatusCode">
        <value>200</value>
    </property>
    <property name="exceptionMappings">
        <props>
            <prop key="com.neophi.exception.ServerException">exception</prop>
        </props>
    </property>
</bean>


Tags: configuration java spring velocity

January 31, 2009

Server Side Sojourn

I'll been a little quite on the blogging front as of late, besides the occasional user group post. The main reason for that has been the last couple of months I've been heads down doing server side Java development for a cloud computing infrastructure using Amazon's Web Services for S3, EC2, SimpleDB, and CloudFront. All that is the back end for some amazing Flex based applications that Allurent has in the works.

Being back heavy on the server side is a mixed blessing. Its an area I've done a lot of work in, in fact many of my first technically oriented posts on this blog where about Java. As a result I'm not playing with that many new things. The flip side is that I've been able to crank out a bunch of high quality code which feels good. Using Eclipse for Java development has unfortunately made me realize how far Flex Builder has to go to be a truly productive editor. Top three things I'm missing when working on ActionScript and MXML code: code formatting , MXML organize imports, and right-click run as FlexUnit test.

Allurent practices peer review before check in and automated unit testing. In order to make reviews effective we've established a coding standard so that anyone looking at someone else's code won't be distracted by funky formatting. Consistent formatting also makes looking at file differences much easier, eliminating the angry fruit salad only the whitespace changed difference report. Alas, without automated formatting support time gets wasted tabbing and spacing files to keep them readable. Likewise the need to launch an external program and occasionally tweak files to run a single TestCase or method increases the barrier to writing unit tests, which is never a good thing. Thankfully, Flexcover helps us keep tabs on areas we are lacking.

Java does has a big head start on Flex/AS3 for getting the tooling in there. Progress is being made, but for someone coming from the Java/Eclipse world, it's frustrating at times.

Tags: aws eclipse flex ide java tdd

December 28, 2008

Merapi (Flex Camp Boston 2008)

Merapi
Andrew Powell, Universal Mind

Only a couple people have used it.

Grew out of old Apollo project. Named after volcano on Java. What AIR to talk to Java.

AIR does what it does well, but we want it to do more. How do you extend AIR? Have it talk to GPS. Make mashups that just aren't components but also bring hardware into the mix. Anything that has Java library or JNI will work. Main component is called a Bridge because it is all about moving data back and forth between AIR and Java.

Need to create a connection, could be local or remote. AIR/Flex runs on OS. Bridge runs on OS. Hardware and applications also running on OS. AIR and Bridge are connected via AMF using BlazeDS serialization/deserialization techniques. Bridge then talks to applications and hardware.

var message:Message = new Message();
message.data = "Hello World";
message.type= " Reply";
Bridge.instance.sendMessage(message);

BridgeInstance has result event that you can handle.

Bridge API is easy, complexity is all in external APIs Merapi talks to.

It's alpha so security, reliability, installer, etc. are still being worked on.

merapiproject.net (where to get)
infoaccelerator.net (Andrew's site)

All applications have a Java piece and a Flex piece.

Demo of AIR application controlling bluetooth connected robot. Lego Mindstorm.
Demo of Google translator and text to speech.
Demo of Growl for the Mac. This also works from the browser.

Demo showing data grid in Flex exported to Excel. Data updates in Excel when saved update the data grid. Can create and send email message, update contacts, meetings, etc. If you can do it in Java you can do it with Merapi.

If within the browser, can it be an applet or if it is an application. Right now it needs to be a Java application, possibly a service.

Remote Java objects and competing with BlazeDS. Some overlap, but Merapi is more about hardware connections.

It is all Flex based. Next beta will also include Flash support.

Excel formula values are sent back. Word formatting probably comes back over RTF.

Public beta in the next couple of months.

Is it open source? It is open source, value is in derivative work.

How would the browser and desktop piece work? Still TBD.

Only limit is your imagination. Anything Java can do you can send it back and forth.

Data access size and transfer rate limits are not known, probably limited to hardware.

Tags: air flex flexcampboston2008 java merapi

October 14, 2008

PPE 2: Java Project Skeleton

GameOfLifeServer

I've been following the progression of the tool AppFuse for some time now but haven't had a chance to use it. This seems like a prime time (cue learning curve for first new technology). While there are many Java frameworks I could use, I've found the Spring Framework to be rock solid and know that it covers everything I could want to do with this simple application. Spring has also created Spring Web MVC to support the front-end pieces. I think it offers a cleaner solution than Struts. AppFuse supports Spring Web MVC based projects so that should make this straight forward.

Alas AppFuse requires Maven (cue learning curve for second new technology) which I don't currently have installed. Back to the command line for that. I already have Java installed so that AppFuse requirement is there and I'll start off with the HSQLDB profile since my MySQL server runs on a different machine and I don't want to mess with configuration just yet.

# 3rd party Java projects I store in a standard directory
cd /Applications/Java
# downloaded from one of the available mirrors
tar -zvxf ~/Storage/apache-maven-2.0.9-bin.tar.gz
setenv MAVEN_HOME /Applications/Java/apache-maven-2.0.9
setenv PATH "${PATH}:${MAVEN_HOME}/bin"

The latter two lines I'll be adding to my shell so that they get picked up next time I launch a terminal window. If you hadn't noticed those commands are in tcsh. I like it better than bash as my terminal shell (since I never made the switch to zsh which I hear is even better) but any scripting I do is in bash.

Now to let AppFuse do its magic.

cd ~/source/trunk/danielr/projects/PPE/
# tried to run the AppFuse Maven command line but got an error, see below
svn delete GameOfLifeServer
svn commit -m "Remove server directory since AppFuse complains if it already exists"
# now I can run it
mvn archetype:create -DarchetypeGroupId=org.appfuse.archetypes -DarchetypeArtifactId=appfuse-basic-spring -DremoteRepositories=http://static.appfuse.org/releases -DarchetypeVersion=2.0.2 -DgroupId=com.neophi.gol -DartifactId=GameOfLifeServer
# checking this into subversion as recommended
svn add GameOfLifeServer/
svn commit -m "Initial AppFuse generated project"
# now to play with the project
cd GameOfLifeServer/
# since I don't want to deal with MySQL properties right now
mvn -Phsqldb
mvn -Phsqldb jetty:run-war

Man those Maven targets are downloading a lot of stuff. That makes sense since I've never used Maven before so have nothing in my local repository. Overall as I've been playing with AppFuse the documentation on their site has been good enough that I can muddle through it. Now to pull it into the IDE.

# create Eclipse project files
mvn eclipse:eclipse

After launching Eclipse I added a Java Classpath Variable called M2_REPO pointing at "/Users/danielr/.m2/repository". I tried to use Maven to add it but it didn't work. Turns out it might have worked but had issues trying to use "~" when specifying the location of my Eclipse workspace directory. Next I imported the project located at "~/source/trunk/danielr/projects/PPE/GameOfLifeServer/". It imported and compiled with the expected errors. I think that means it's time to commit to subversion again.

# don't check in the directory Maven creates its files in
svn propset svn:ignore target .
# add the Eclipse created files
svn add .classpath .project .settings/
svn commit -m "Added ignores and Eclipse project files"

And with that, I'm calling it quits for today.

Closing Thoughts

For a snapshot of the project in process grab PPE-2.tar.gz.

For the history of this project see Programming Project Experiment (PPE).

Tags: gameoflife java ppe

August 27, 2008

Tomcat, Spring Web MVC, and Exceptions

I've been doing some server side development lately and using Spring 2.5.5 with Tomcat 6.0.18. One of the features built in is intelligent exception handling through implementations of HandlerExceptionResolver. In particular there is easy support to "fix" the HTTP response code for errors to be 200 so that Flash doesn't croak. I got my configuration setup but no matter what I did I kept getting back the default Tomcat 500 error page. A little code tracing showed that my configuration was valid and my Velocity based error page was getting picked up and processed but not reflected in the response. Turns out that Spring 2.5.5 and Tomcat 6.0.18 (and earlier versions) don't play well together. A bug has been logged against Spring so that if it generates an error response it clears out the Servlet error request attributes that Tomcat examines to determine if it should return its own built in error page. Alas as of today you'll have to grab a nightly snapshot of Spring to pickup the fix or manually patch DispatcherServlet.java.

Tags: exception java spring tomcat