Sunday, October 28, 2012

Lombok and Spring: IntelliJ Plugin

As indicated in my last post, I've been playing around with Project Lombok a little. One of the easier to absorb features is the @Getter/@Setter annotations, which removes the need to explicitly define getters and setters in your Java classes.

I use IntelliJ as my main IDE. However, when I started to use Lombok, I would get error messages from the IDE when viewing a Spring configuration file that used setter injection.

The answer to this problem was to simply install the lombok-intellij-plugin, which fixed the error rather nicely.

We'll setup the scenario withe simplest of objects that I can think of. If you now have the answer you're looking for (and you probably do), feel free to skip the example below:

    public class Person {

        private String name;

        public Person() {}

        public Person(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

A very simplisitc Spock specification that uses Spring testing to inject an instance of a Person:

    @ContextConfiguration
    class PersonSpec extends Specification {

        @Autowired
        Person person

        def "has a name"() {
            expect: person.name == 'Rudiger'
        }
    }

And the bean that is autowired in from PersonSpec-context.xml:

    <bean id="rudiger" class="prystasj.lombok.plugin.example.Person">
        <property name="name" value="Rudiger"/>
    </bean>

Here the test passes and there is no "red" for errors in our IDE.

Now if we replace the getter and setter in the Person with annotations from Lombok:

    public class Person {

        @Getter @Setter
        private String name;

        public Person() {}

        public Person(String name) {
            this.name = name;
        }
    }

The tests still passes, but our IDE is showing us some red when viewing the Spring configuration file:

At this point, installing the lombok-intellij-plugin sends the error away.

Wednesday, October 24, 2012

Lombok: Using @Getter/@Setter and @Delegate

I've been working on a project for the majority of the past year that's part of a larger architecture where the powers that be have not approved the use of a language like Groovy due to strong feelings about things like type safety, among other fears. I don't want to get into a debate about whether such fears have any foundation (maybe at a later date). I do however want to try to introduce Project Lombok here, which has helped simplify the Java we've been writing, helping to remove some of the boilerplate code that we've been writing, bringing our code a little closer to what it might look like with Groovy.

Lombok has many features to help simplify your Java. For now, I'll present just @Getter/@Setter and @Delegate. We'll compare a plain Java version of some object and present both a Lombok and Groovy version for comparison.

Our example is pretty straightforward, a nameable Rocket that uses a Booster to take off and record if the rocket has been started:

    public class Rocket {

        private final Booster booster;

        private String name;

        public Rocket(String name, Booster booster) {
            this.name = name;
            this.booster = booster;
        }

        public void takeoff() {
            booster.takeoff();
        }

        public boolean isStarted() {
            return booster.isStarted();
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public class Booster {

        private boolean started = false;

        public void takeoff() {
            System.out.println("3.. 2.. 1.. Java Rocket go now!");
            started = true;
        }

        public boolean isStarted() {
            return started;
        }
    }

The above code has some classic Java boilerplate in getters and setters, along with a couple one line methods that acts as simple pass-throughs from Rocket to its Booster collaborator.

Now we can introduce the @Getter/@Setter and @Delegate annotations to simplify the code (with the import statements ommitted for brevity):

    public class Rocket {

        @Delegate private final Booster booster;

        @Getter @Setter private String name;

        public Rocket(String name, Booster booster) {
            this.name = name;
            this.booster = booster;
        }
    }

    public class Booster {

        @Getter private boolean started = false;

        public void takeoff() {
            System.out.println("3.. 2.. 1.. Lombok Rocket go now!");
            started = true;
        }
    }

This code is simpler as the getters and setters have been removed, along with the pass-throughs. What would a more Groovy example look like?

    class Rocket {
        @Delegate private Booster booster
        String name
    }

    class Booster {

        boolean started = false;

        def takeoff() {
            println "3.. 2.. 1.. Groovy Rocket go now!"
            started = true
        }

    }

This code is extremely similar to the Lombok example. The @Getter and @Setter annotations are missing because with Groovy we get them by default, however, now we could conceivably find a way to directly set the started property of the Booster class. Another somewhat significant difference is the Rocket constructor is missing, which we would have to reinstate if we were using this code from Java.

The same Spock specification can be used to test all 3 classes to verify they provide the same behavior:

    class RocketSpec extends Specification {

        def name = "LombokRocket"
        def booster = new Booster()

        def rocket = new Rocket(name, booster)

        def "initially has not taken off"() {
            expect: !rocket.isStarted()
        }

        def "can takeoff"() {
            when: rocket.takeoff()
            then: rocket.isStarted()
        }

        def "has a name that can be changed"() {
            when: rocket.name =  name.reverse()
            then: rocket.name == name.reverse()
        }

    }

When looking at the Lombok version, it is definitely closer to the Groovy version, showing that if you are stuck using Java, there are some features you can still have with a little work.

Another point of interest is getting both Lomboked and Groovy code to compile alongside our Java code using Maven. I've uploaded this project to GitHub if you would like to view the POM and the rest of the source:

I'll look to add to the above project in the future to demonstrate some more Lombok features.

Comment away, and thanks!

Thursday, July 26, 2012

Setting the Location of the Maven Local Repository at the Command Line

If you ever need to temporarily override the directory Maven uses for your local repository when running Maven from the command line, you can do so by setting the property maven.repo.local:

    $ mvn -Dmaven.repo.local=/tmp/repository install

Why would you want to do this? I found a useful situation while logged into a server at work where my login had a form of "read-only" access, and therefore no home directory, but where I had access to Maven and needed to test something out. I'm sure there would be other reasons out there as well or the property wouldn't be available?

Resolving Font Preferences Between Openbox and Gnome

While working on setting a new workstation with Linux Mint 13 Maya and Openbox, I had quite a difficult time getting any adjustments to the fonts to take hold while working in Openbox.

The two approaches I took was adjusting the fonts through Gnome Tweak Tool and ObConf. Changes with the tweak tool took effect when logged in to Gnome, but not when in Openbox, which I found surprising in part because Gtk was still being used to render the windows. Adjustments in ObConf only affect items like the font rendering in the window title bar.

The difference however is when in Openbox, gnome-settings-daemon was not running. A good hint is found in the system wide autostart script at /etc/xdg/openbox/autostart:

    # If you want to use GNOME config tools...
    #
    #if test -x /usr/lib/openbox/gnome-settings-daemon >/dev/null; then
    #  /usr/lib/openbox/gnome-settings-daemon &
    #elif which gnome-settings-daemon >/dev/null; then
    #  gnome-settings-daemon &
    #fi

Running /usr/bin/gnome-settings-daemon from a terminal did the trick and the changes made to the fonts did take hold.

To make the changes permanent, you could uncomment the above section in the system-wide autostart script, but I chose for no particular reason to adjust the user-level script, ~/.config/openbox/autostart by simply adding:

    gnome-settings-daemon &

Either way should work if anyone is running into the same issue.

Monday, May 14, 2012

Spock: Using @Unroll with Parameterized Data

With Spock, a testing framework for Java and Groovy, we can easily write tests using parameterized data. One feature I'd like to share is the @Unroll annotation which makes working with parameterized data easier as each entry in the table will be treated as separate test.

Take this example that tests the addition of two numbers:

    package org.stash.example

    import spock.lang.Specification
    import spock.lang.Unroll

    class AdderSpec extends Specification {

        Adder adder = new Adder()

        @Unroll("#i + #j == #sum?")
        def 'can add two numbers together to produce a sum'() {
            expect:
                sum == adder.add(i, j)
            where:
                i | j | sum
                1 | 2 | 3
                2 | 2 | 4
               -1 | 2 | 0
        }
    }

Prior to adding the @Unroll annotation, our test output in Maven would look like this:

    Running org.stash.example.AdderSpec
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.374 sec

The three separate test are treated as a whole. With the annotation added:

    Running org.stash.example.AdderSpec
    Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.388 sec

Now each entry for the data table is treated as a separate test

If we were to force a failure, by say expecting -1 + 2 == 0...

    Running org.stash.example.AdderSpec
    Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.501 sec <<< FAILURE!

    Results :

    Failed tests:   -1 + 2 == 0?(org.stash.example.AdderSpec): Condition not satisfied:(..)

We now see in the output the message attached to the annotation with the values used in the test from the data table filtered in!

Hessian: Expected "End of Map" Exception

We've been working with Hessian services lately to send Java objects over the wire. So far the work has been trouble free, but from time to time, we run into some cryptic error messages. I'll document one here in case someone runs into a same problem.

Take the following error:

  Caused by: com.caucho.hessian.io.HessianProtocolException: expected end of map ('Z') at 'end of file'

This appear simply means, at least in our case, that the object being received by the caller of a Hessian service cannot be deserialized, either the object being transferred directly, or object contained with the transferred object's graph.

To resolve make sure every object in the graph implements java.io.Serializable.

Note: The above error came from com.caucho:hessian:jar:4.0.7.

Saturday, April 21, 2012

Spring Expression Langauge and Simple Bean References

In this post I'll demonstrate a simple use of Spring Expression Language (SpEL). First, I'll give a little background of the "problem" I used to solve, but feel free to skip ahead to the Spring configuration below.

The project in question was required to make two separate RESTful calls to the same service, for example:

  1. http://service.mycompany.com/business/record
  2. http://service.mycompany.com/business/order

The URLs contain the same base path, http://service.mycompany.com/business, and two separate paths, record and order. The URLs are to be looked up in a service directory, whose entries we have control of.

At first I considered placing both URLs in the directory to avoid having to deal with adding each path to the base URL in code. This sounded like a misuse of the directory however as each URL would not represent a separate service deployment. Then I remembered reading about SpEL and thought this could be help me add the paths to the URL in good ol' Spring configuration.

Here is a simplification of the defintion of the bean for the URL (java.net.URL) we will reference for defining the two service URLs:

    <bean id="serviceUrl" class="org.mycompany.service.entry.ServiceEntryProxy">
       <property name="serviceName" value="businessService"/>
       <property name="serviceDirectory" ref="serviceDirectory"/>
    </bean>

As we planned on using Spring's RestTemplate to invoke the remote service, we can convert the java.net.URL returned by the service lookup and translate them to Strings to be injected in the calling class.

    <bean id="recordServiceUrl" class="java.lang.String">
        <constructor-arg value="#{serviceUrl.toExternalForm()}/record"/>
    </bean>

    <bean id="orderServiceUrl" class="java.lang.String">
        <constructor-arg value="#{serviceUrl.toExternalForm()}/order"/>
    </bean>

We create the expressions above using #{...}, which is similar to syntax used to resolve properies in Spring, ${...}. Inside the expression, we can reference the serviceUrl bean defined earlier and call a method on it, #{serviceUrl.toExternalForm()}, which returns a String representation of the URL. From there we can add the remaining paths, /record and /order.

Given the following property signature of the class required to invoke the service:

    public class ServiceController {
        private RestTemplate restTemplate;

        private String recordUrl;
        private String orderUrl;

        // ...
    }

We can inject the URL string defined earlier:

    <bean id="serviceController" class="org.mycompany.service.business.ServiceController">
        <property name="restTemplate" ref="restTemplate"/>
        <property name="recordUrl" ref="recordUrl"/>
        <property name="orderUrl" ref="orderUrl"/>            
    </bean>

    <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>

Admittedly, this is a very simple example of what we can do with SpEL. The feature overview in the documentation does a much better job of enumerating them than I could try to do. Hopefully, now that I've used in once, I'll look to SpEL again for other uses to help get out of some potentially tricky situations.

Saturday, March 10, 2012

Groovy: Regular Expressions and Multiple Lines

Regular expressions are sometimes used on text that spans multiple lines, which Groovy has support for. I had to search for how to enable multi-line searching, so I thought it would be good to post here.

To allow the expression to span multiple lines we can add (?ms) to the beginning of the expression.

Take the following example, where want to grab the entire book element from a single-line XML document:

    def xml = "<library><book><title>Effective Java</title><author>Bloch</author></book></library>"
def matcher = xml =~ /<book>.*<\/book>/
matcher.size() > 0 ? matcher[0] : "NOTHING"

This gives us an entire book:

    <book><title>Effective Java<title><author>Bloch<author><book>

If the XML was to span multiple lines however, we end up with NOTHING:

    def xml = """<library>
<book>
<title>Effective Java</title>
<author>Bloch</author>
</book>
</library>"""
def matcher = xml =~ /<book>.*<\/book>/
matcher.size() > 0 ? matcher[0] : "NOTHING"

Now if we add the (?ms), we will still get an entire book entry:

    def xml = """<library>
<book>
<title>Effective Java</title>
<author>Bloch</author>
</book>
</library>"""
def matcher = xml =~ /(?ms)<book>.*<\/book>/
matcher.size() > 0 ? matcher[0] : "NOTHING"

The above results in:

  <book>
<title>Effective Java<title>
<author>Bloch<author>
<book>

If you have any other tips or another way to accomplish the same thing, please feel free to leave a comment.

Injecting a Hostname with Spring

Sometimes our applications are required to know the name of the host or server they are running on. Usually, the hostname can be attained using plain old Java, however, in this post, I'll demonstrate a way to inject the name of the host an application is running on using Spring. This may sound like a case of over-engineering, but the main advantage of doing so is we can save our code from knowing how to obtain the hostname and avoid having to catch any exceptions related to retrieving the hostname.

As a use case, I'll recall a project I was working on that was tasked with consuming a service that required a client identifier be passed along in the request. The requirement stated that the ID be unique for every request and contain the hostname of the caller for tracking purposes inside the service. The form of the ID would be:

    <hostname>:<request_number>

Yes, this requirement could be considered a case of internal requirement of the service being called leaking into the implementation of the caller, but this a requirement we could not work around. To start, it made sense to task the creation of the identifier to a separate object. To fulfull the requirement that the ID be unique, we could use a UUID. The ugly part is deriving the hostname. Here is a first pass at the new class:

    public class RequestIdentifier {

public String requestId() {
return new StringBuilder()
.append(hostname())
.append(':')
.append(uuid())
.toString();
}

private String hostname() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException uhe) {
return defaultHostName;
}
}

private String uuid() {
return UUID.randomUUID().toString();
}

private static final String defaultHostName = "myHost";
}

Here we're forced to catch an UnknownHostException. As we still want the request to be made in the unlikely event that the exception is thrown, we default to a hostname (which would probably indicate the calling application) so that processing can proceed. We could improve on this implementation by caching the result of the first hostname lookup, but the potential for the exception to be thrown at least once would still exist.

Having to catch and deal with the exception places a burden on the class and adds complexity. Additionally, to fully cover the class during unit testing, we will have to find a way to simulate the exception, which could be difficult since the call InetAddress.getLocalHost() is static.

It might be better if the class was given its hostname, simplifying the code greatly, and removing the need for the default:

    public class RequestIdentifier {

private String hostname; // setter omitted for brevity

public String requestId() {
return new StringBuilder()
.append(hostname)
.append(':')
.append(uuid())
.toString();
}

private String uuid() {
return UUID.randomUUID().toString();
}
}

To make this situation usable, we can inject the hostname into the class:

    <beans xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="requestIdentifier" class="org.prystasj.service.validation.RequestIdentifier">
<property name="hostname" ref="hostname"/>
</bean>

<bean id="hostname" factory-bean="localhost" factory-method="getHostName"/>

<bean id="localhost" class="java.net.InetAddress" factory-method="getLocalHost"/>
</beans>

Now if there is an issue retrieving the hostname, we will know when the application starts up, before any processing is requested, and we have a cleaner, more usable class for creating the request identifier.

Monday, March 5, 2012

Subversion: Setting the MIME Type Property

As I'm tired of having to look this up every now and then when I need it, here's an example for how to add the MIME type for a file in Subversion:

 $ svn propset svn:mime-type "text/html" src/site/resources/design.html

The above command will cause the HTML file to be loaded as HTML in a browser when it is linked to in Subversion in the event your browser would like to display it as plain text.

Saturday, February 18, 2012

Linux: Burning an ISO Image from the Command Line

Here's a little tip (and reminder for myself) if you ever need to burn an ISO image to CD from the command line:

  $ cdrecord -v -eject speed=<speed> dev=<cdrom device> </path/to/iso>

Here's an example I used to burn the latest copy of Linux Mint Debian:

 $ cdrecord -v -eject speed=48 dev=/dev/cdrom \
/home/prystasj/Downloads/linuxmint-12-gnome-cd-nocodecs-64bit.iso

No GUI needed!

Addressing Database Connection Timeouts with c3p0

Many of our web applications run in Apache Tomcat and communicate with a MySQL database to persist data. After leaving one such development instance of an application up overnight, I was greeted with an error message when after trying to access it the next day. Looking at the Tomcat log, I found the following exception message:

   Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: 
The last packet successfully received from the server was 241,479,103 milliseconds ago.
The last packet sent successfully to the server was 241,479,103 milliseconds ago. is longer than the server configured value of 'wait_timeout'.
You should consider either expiring and/or testing connection validity before use in your
application, increasing the server configured values for client timeouts, or using the
Connector/J connection property 'autoReconnect=true' to avoid this problem.

The application was using commons-dbcp from the Apache Commons project. Below was the Spring configuration of the data source that connected to the database.

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${batch.jdbc.driver}" />
<property name="url" value="${batch.jdbc.url}" />
<property name="username" value="${batch.jdbc.user}" />
<property name="password" value="${batch.jdbc.password}" />
</bean>

Apparently, the connection to the database had timed out and needed to reconnect. After some searching, several posts mentioned that adding autoReconnect=true to the end of the database URL would fix the problem, but an exception would still be thrown before a reconnect is attempted.

A more popular answer seemed to be replacing the use of commons-dbcp with c3p0. I swapped out the dependency on commons-dbcp with:

    <dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
<scope>runtime</scope>
</dependency>

Followed by a new definition of the data source:

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${batch.jdbc.driver}" />
<property name="jdbcUrl" value="${batch.jdbc.url}" />
<property name="user" value="${batch.jdbc.user}" />
<property name="password" value="${batch.jdbc.password}" />
<property name="maxPoolSize" value="${mysql.db.maxPoolSize}"/>
<property name="maxIdleTime" value="${mysql.db.maxIdleTime}"/>
<property name="maxConnectionAge" value="${mysql.db.maxConnectionAge}"/>
<property name="acquireRetryAttempts" value="${mysql.db.acquireRetryAttempts}"/>
<property name="maxIdleTimeExcessConnections" value="${mysql.db.max.idle.time.excess.connections}"/>
<property name="idleConnectionTestPeriod" value="${mysql.db.idle.connection.test.period}"/>
<property name="preferredTestQuery" value="${mysql.db.preferred.test.query}"/>
<property name="testConnectionOnCheckout" value="${mysql.db.test.connection.on.checkout}"/>
<property name="testConnectionOnCheckin" value="${mysql.db.test.connection.on.checkin}"/>
<property name="checkoutTimeout" value="${mysql.db.checkout.timeout}"/>
</bean>

As you can see, there are lot more properties that can be set on the ComboPooledDataSource. The following additional properties settings appear to do the trick, although I must admit not spending much time yet fine tuning them:

    mysql.db.maxPoolSize = 10
mysql.db.maxConnectionAge = 0
mysql.db.acquireRetryAttempts = 5
mysql.db.max.idle.time.excess.connections = 300
mysql.db.idle.connection.test.period = 540
mysql.db.preferred.test.query = SELECT 1
mysql.db.test.connection.on.checkout = false
mysql.db.test.connection.on.checkin = false
mysql.db.checkout.timeout = 60000
mysql.db.maxIdleTime = 500

For now, the connection issue has been resolved in the application. Hope this helps someone out in a similar situation. Thanks for reading.

Saturday, January 14, 2012

Xerces Parsing and the Dreaded FWK005 Exception

One of the Java/Groovy applications I'm currently works with multiple threads. In each thread, an XML service response is marshalled into an object using a method similar to:

    private def messageObjectFrom(String responseXml) {
def jaxbElement = (JAXBElement) unmarshaller().unmarshal(readerFor(responseXml))
(MessageType) jaxbElement.value
}

Under a reasonable amount of load (several threads), the application would report the following exception during an execution of the method:

    javax.xml.bind.UnmarshalException: null
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:315) ~[na:1.6.0_24]
...
Caused by: org.xml.sax.SAXException: FWK005 parse may not be called while parsing.
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source) ~[com.springsource.org.apache.xerces-2.8.1.jar:na]
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source) ~[com.springsource.org.apache.xerces-2.8.1.jar:na]
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:211) ~[jaxb-impl-2.1.13.jar:2.1.13]
... 43 common frames omitted

I've seen the error in the past when parsing XML in a multi-threaded application using Xerces. Several mailing lists have had questions about this error over the years which point to a concurrency issue in the Xerces parser. In my application, the parser is used inside multiple threads.

Most of the postings suggest synchronizing access to the parser. I attempted to do so by adding the synchronized keyword to the method signature:

    synchronized private def messageObjectFrom(String responseXml) {
def jaxbElement = (JAXBElement) unmarshaller().unmarshal(readerFor(responseXml))
(MessageType) jaxbElement.value
}

This indeed did resolve the issue as I haven't run into a FWK005 error since. Its unfortunate the parser itself is not thread-safe, but this solution will do for me for now.

Hope this may help someone else who runs into a similar situation. Thanks!