You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-user@axis.apache.org by Michael Thome <mt...@bbn.com> on 2005/03/08 22:33:05 UTC

Stupid question: how to deserialize/serialize axis data objects

Here's a stupid question - gotta be a faq, but darned if I can find the 
right keywords...

I'd like to be able to deserialize/serialize data in the form of 
wsdl2java-generated structures from/to arbitrary streams.  For instance, 
if I serialize such an object to a file, I would like to end up with an 
xml representation of the object in the file that conforms to the schema 
I used to generate the data structures.

I currently have a glacially-slow hack for deserialization involving 
setting up a dummy DeserializationContext and calling parse... but it is 
*horrendously* slow, seeming to spend all its time creating and 
releasing thousands of temporary Documents...  I'm clearly missing 
something here.


Thanks for any help,
    -Michael


Re: Stupid question: how to deserialize/serialize axis data objects

Posted by Michael Thome <mt...@bbn.com>.
I've made some progress on my own worth mentioning...

It turns out that the feature of my data that was causing axis so much 
trouble was the rather deep xml structure passed around by my schema 
(using xsd:any ##any):  NodeImpl.getOwnerDocument has spectacularly bad 
behavior on deep structures.
I've submitted a patch attached to jira ( 
http://issues.apache.org/jira/browse/AXIS-1862 ) that fixes this issue.

Along the way, I stumbled on an alternative implementation of 
deserialize that performed much better than either your or my original 
code... at least, until I fixed the NodeImpl performance bug.  
Essentially, I do the following:

      String mstr = ... // the message;
      Message m = new Message(mstr,true);
      m.setMessageContext(new MessageContext(new 
org.apache.axis.server.AxisServer()));
      javax.xml.soap.SOAPPart part = m.getSOAPPart();
      SOAPEnvelope e = (SOAPEnvelope) part.getEnvelope();
      SOAPBodyElement be = e.getFirstBody();
      MessageElement mel = findFirstArgument(be);
      Object result = mel.getValueAsType(myqn, myclass);

I found the basic structure in the axis unit test code.  Before I fixed 
the NodeImpl algorithm, this was around 100x faster than the approaches 
I tried before.

At any rate, using either the above code or my original code leaves me 
deserializing a bit more than 1000x faster than yesterday.  Can't 
complain too much about that... ;-)

Thanks,
    -Michael

Michael Thome wrote:

> Thanks for the examples.  I've got a few followups, if you don't mind...
>
> Peter Molettiere wrote:
>
>>
>> Chances are you're doing it right. My experience is that axis is 
>> pretty slow, especially if you have large object graphs to read and 
>> write. 
>
>
> I sure hope I'm not doing it right, though so far your solution and 
> mine performs about the same... that is, unacceptably slow by several 
> orders of magnitude - 4 minutes to deserialize a 1KB serialized message!
>
>

Re: Stupid question: how to deserialize/serialize axis data objects

Posted by Michael Thome <mt...@bbn.com>.
Thanks for the examples.  I've got a few followups, if you don't mind...

Peter Molettiere wrote:

>
> Chances are you're doing it right. My experience is that axis is 
> pretty slow, especially if you have large object graphs to read and 
> write. 

I sure hope I'm not doing it right, though so far your solution and mine 
performs about the same... that is, unacceptably slow by several orders 
of magnitude - 4 minutes to deserialize a 1KB serialized message!

> These two methods depend on the following code to register the object 
> types you'd like to serialize first:

I presume that these are filling up static structures referenced by the 
service instance?  Or is there something missing that links the service 
to the AxisServer parameter?

Could mis-registration of the types lead to poor performance somehow, or 
would it just plain fail?

Thanks much,
    -Michael


Re: Stupid question: how to deserialize/serialize axis data objects

Posted by Peter Molettiere <pi...@axonstudios.net>.
On Mar 8, 2005, at 1:33 PM, Michael Thome wrote:
> I'd like to be able to deserialize/serialize data in the form of 
> wsdl2java-generated structures from/to arbitrary streams.  For 
> instance, if I serialize such an object to a file, I would like to end 
> up with an xml representation of the object in the file that conforms 
> to the schema I used to generate the data structures.
>
> I currently have a glacially-slow hack for deserialization involving 
> setting up a dummy DeserializationContext and calling parse... but it 
> is *horrendously* slow, seeming to spend all its time creating and 
> releasing thousands of temporary Documents...  I'm clearly missing 
> something here.

Chances are you're doing it right. My experience is that axis is pretty 
slow, especially if you have large object graphs to read and write. 
Here's some code you look at to see if it helps. This is posted as part 
of a bug I opened dealing with large amounts of memory being used and 
released during the ser/deser process. It hasn't really been fixed 
aside from a few small patches which help a little.

You can look here for complete compilable code: 
http://issues.apache.org/jira/browse/AXIS-1771

These two methods depend on the following code to register the object 
types you'd like to serialize first:

	...
         ServiceFactory serviceFactory = null;
         Service service = null;
         try {
             serviceFactory = ServiceFactory.newInstance();
             service = serviceFactory.createService(new QName(endpoint, 
"MemoryTester"));
         } catch (ServiceException e) {
             e.printStackTrace();
             return;
         }

         TypeMappingRegistry registry = service.getTypeMappingRegistry();
         TypeMapping map = registry.getDefaultTypeMapping();
         map.register(Entity.class, qnEntity,
                 new 
org.apache.axis.encoding.ser.BeanSerializerFactory(Entity.class, 
qnEntity),
                 new 
org.apache.axis.encoding.ser.BeanDeserializerFactory(Entity.class, 
qnEntity)
         );
	....


Note that in this method you can swap out the StringWriter for a 
FileWriter to write to files:

     public String serialize( QName dataQName, Object data ) throws 
Exception {
         AxisServer server = new AxisServer();
         server.setOption(AxisEngine.PROP_DOMULTIREFS, Boolean.TRUE);
         MessageContext msgContext = new MessageContext(server);
         msgContext.setProperty(AxisEngine.PROP_DOMULTIREFS, 
Boolean.TRUE);
         SOAPEnvelope msg = new SOAPEnvelope();
         RPCParam arg = new RPCParam("Test", "struct", data);
         RPCElement body = new RPCElement("Test", "method1", new 
Object[]{arg});
         msg.addBodyElement(body);
         StringWriter writer = new StringWriter();

         SerializationContext context = new SerializationContext(writer, 
msgContext);

         msg.output(context);

         String messageStr = writer.toString();

         return messageStr;
     }

Here again you can swap out the StringReader for a FileReader:

     public Object deserialize( String messageStr ) throws Exception {
         AxisServer server = new AxisServer();
         server.setOption(AxisEngine.PROP_DOMULTIREFS, Boolean.TRUE);
         MessageContext msgContext = new MessageContext(server);
         msgContext.setProperty(AxisEngine.PROP_DOMULTIREFS, 
Boolean.TRUE);

         //System.err.println(messageStr);

         Reader reader = new StringReader(messageStr);
         DeserializationContext dser = new DeserializationContext
                 (new InputSource(reader), msgContext, 
org.apache.axis.Message.REQUEST);
         dser.parse();
         SOAPEnvelope env = dser.getEnvelope();

         RPCElement rpcElem = (RPCElement) env.getFirstBody();
         MessageElement struct = rpcElem.getChildElement(new 
QName("Test", "struct"));

         Object result = struct.getObjectValue();
         return result;
     }

--
Peter Molettiere
Senior Engineer
Truereq, Inc.
http://www.truereq.com/