Insights on Software Development and Architecture

ErionPC's weblog on software development

Tag Archives: Glassfish

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! 🙂

Advertisements

Glassfish and XML Serialization

Having worked with the .NET frameworks in Visual Studio, whenever I implemented an ASPNET web service I was used to return generalized collections of my business objects which were declared in nested layers and I never had any problems because the returned values would always be xml-serializations of my classes. However, having to work with GlassFish now I found that serialization isn’t that immediate. After days of looking for documentation on this issue, I discovered that Glassfish doesn’t serialize your objects unless they respect the java-beans structure (private fields, public getters and setters in CamelCase and a no-parameter constructor) and (obviously) they need to implement the java.io.serializable interface. I also found that nested classes can’t be serialized (but maybe I’m wrong).

I’ve written a more recent post on this topic. Click here to view it.

Silverlight and JAX-WS Web Services?

This is a tough one,

for the last two days I’ve been trying to make a Silverlight client consume a Glassfish JAX-WS Web Service, but without any success till a few hours ago. I tried the procedure indicated at “Call a Java EE Web service from Silverlight Client” on the MSDN blogs (the only one I could find) but it didn’t work. That blog post says that the solution is copying an xml file called clientaccesspolicy.xml in the docroot folder of the GlassFish domain where the web service resides. I found that when you add a GlassFish WS web reference to a Silverlight project, Visual Studio (I use the Professional 2008 version) creates a configuration file that gives compilation problems, unless you manually change the “customBinding” to “basicHttpBinding” and manually add the endpoint. When I ran the Silverlight client it launched a CommunicationException due to a “cross-domain configuration error”. I had already copied the clientaccesspolicy.xml file on the docroot folder of my GlassFish domain as indicated on the msdn blog.

Then, after some hours, I had the idea of creating an ASPNET Web Service which acts as a wrapper for my GlassFish WS, but I found out that neither that would work and it would launch the same exception! I started to have strong suspicions that this was a Silverlight bug. I completely erased the existing project which didn’t work and created a new one, adding the web references normally (not manually). In this way it finally worked!

Just out of curiosity I tried adding another web reference to the Silverlight project to my original GlassFish WS, having to change the configuration file manually as before. It not only didn’t work, but it also caused the other (.NET) web service to stop working, even after I had removed it completely and had restored the configuration file to the original state. It’s so ridiculous! Silverlight is good looking, but still not serious enough for interoperability.

Cheers.