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) {
            }
        }
    }
}

Wednesday, January 25, 2012

Hibernate Sequence generation

A while ago I was working with an older version of hibernate (3.3 I think) and had to do a few thousand inserts. Whilst hibernate is not necessarily the tool for this job I was using it to do the insertion and found it spent a large amount of time fetching the primary key id one by one from the database sequence.

To get around this you can use the TableHiLoGenrator but this means that your sequence values are not what you are actually inserting into the database which means that if you wanted to use the sequence later you will need to do some stuffing around.

I had a look at implementing my own sequence generator that relied on the sequence using an increment n and then the generator is configured with this value so that it only fetches the sequence value every n times. I got this working but then we ended up not using it as we found a better way of managing the bulk insertions.

Deadlocks in oracle 11g

We ran into an issue recently where we would get deadlocks on Oracle 11g but not on 10g. After some investigation it turns out there is a change in how Oracle locks rows in 11g which means that insertions to a table with a foreign key also lock the candidate key in the referenced table!

The fix was to add indexes to the column in the referenced table so that Oracle can use this instead of locking the row.

This blog post by Richard Foote had a good explanation of the issue.