Tuesday, 29 June 2010

A Daily WTF.....

Today a colleague of mine discovered this extremely nice piece of code in one of our classes:

public class ProductSpeedsUtil {
...
public static int[] getSpeed(String theMinSpeed){
int minSpeed = Integer.parseInt(theMinSpeed.trim());
return ProductSpeedsUtil.getSpeed(theMinSpeed);
}
...
}


Need I say that there was not a unit test (total coverage for the ~800,000 lines of code in the project is 2.6% :-) ) for that code...and that the code is not used anywhere..

Tuesday, 8 June 2010

Accessing JBoss (JMS) behind firewall

Recently we migrated a large portion of my employers applications from Weblogic 8 to JBoss 4. During this process we had to re-write some of the clients that are using JMS to send messages to our application.
Since the clients are mostly running Weblogic it was not an issue before, but with our JBoss servers running behind a firewall it was not a straight-forward operation to just add some client jars and change the endpoints.
This blog entry is a reminder for me what needs to be done to be able to access a JBoss JMS through a firewall.

First, let's take a look at the client libraries that are necessary to run a JBoss JMS client.
The naive approach was to pick the jbossall-client.jar from the client folder of the JBoss installation - but that will not work (allthough the name suggests it right? :))
I ended up with the following jars for my test client (pure Java application):
* jbossall-client.jar
* jboss-common-client.jar
* jboss-messaging-client.jar
* javassist.jar
* jboss-aop-jdk50.jar (from the server/default/deploy/jboss-aop-jdk50.deployer folder!)
* trove.jar (from the server/default/deploy/jboss-aop-jdk50.deployer folder!)
* log4j.jar

Of course the jbossall-client must NOT be used when running from another applicationserver since it contains (for example) most of the javax.* interfaces in JDK1.4 version (for JBoss 4). So for the application running in the Weblogic the final list looked like:
* concurrent.jar
* javassist.jar
* jboss-aop-jdk50.jar (from the server/default/deploy/jboss-aop-jdk50.deployer folder!)
* jboss-common-client.jar
* jboss-messaging-client.jar
* jboss-remoting.jar
* jnp-client.jar
* trove.jar (from the server/default/deploy/jboss-aop-jdk50.deployer folder!)

Now on to the actual JBoss configuration. Since JBoss uses 2 different ports for JNDI, one for lookup and one for RMI we had to open two ports in the firewall.

Relevant attributes in conf/jboss-service.xml are Port and RmiPort.

Now we could successfully list and retreive the objects in the JBoss JNDI. When we tried to create a Connection from the ConnectionFactory we got stuck in the firewall once more. After looking in the firewall logs we realized that the JBoss server opened "random" ports back to the client for communication, which obviously won't work through a firewall.
The server/default/deploy/jboss-messaging.sar/remoting-bisocket-service.xml contains the configuration for this feature, and the ports must be specified otherwise JBoss will use "random" ports. The relevant attributes are serverBindPort and secondaryBindPort.

Setting the ports in the configuration file as well as using the correct jars solved our problems.

Wednesday, 12 May 2010

Sed magic

Yesterday I had to add a maven dependency to a lot of pom.xml files in our repository. Since I'm a lazy developer I naturally wanted to use some kind of find/grep/sed magic to do the trick.
In search of a solution I learned a neat sed magic:
find . -mindepth 2 -name "pom.xml" -exec sed -i '/<dependencies>/ r /tmp/data' {} \;

This will find all pom.xml files I'm interested in, and then find the <dependencies> tag and INSERT the lines found in the /tmp/data file.

Probably should do a man sed and spend an hour or two to learn some more magic :)

Sunday, 23 August 2009

XML posts on Blogger

Some of my posts contains XML I've had to convert the XML tags. Since I'm lazy, and tend to forget how I did it the last time , I obviously need to put a link here to a page that d

Saturday, 22 August 2009

Log4j, Maven Findbugs and custom Checkers

Lately I've been hit hard with how most Java developers using Log4j have no understanding of what happens when passing a Throwable to the log method.
For example:

Logger log = Logger.getLogger(getClass());
try {
someNiceMethod();
} catch (Exception e) {
log.error(e);
}

This will result in Log4j calling getMessage() on the Exception, thus losing all stacktraces and so on, making it harder to find the bug in the code. More info here.
Since this occured a few times in our code base, I decided to make a Findbugs custom checker that looked for this pattern.
The implementation was rather simple, I will probably enhance it to find further patterns that I want to disallow in the future. I tried it using the Findbugs GUI and it worked like a charm, but since we are using Maven to build our code I wanted to extends Findbugs with my custom Checker. This proved to be harder than I suspected.
According to the findbugs-maven-plugin documentation I'm supposed to pass the name of the jar file to my configuration in the tag.

<plugin>
<groupid>org.codehaus.mojo</groupid>
<artifactid>findbugs-maven-plugin</artifactid>
<version>2.1</version>
<configuration>
<pluginlist>myDetectors.jar</pluginlist>
</configuration>
</plugin>

This doesn't feel very "Mavenish"? Does anyone know how I can use it with Maven artifacts? I would like to configure something like this:

<plugin>
<groupid>org.codehaus.mojo</groupid>
<artifactid>findbugs-maven-plugin</artifactid>
<version>2.1</version>
<configuration>
<pluginlist>nu.sunfire.findbugs:myDetectors:1.0</pluginlist>
</configuration>
</plugin>

Since the Findbugs-maven-plugin is opensource I might have to fix this myself :)

Tuesday, 19 May 2009

JDK Proxies and catching (correct) Exceptions

Recently I discovered that JDK proxies behave a little weird if not implemented "correctly".
We have a logging proxy that will perform auditlogging for components in our system, so we simply create JDK proxies around our components and let the proxy log.
When checking logs on our servers I discovered that we got some strange Exceptions that were logged.
This is how the code looks like (more or less):


public final Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
try {
return method.invoke(wrappedObject, args);
} finally {
log();
}
}


What was logged in the log was always InvocationTargetException, with the actual Exception that was thrown by the method as a nested Exception.
This is not what I expected, and all my clients got InvocationTargetExceptions from the method call, which of course were not caught and hence logged by the application server...

So the "correct" way to write a JDK proxy seems to be:

public final Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
try {
return method.invoke(wrappedObject, args);
} catch (final InvocationTargetException t) {
throw t.getCause();
} finally {
log();
}
}


This will throw the correct exception. Perhaps one should check to see if the exception really is an InvocationTargetException or not?
More information here.

Wednesday, 4 March 2009

Maven Findbugs

Since we're using Maven to build our projects and we want a certain degree of code quality we using FindBugs.
Today I got hit hard with it since generated code is not always (never?) of good enough quality for Findbugs.
I couldn't easily get Findbugs not to check the generated files, since they have to built in order for the rest of the codebase to build.
Looking at the Findbugs manual I came across Filters which saved the day.
Now I could define packages that I don't want Findbugs to check.

First, create a file with the filter definition:

<findbugsfilter>
<match>
<package name="~nu\.sunfire\.entity.*">
</match>
</findbugsfilter>


Second, configure Maven:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.0-SNAPSHOT</version>
<configuration>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.0-SNAPSHOT</version>
<configuration>
<threshold>Low</threshold>
<effort>Default</effort>
<omitVisitors>FindDeadLocalStores,UnreadFields
</omitVisitors>
<onlyAnalyze>nu.sunfire.-</onlyAnalyze>
<excludeFilterFile>sunfire/findbugs-excludes.xml</excludeFilterFile>
<relaxed>false</relaxed>
<findbugsXmlOutput>true</findbugsXmlOutput>
<xmlOutput>true</xmlOutput>
</configuration>
</plugin>