Archive

Archive for May, 2009

DTO in anger

May 30th, 2009 1 comment

In this article, I will show you how in JEE architecture using lighweight frameworks, creating a DTO layer is an anti-pattern.

Once upon a time, Sun created standards to interact with the database tier: those where Entity EJB. In their version 2, an EJB entity is a Java class that is mapped to a specific table through the EJB jar deployment descriptor. This class is the true entity Bean. Since EJB calls can be made across different Virtual Machines, through the RMI protocol, no instances of Bean are truly returned.

What is really passed to the client is a reference to another interface instance. This interface must be a subinterface of javax.ejb.EJBObject or, if running inside the same Virtual Machine, of javax.ejb.EJBLocalObject. The latter is equivalent to the first, only it removes the checked RemoteException from all methods signatures.

The following snippet shows an typical direct invocation of an Entity bean:

Context context = new InitialContext();

// Entity bean home interface
ClientHome myClientHome = (ClientHome) PortableRemoteObject.<span>narrow</span><span>(</span>context.lookup("java:comp/env/ejb/ClientSessionBean"), ClientHome.class);

// Entity bean local interface
Client myClient = myClientHome.findByPrimaryKey(53);

// Get accounts of client
List myAccounts = myClient.getAccounts()

Now, this client can have accounts. In order to get its accounts list, the client code has to call the getAccounts() method. But each call to the local interface is potentially remote, creating network overhead.

// This call is no simple method invocation but is made over the network
List myAccounts = myClient.getAccounts()

Wouldn’t it be better if I could get all of the needed data, the client and its accounts, in one network call? This is the goal of the DTO pattern. By the way, it is interesting to note that what call Design Pattern in an EJB environment are less so and more a rule to enforce in order to increase performance – end parenthesis.

So, DTO is about creating a C-like structure class (no behaviours, only accessor methods). For a client call, an instance of this DTO is created. Then it is set, eventually by multiple database access in the remote JVM and returned in one network response to the client. The main idea here being: the purpose of the DTO is to minify the amount of network traffic, that’s all.

A good question to be asked is why should local EJB implement this pattern. It could be argued that tomorrow, all calls could be made to a remote server, and that it is good sense to keep this option open.

But in using lightweight persistence frameworks, such as Hibernate or TopLink, there wouldn’t be anymore need for DTO, would it? Astonishingly enough, that’s the second time I come upon a project that still implements this pattern though it doesn’t use EJB Entities as their persistence layer. In the latest occurence, model objects that are loaded through Hibernate are converted into DTO. What are the drawbacks?

  • a performance overhead of converting objects from and to the database,
  • a cost overhead in the initial configuring of the conversion framework (Dozer in this case),
  • a cost overhead in each subsequent modifying of the database structure that should be mirrored in DTO.

What are the advantages of keeping a DTO pattern? The point is, I don’t know (which is a more polite form of ‘None’), but from my point of view, it clearly looks like an anti-pattern.

To go further:

Categories: Java Tags: , , ,

Web Start your legacy applications

May 24th, 2009 1 comment

In this article, we’ll see how to make an old-but-useful legacy Java application into a brand new Java Web Start (JWS for short) application.

JWS is an often overlooked technology that works miracles. With it, you can deploy any Java application, as easily as you would a web one: with the only update server-side and still your application running client-side, with access to all its resources. JWS has two main features: the downloading of the application to the client and the launching of said application. It’s a technology available in the Java Runtime Environment since version 1.4.

JWS is based on a most specific deployment descriptor in JNLP format. This DD takes place along the many JARs of the application on the server. JNLP files are XML although there are no schemas published by Sun, either in DTD or XSD format. You may find some schemas made by people on the web.

In order to publish your application through JWS, you’ll need to perform the following steps.

Step 1: Make your code available as a web resource

I sold you that any Java application can be made available on the web. This means you’ll have to publish both your JAR itself and the associated JNLP.

  • /jnlp/@codebase specifies where the root directory lies
  • /jnlp/@href the name of the JNLP file under this root
  • /jnlp/resources/jar/@href the path to your JAR
<?xml version="1.0" encoding="utf-8"?>
<jnlp codebase="http://blog.frankel.ch/demo" href="launch.jnlp">
    <information>
        <title>Legacy Application</title>
        <vendor>Nicolas Frankel</vendor>
    </information>
    <resources>
        <jar href="myMainJar.jar" />
    </resources>
</jnlp>

Both /jnlp/information/title and /jnlp/information/vendor are required and will be shown in the JWS dialog menu.

Step 2: Adress a version of the JRE

Since you will make your application available, ask yourself which version will be used on the client’s computer. In essence, it will amount to 2 things:

  • /jnlp/@spec specifies the version of the JNLP XML format
  • /jnlp/resources/j2se/@version the needed version of the client JRE
<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.5+" codebase="http://blog.frankel.ch/demo" href="launch.jnlp">
    <information>
        <title>Legacy Application</title>
        <vendor>Nicolas Frankel</vendor>
    </information>
    <resources>
        <j2se version="1.5+" />
        <jar href="myMainJar.jar" />
    </resources>
</jnlp>

See how both can use the plus sign in order to indicate a minimum version.

You can even tell to JWS to redirect the browser to a JRE download page or download it automatically. Both are done through a combination of JavaScript and HTML.

Step 3: Reference dependent libraries and the Main Class

Usually, informations about the main class – the one containing the main method – and the JAR dependencies are specified either on the command line or in the JAR’s deployment descriptor.

Informations specified on the command line:

java -cp myMainJar.jar;lib/myFirstDependency.jar;lib/mySecondDependency.jar ch.frankel.blog.jws.MainClass

Informations specified in the MANIFEST.MF:

java -jar myMainJar.jar

META-INF/MANIFEST.MF in the JAR:

Manifest-Version: 1.0
Class-Path: lib/myFirstDependency.jar lib/mySecondDependency.jar
Main-Class: ch.frankel.blog.jws.MainClass

The first thing to understand is that JWS ignores what is written is the manifest. So, in either case, you have to tell Java Web Start the main class and your dependencies manually in the JNLP.

<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.5+" codebase="http://blog.frankel.ch/demo" href="launch.jnlp">
    <information>
        <title>Legacy Application</title>
        <vendor>Nicolas Frankel</vendor>
    </information>
    <resources>
        <j2se version="1.5+" />
        <jar href="myMainJar.jar" />
        <jar href="lib/myFirstDependency.jar" />
        <jar href="lib/mySecondDependency.jar" />
    </resources>
    <application-desc main-class="ch.frankel.blog.jws.MainClass" />
</jnlp>

Notice how both the JAR containing the main class and dependents JAR are referenced in the same fashion. The lib folder is for my own purpose only: JWS doesn’t differentiate based on where the JARs are located.

Step 4: Passing system properties to the JVM

Usually, system properties are passed to the JVM on the command line like this:

java -Dch.frankel.firstProp -Dch.frankel.secondProp=aValue -jar myMainJar.jar

This is done likewise in the JNLP:

<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.5+" codebase="http://blog.frankel.ch/demo" href="launch.jnlp">
    <information>
        <title>Legacy Application</title>
        <vendor>Nicolas Frankel</vendor>
    </information>
    <resources>
        <j2se version="1.5+" />
        <property name="ch.frankel.firstProp" />
        <property name="ch.frankel.secondProp" value="aValue" />
        <jar href="myMainJar.jar" />
        <jar href="lib/myFirstDependency.jar" />
        <jar href="lib/mySecondDependency.jar" />
    </resources>
    <application-desc main-class="ch.frankel.blog.jws.MainClass" />
</jnlp>

Step 5: Passing parameters to your application

Parameters are passed to your main method on the command line like this:

java -jar myMainJar.jar myFirstParam mySecondParam

This is done likewise in the JNLP:

<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.5+" codebase="http://blog.frankel.ch/demo" href="launch.jnlp">
    <information>
        <title>Legacy Application</title>
        <vendor>Nicolas Frankel</vendor>
    </information>
    <resources>
        <j2se version="1.5+" />
        <property name="ch.frankel.firstProp" />
        <property name="ch.frankel.secondProp" value="aValue" />
        <jar href="myMainJar.jar" />
        <jar href="lib/myFirstDependency.jar" />
        <jar href="lib/mySecondDependency.jar" />
    </resources>
    <application-desc main-class="ch.frankel.blog.jws.MainClass">
        <argument>myFirstParam</argument>
        <argument>mySecondParam</argument>
    </application-desc>
</jnlp>

Step 6: Signing your JARs

Java Web Start applications are meant to run in a sandbox since they are downloaded on the web where, by definition, all resources are unsafe. If your application doesn’t use potentially unsafe operations, well, that’s fine. If it does, you’ll have to explicitly ask for special permissions in the JNLP. Unsafe operations include: file access, clipboard use and so on.

<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.5+" codebase="http://blog.frankel.ch/demo" href="launch.jnlp">
    <information>
        <title>Legacy Application</title>
        <vendor>Nicolas Frankel</vendor>
    </information>
    <resources>
        <j2se version="1.5+" />
        <property name="ch.frankel.firstProp" />
        <property name="ch.frankel.secondProp" value="aValue" />
        <security>
            <all-permissions/>
        </security>
        <jar href="myMainJar.jar" />
        <jar href="lib/myFirstDependency.jar" />
        <jar href="lib/mySecondDependency.jar" />
    </resources>
    <application-desc main-class="ch.frankel.blog.jws.MainClass">
        <argument>myFirstParam</argument>
        <argument>mySecondParam</argument>
    </application-desc>
</jnlp>

There’s one big but: all all of your JARs must then be signed by the same certificate! It means that if you reference already-signed JARs, you must unsign them first and then sign them using an unique certificate.

If that is too much hassle for you, then you will need to change the litigious parts of your code and replace them with calls to the JNLP API. In that case, kiss good bye to your application’s ability to run outside a Web Start-context. Beware, the API is quite small.

Step 7: Enhance your user experience

Shortcuts, splash screen, ability to run off-line, Java Web Start provides them all. The following JNLP adds these features to the previous one:

<?xml version="1.0" encoding="utf-8"?>
<jnlp spec="1.5+" codebase="http://blog.frankel.ch/demo" href="launch.jnlp">
    <information>
        <title>Legacy Application</title>
        <vendor>Nicolas Frankel</vendor>
        <offline-allowed />
        <icon kind="splash" href="image/welcome.jpg" />
        <shortcut online="false">
            <desktop />
            <menu submenu="frankel dot ch"/>
        </shortcut>
    </information>
    <resources>
        <j2se version="1.5+" />
        <property name="ch.frankel.firstProp" />
        <property name="ch.frankel.secondProp" value="aValue" />
        <security>
            <all-permissions/>
        </security>
        <jar href="myMainJar.jar" />
        <jar href="lib/myFirstDependency.jar" />
        <jar href="lib/mySecondDependency.jar" />
    </resources>
    <application-desc main-class="ch.frankel.blog.jws.MainClass">
        <argument>myFirstParam</argument>
        <argument>mySecondParam</argument>
    </application-desc>
</jnlp>

Step 8: Remove bugs from your legacy code

In the context of Java Web Start, some legacy code may not run. For example, forget ClassLoader.getSystemResource(): replace it with the following snippet Thread.currentThread().getContextClassLoader().getResource() which will run in both JWS and local contexts. Remember, if you run into a problem, chances are someone did before you: Google is your friend here.

I hope this article convinced you that your legacy applications can be brought online with only minimal effort. Java Web Start is a standardized, cost-effective and technically sound solution to do this.

To go further:

Categories: Java Tags: , , , ,

JNA meets JNI

May 23rd, 2009 5 comments

I reccently stumbled upon a nice framework you’ll love if you ever have to work with native code. Before this framework, if you needed to call native code, you would use JNI. JNI uses a proved but complex and error-prone process.

First thing first, you write your Java classes like always. But for methods you want to delegate to native code, you use the native keyword and do not provide an implementation. Then, you call a JDK-provided executable named javah. This generates your C header file (*.h) and an empty stub implementation: you have to fill the voids. Finally, you compile both Java and C files.

At runtime, do not forget to load the library with System.loadLibrary("mylib"). Notice you do not provide the extension, the JVM does it automatically for you, depending on you platform (.dll on Windows, .so on Linux). Then call you Java class and it will magically delegate to your native code.

This whole process always frustrated me (and so, I can imagine, lots of developers) because of the following reasons:

  • since I’m a Java developer and not a C developer, I could never write good C code. It hurts my head to even consider memory allocations or to bring myself to think about function pointers ;-)
  • if I need to change the native Java method signature, I have to run the whole process again or change both header and C files without errors, and then compile everything again. In this case, I can’t stress out the importance of having a very automated build process or the adequate IDE (I tend toward the former)
  • last, but not least, what if I do not have access to the source C file? JNI can’t help you call Windows dll… or you have to write a proxy-like C file to do so

Rejoice people. Java.net brought you the solution. The answer to your problems is Java Native Access or JNA. Now calling a NTLM authentication or showing the running services inside your application will be a breeze. Let’s try to get informations about your computer running under Windows – sorry ‘Nix users.

The first thing is to know which function will get you there: such is the goal of the MSDN library. Now, create an interface, preferably name after the DLL you will use and make it inherit from com.sun.jna.Libray. Its methods will have to map exactly the name and the arguments of the DLL. For example, let’s say you want to display your computer’s name. Under Windows, there’s a method named GetComputerNameW() that is provided by kernel32.dll. So, you interface will have a method adequately named GetComputerNameW(). The Devil being in the details, you’ll have to map each parameter documented in MSDN on a parameter in your interface’s method’s signature. GetComputerNameW() takes 2 parameters: a LPTSTR (pointer to a char buffer) and a LPDWORD (pointer to a integer). Running to JNA documentation, the mapping in Java becomes a char[] and a com.sun.jna.ptr.IntByReference.

Your interface now looks like this:

public interface Kernel32 extends StdCallLibrary {

    int GetComputerNameW(char[] name, IntByReference number);

    // Other method mappings
    ...
}

Now, in order to access a Kernel32 reference, just use the following codeline. Under the table, it will bind our interface to the underlying implementation through a proxy:

Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);

This done, each subsequent call to kernel32′s GetComputerName() method will fill the char buffer with our computer’s name.

JNA still suffers from some drawbacks:

  • JNA usually performs 10x slower than JNI. It has some techniques to speed up execution, so if you are in a performance-aware environment, you’ll probably want to use them
  • it won’t make you a pro C programmer so very complex method signatures will throw you into frenzy: the harder part of the job will be mapping the datatypes from C to Java. This will probably frustrate you to no end since you will be seeing java.lang.UnsatisfiedLinkError: Error looking up function XXX: La procédure spécifiée est introuvable more often than not. In this case, call a C programmer for help!

The sources of this small project are provided Maven-style. Have fun with Java and Windows!

To go further:

Categories: Java Tags: , , , , , , ,

Theme change

May 21st, 2009 No comments

If you already visited here, you can clearly see something has changed. In order to celebrate my new job, Spring eternal and what have you, I changed my blog’s theme. I previously used Mandigo, which has many, many options but I grew tired of it. Mandigo is a beautiful theme but I wanted something more focused, that doesn’t take precedence over what is written. My choice went with iNove, even if I had to hack the theme PHP scripts to keep Goggle analytics scripts and favicon. It’s sober, modern and (I think) more oriented toward a geek’s blog.

Categories: Miscellaneous Tags: , ,

Mockito’ spy() method and Spring

May 21st, 2009 1 comment

Mockito is a mocking framework (see Two different mocking approaches) that is an offshoot of EasyMock. Whatever the mocking framework one uses, a common feature is the ability to mock interfaces, through the JDK Proxy class. This is well and nice, but one has to explicitly mock every method that one wants to use in the course of the test.

What if I want to mock an already existing implementation, with some methods providing behaviours that suit me ? Today, I ran across this case: Read more…