Wednesday, 24 April 2013

Reflecting on life, the Universe and what the hell is that BeanInfo class doing to my JSF!!!

As my career at my current employers comes to a close I have been revisiting all the Project sources that I have created for the company with an eye to making them suitable for handover to the guy taking them on when I leave.

In one of them I found a nice booby trap that causes an intermittent problem with a JSF based app.
Essentially a specific domain entity was being accused of not having a specific property by Glassfish but not all the time.

I checked, the property is there as it should be. But what the hell is this BeanInfo class doing here?

The BeanInfo class was also for the domain entity that was sometimes being accused of not having a property it actually did have. Armed with my trusty Sherlock Holmes Deerstalker and magnifying glass I had a look at it. Cause for the problem found! The PropertyDescriptor for the offending property was missing: the BeanInfo class was not in synch with the entity class that had since been changed.

But why would this cause JSF to sometimes complain?
Well with Introspection you can obtain information about a class with

    BeanInfo info = Introspector.getBeanInfo( SimpleBean.class );

where the bean info is used to obtain lists of fields, properties etc. What happens when you make the getBeanInfo call? Well the clever stuff under the hood checks in something called SimpleBeanBeanInfo.class exists in the same package as the class parameter. If one does not exist then one is automagically created for you and this is returned.

The inference here is that Mojarra, the Glassfish JSF Implementation, is doing similar things with Introspector as above but

  • Not all the time
    Or has a weird classloader thing going on so that the existing BeanInfo class is not found consistently
  • is picking up the out-of-synch BeanInfo class and causing the clever-under-the-hood stuff to appear broken.
Now before throwing the baby away with the bath water I also hunted around to see if deleting these things would have any inadvertant untoward effects on the rest of the system.

Sadly yes, another developer added a totally unneeded Replication framework for DTOs that was commited to the project repository and not the asylum where it belonged. Because this person is no longer with us it is my job to remove the junk.
Only good thing is no JUnit tests for this were added.... but that was also a bad thing.

Tuesday, 23 April 2013

A tale of detached Entities, identity and equals with JPA

I was asked to do update an old project of mine in order to accommodate some new requirements for a web application which manages manufacturing cycle times. Data about the resulting cycles is stored in a Database for analysis through another system.

The existing project was specifically designed with Cathode Dip Painting plants in mind and wasn't suitable for generic assembly line monitoring. In particular a requirement that the current cycle and production lot state be persisted through Web Application downtimes/restarts was new.

A majority of the new requirements were cosmetic and easily added without having to reach into the plumbing of the asynchronous progress state monitoring.

Yesterday however I added the cycle start persistence and suddenly everything broke. Granted I had things like telephone calls breaking my concentration but still I was flummoxed about why the Production Lot data was not being processed as expected.

Basically a Production Lot has a maxCycles and a currentCycle property.
When the currrent cycle completes, the currentCycle property is decremented. If this value is < 1, the current production lot is deleted and the next one is retrieved via JPA. The next cycle is then started.

So, being the optimist that I was and between phone calls I simply added a merge(ProductionLot entity).
This one line of code broke the app such that Production Lots were not being processed correctly.

After 2 hours bashing my head against the telephone I went home hoping that today would bring a fresh head and ideas to the problem.

This morning all sorts of light bulbs were lit up. In what way can an entity merge cause a problem like this... Consult the literature... lo and behold

The merge method of an EntityManager is used when you want to either update an Entity persistently OR when you want to attach the Entity to the current Persistent Context. It will also create a new Entity for the current Persistent Context if one does not exist (essentially equivalent to a persist method call). It also returns the Entity you merged. But, and this is what was causing me the problems, it returns the attached version of the entity and not the original.

Somewhere in my code I was checking for equality between the current Production Lot and one returned by the ProductionLot Stateless Session EJB. This worked before because the Production Lot only changed when the current one was exhausted and new one returned. In merging the current Production Lot I broke the semantics because the equals semantic was no longer strong enough.

So currentProductionLot != nextProductionLot && currentProductionLot.equals(nextProductionLot) need to be added.

This is something that is normally bread and butter to me but I still made the elemental mistake. Why?

Was it the telephone calls or the desire to leave before 19:00? No, actually it was a lack of preparation made when changing the actual semantics of the system.

On the face of things: never take for granted that a one line change will not profoundly change things. They will and the possibility should always be taken into consideration when making them.