Insights on Software Development and Architecture

ErionPC's weblog on software development

Monthly Archives: November 2008

GlassFish and XML serialization – reviewed

I keep finding work arounds to OpenESB-Glassfish bugs by chance. I am currently using;

Product Version: NetBeans IDE 6.1 (Build 200809100101)
Java: 1.6.0_04; Java HotSpot(TM) Client VM 10.0-b19
System: Windows XP version 5.1 running on x86; Cp1252; en_US (nb)

On a previous post I had written that as far as I knew by my experience, GlassFish doesn’t serialize business objects which inherit from other business objects. This is quite limiting in regards to software architecture and I really like using polymorphism.

I had been desperately trying to make my JAX-WS return xml-serialized business objects which I had defined, but without success, until I tried the following. I’ll need to give further details on this to make it clear. These are the business objects that I wanted to be serialized (click on the image to see it bigger).

streamhandler package class diagram

streamhandler package class diagram

My DataBlock objects are specialized into TrackDataBlock and MessageDataBlock and are composed by a DataBlockHeader and a RecordList. DataBlockHeader is specialized into TrackDataBlockHeader and MessageDataBlockHeader. RecordList is composed by a list of Records. A Record is an abstract BO which is made concrete by the types TrackIdRecord, TrackPointRecord, CellSwitchRecord and MessageRecord. The latter one is specialized further by TextMessageRecord. My objective is to have all this structure available as a return type for a JAX-WS -> consequently serialized into xml.

The first thing I did was refactoring all the java classes into the ‘Bean’ form. I then tried serializing a DataBlock, but got the incomprehensible exceptions:

javax.servlet.ServletException: java.lang.reflect.InvocationTargetException
	at com.sun.enterprise.webservice.monitoring.WebServiceTesterServlet.doPost(WebServiceTesterServlet.java:345)
	at com.sun.enterprise.webservice.monitoring.WebServiceTesterServlet.invoke(WebServiceTesterServlet.java:121)
	at com.sun.enterprise.webservice.EjbWebServiceServlet.service(EjbWebServiceServlet.java:140)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
	at com.sun.enterprise.web.AdHocContextValve.invoke(AdHocContextValve.java:114)
	at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
	at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
	at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:87)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
	at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
	at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
	at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
	at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
	at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
	at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
	at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
	at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:272)
	at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:637)
	at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:568)
	at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:813)
	at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)
	at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263)
	at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214)
	at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
	at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at com.sun.enterprise.webservice.monitoring.WebServiceTesterServlet.doPost(WebServiceTesterServlet.java:316)
	... 27 more
Caused by: com.sun.xml.ws.encoding.soap.DeserializationException: Failed to read a response: javax.xml.bind.UnmarshalException
 - with linked exception:
[javax.xml.bind.UnmarshalException: Unable to create an instance of ejb.easyict.it.track.Record
 - with linked exception:
[java.lang.InstantiationException]]
	at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:124)
	at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:89)
	at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:118)
	at $Proxy174.testSerializzazioneRecordList(Unknown Source)
	... 32 more
Caused by: javax.xml.bind.UnmarshalException
 - with linked exception:
[javax.xml.bind.UnmarshalException: Unable to create an instance of ejb.easyict.it.track.Record
 - with linked exception:
[java.lang.InstantiationException]]
	at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:421)
	at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:360)
	at com.sun.xml.bind.v2.runtime.BridgeImpl.unmarshal(BridgeImpl.java:120)
	at com.sun.xml.bind.api.Bridge.unmarshal(Bridge.java:233)
	at com.sun.xml.ws.client.sei.ResponseBuilder$DocLit.readResponse(ResponseBuilder.java:525)
	at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:121)
	... 35 more
Caused by: javax.xml.bind.UnmarshalException: Unable to create an instance of ejb.easyict.it.track.Record
 - with linked exception:
[java.lang.InstantiationException]
	at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:603)
	at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:244)
	at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java:570)
	at com.sun.xml.bind.v2.runtime.unmarshaller.StructureLoader.startElement(StructureLoader.java:181)
	at com.sun.xml.bind.v2.runtime.unmarshaller.ProxyLoader.startElement(ProxyLoader.java:55)
	at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:449)
	at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:427)
	at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.handleStartElement(StAXStreamConnector.java:275)
	at com.sun.xml.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:209)
	at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:358)
	... 39 more
Caused by: javax.xml.bind.UnmarshalException: Unable to create an instance of ejb.easyict.it.track.Record
 - with linked exception:
[java.lang.InstantiationException]
	... 49 more
Caused by: java.lang.InstantiationException
	at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:30)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
	at com.sun.xml.bind.v2.ClassFactory.create0(ClassFactory.java:123)
	at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.createInstance(ClassBeanInfoImpl.java:257)
	at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.createInstance(UnmarshallingContext.java:564)
	... 46 more

Then I declared simple test web methods on my WS which used each of the BOs as return types, starting from the leaves of the above architecture. I found that GlassFish would serialize them with no problems. Then I tried to serialize a generic list of different object types which inherited from the same object (like the different specialized types of Record). I found out that “magically” GlassFish serialized the list!! I then tried the final test -> serializing a DataBlock; it worked out fine!!

At this point I couldn’t help trying to comment out the test methods which used the bottom level BOs as return types and recompile. When I executed the method for serializing a DataBlock, I got the same exceptions as before!! This proved to me that as long as my JAX-WS declared methods which return the bottom level BOs, GlassFish would be happy to serialize even the higher level BOs.

I’d be happy if this helps out someone who’s trying to keep using polymorphism on a JAX-WS.

Happy days! 🙂