Wednesday, June 5, 2013

Jersey, JAXB and json with generics and inheritance

A month or two ago I ran into an issue where I was marshalling Objects to json using Jersey with JAXB annotations on my pojos but only the Super Class attributes were being marshalled. I have uploaded some code to github to demonstrate this:

https://github.com/nebnagrom/jaxbInheritance

In this contrived example we have a Super Class House which has a member variable which is a String and an @XmlRootElement annotation. There are three child Classes of House:
  • BlueHouse which has an additional Integer
  • RedHouse which has an additional String
  • GreenHouse which has an additional Boolean
We then also have a HousingEstate<T extends House> which wraps a typed collection of houses. In this example it has no behavior but in the situation I had we had behavior on this collection as well.

The issue occured once I started trying to return HousingEstate objects from my RESTful resource. When you invoked the resource you only got back member variables from the House class, i.e. something like this:

 {"houses":[{"houseName":"first blue"},{"houseName":"2 blue"}]}

 When what I wanted was more like:

{"houses":[{"houseName":"first blue", "blueAttribute":1},
           {"houseName":"2 blue", "blueAttribute":2}]}
 
After a bit of digging I found that I needed to add another annotation on the House class - @XMLSeeAlso like this:

@XmlSeeAlso({ GreenHouse.class })

After I added that I started getting the results I wanted.

I also tried this without generics or just using the Super Class but this did not work either. Interestingly I found that:
  1. Using no generics meant that I got House member variables only, even when I annotated BlueHouse with annotation and added BlueHouses to the collection
  2. Using the parent class as the Generic gave me Marshalling exceptions, probably to be expected though.
I haven't really tried to dig into what is going on here, I assume that there is something with generics and type erasure that makes it impossible for JAXB / Jackson to know that there is a child class that it should be looking at for the marshalling.

Stack trace of error you get with the House based version over the fold:


Thursday, February 7, 2013

Cryptography in Java

I spent an evening recently playing around with cryptography in Java. I had to look up something similar for work and then it piqued my interest so I had a bit of a play with it.

What I was looking to do was AES encrypt a file using a key derived from a passphrase. After some digging around it seems that the way to create a key is to use the PKCS #5 algorithm and hash the result. This can be done in Java with a key factory using the algorithm PBKDF2WithHmacSHA1:

    private static SecretKey generatePBKKey(String password) throws NoSuchAlgorithmException, InvalidKeySpecException {

        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        SecureRandom rand = SecureRandom.getInstance("SHA1PRNG");
        byte[] salt = new byte[16];
        rand.nextBytes(salt);
        KeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), salt, 2, 128);
        SecretKey generatedKey = keyFactory.generateSecret(pbeKeySpec);

        SecretKey encKey = new SecretKeySpec(generatedKey.getEncoded(), "AES");

        return encKey;
    }


This key can then be used to initialise a AES Cipher which you can then encrypt the file with using a CipherOutputStream. Creating the AES Cipher was done using AES with ECB (Electronic Code Book) and PKCS5 padding.

        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key);


 I wasn't sure what block mode and padding to use and this seemed to be what most use.

The best doco I could find from Oracle was the Java 6 guide which ran through the main classes - http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html

 The full code of what I ended up with is over the jump.


Thursday, January 3, 2013

Build failure in Windows with Maven

I had an 'interesting' problem with Maven and Windows today where the build was broken on a Windows machine but worked on Linux. All we were getting were weird cryptic errors that a class in the test directory could not resolve a class from the src directory. The build worked fine in the ide on windows just not when run on the command line.

Turns out the issue was that we had a lower case name for the package in src/main/resources but an upper case name in src/main/java. During the build the resources are copied over first this means that the directory was created as lower case. Then when the source was compiled it placed the class files in the lower case directory as Windows paths are not case sensitive.

For example we had src/main/java/FOO and src/main/resources/foo when this is built with maven you will get your class files compiled into the package 'foo' even though anything that imports this class will be looking for 'FOO'.

Hopefully this helps someone else so they don't spend a day pulling out their hair over this!

Thursday, November 22, 2012

Hibernate caching with multiple objects mapped to one table

I recently had to do some performance tuning on an old application which for some reason had a database table that was mapped to two different domain objects. The mapping is bizarre because the domain objects are actually the same thing but for some reason there are two representations in this application!

One thing I wanted to setup was the second level cache to see if this would improve performance however once I discovered the crazy mappings I wondered how hibernate was going to cache this.

I didn't have enough time to really dig into what Hibernate was doing but based on the cache logs it appears that it knows which tables the entities it is caching are from and invalidates the cache for both when one is updated. Interestingly it also maintains the query cache appropriately so that a fetch for one entity will prime the cache for the other!

I was pretty impressed by this as I was expecting these crazy mappings to confuse hibernate but it seemed to handle it fine. This was an older version though so hopefully it is still valid in the later releases.

If you are interested this was done using Hibernate 3.2 and eh cache 1.3 (ancient!).

Wednesday, October 31, 2012

The Business Rules Curmudgeon

Its been a while since my last post, in that time my wife and I have had a baby boy who was born in the 9th of June.

Something that I have been pondering for a while is how to reduce the number of small business rules that seem to creep into requirements. Taken individually these seem minor but as they add up you find yourself maintaining dozens of different small rules that in aggregate are complex. This is particularly the case where you have a feature that grows over time and you steadily add more pieces to it.

The part I struggle with is how to say no to these things without sounding like a curmudgeon. The upfront development cost is usually small but when multiplied out across analysis, testing and training materials. I haven't really worked out a way around this, small tasks will disappear within estimates and people often become fixed on their vision and persuading them that it is wrong is difficult or impossible.

Perhaps its time to embrace being a curmudgeon.

Thursday, May 10, 2012

Font Crashing / Terminating jvm in Linux with X11 forwarding

I ran into an issue recently where when a certain report was run on a specific server the jvm would disappear without a trace! There were no core dumps, no errors in logs just a 500 response from Apache  and the process was gone.

I struggled with this for a while as I could regularly reproduce the issue but only on one server. By pure co-incidence I could see the terminal when the application was started and there was a cryptic X11 error message:

X connection to localhost:10.0 broken (explicit kill or server shutdown)

This server also turned out to be one where we had to sudo su to a different user to start the application and had hacked around with the Magic Cookie for X11 forwarding. This mean that although I had X11 enabled on my session it was broken.

Removing the X11 forwarding from my ssh session fixed the issue. I never managed to work out if it was a bug in the JVM or if it was my broken X11 session sending a kill signal to the process,  full details of my digging over the jump.

Saturday, February 25, 2012

Java Puzzles

In the Java Specalists newsletter they had a link to some java puzzles from http://wouter.coekaerts.be/puzzles which were rather interesting. The first one had me for a while till I read the hints about hashset and I'm still not quite sure about the second puzzle.

My original solution used Thread.sleep which did not work but after some googling I changed it to wait on the sleeper which did work. I'm not exactly sure why this is but it is to do with Thread.sleep not releasing its lock on the synchronised block whereas the sleeper.wait means that the current thread is now waiting on the original thread.

Hopefully when they publish the solution it will be a bit more clear what is going on here.

package dream;

import sleep.Sleeper;

public class Dream {

    public void dream(Sleeper s) {

        DreamThread dreamThread = new DreamThread();
        dreamThread.sleeper = s;

        new Thread(dreamThread).start();
        try {
//             Thread.sleep(100);
            s.wait(100);
        } catch (InterruptedException e) {
        }
    }

    private class DreamThread extends Dream implements Runnable {

        private Sleeper sleeper;

        @Override
        public void run() {
            sleeper.enter(this);
        }

        public void dream(Sleeper s) {
           
            try {
//                 Thread.sleep(500);
                s.wait(500);
            } catch (InterruptedException e) {
            }
        }
    }
}