Mantis Bugtracker
  

Viewing Issue Simple Details Jump to Notes ] View Advanced ] Issue History ] Print ]
ID Category Severity Reproducibility Date Submitted Last Update
0001015 [Resin] minor always 03-24-06 10:53 03-30-06 15:17
Reporter ferg View Status public  
Assigned To ferg
Priority normal Resolution fixed  
Status closed   Product Version
Summary 0001015: burlap deserialization
Description (rep by Jerry Tian)

I am using Spring with Burlap and Hessian to expose my service to
remote clients. At first, all the development is focused on the
realization with Hessian, and my unit test all passed with it. Since
it is easy to switch the Hessian exporter with Burlap exporter in
Spring, I simply switch the exporter to Burlap and test it with my
unit test, unfortunately, some of my test failed. I used a sniffer to
capture the Burlap packet, also the source code of Burlap(however, the
link to test package is dead, anyone could provide a valid one?),and here is my
analyse and fix:

here is the packet which made the Burlap deserializer throw a
"Operation not supported" exception:

<burlap:call>
       <method>process</method>
       <map>
               <type>com.tribe.sp.common.ServiceRequest</type>
               <string>serviceId</string><int>1</int>
               <string>servicePassword</string><string>5ae0c1c8a5260bc7b6648f6fbd115c35</string>
               <string>requestServiceName</string><string>hello</string>
               <string>contentObj</string><string>jerry</string>
       </map>
</burlap:call>

and my exported service is just a simple interface:

public interface ServiceProcessor {
       public ServiceResponse process(ServiceRequest request);
}

the parameter object type of the 'process' method is as plain as below:
public class ServiceRequest {
       private int serviceId;
       private String servicePassword;
       private String requestServiceName;
       private Object contentObj;

       public String getRequestServiceName() {
               return requestServiceName;
       }
       public void setRequestServiceName(String action) {
               this.requestServiceName = action;
       }
       public Object getContentObj() {
               return contentObj;
       }
       public void setContentObj(Object contentObj) {
               this.contentObj = contentObj;
       }
       public int getServiceId() {
               return serviceId;
       }
       public void setServiceId(int serviceId) {
               this.serviceId = serviceId;
       }
       public String getServicePassword() {
               return servicePassword;
       }
       public void setServicePassword(String servicePassword) {
               this.servicePassword = servicePassword;
       }
}

I have looked into the code, and the problem is, take a string for
example, the serializer will recognize the object of a string as
internal supported string type and serialize it enclosed in the
<map><string>string literal</string></map> tags, but when the
deserializer find it is a general object(according to the <map></map>
tags) to desrialize, it dosn't understand the <string></string> tags
at all, and treat it as illegal operation. so are the other burlap
internal supported types.

my fix to the problem is to modify one method in BurlapInput.java:
/**
        * Reads an object from the input stream with an expected type.
        *
        * modified!
        *
        * it can not correctly restore a internal burlap
        * supported Object type cast to Object, for example, a method
        * like &quot;void process(Object obj)&quot; exposed through burlap, and
        * the parameter of obj is given as follow:
        *
        * String s = &quot;hi&quot;;
        * Object obj = (Object) s;
        * x.process(obj);
        *
        * when serialize the obj, the serialization detect it is a string
        * type and use a internal type to serialize it, but when deserializing,
        * burlap didn't recognize it(according to the prototype of
x.process method),
        * and it just call this method try to desrialize it, thus it fails.
        *
        * I think it is reasonable to add internal type support to this
method too, since
        * it is the most generic &quot;Object&quot;.
        *
        * yes, it is added! and it works.
        *
        */
       public Object readObject(Class cl) throws IOException {
               if (cl == null)
                       return readObject();

               int tag = parseTag();
               switch (tag) {
                       case TAG_NULL:
                               expectTag(TAG_NULL_END);
                               return null;

                       case TAG_MAP: {
                               String type = readType();
                               Deserializer reader;
                               reader =
_serializerFactory.getObjectDeserializer(type);

                               if (cl != reader.getType() &&
cl.isAssignableFrom(reader.getType()))
                                       return reader.readMap(this);

                               reader = _serializerFactory.getDeserializer(cl);

                               return reader.readMap(this);
                       }

                       case TAG_LIST: {
                               String type = readType();
                               int length = readLength();

                               Deserializer reader;
                               reader =
_serializerFactory.getObjectDeserializer(type);

                               if (cl != reader.getType() &&
cl.isAssignableFrom(reader.getType()))
                                       return reader.readList(this, length);

                               reader = _serializerFactory.getDeserializer(cl);

                               return reader.readList(this, length);
                       }

                       case TAG_REF: {
                               int ref = parseInt();

                               expectTag(TAG_REF_END);

                               return _refs.get(ref);
                       }

                       case TAG_REMOTE: {
                               String type = readType();
                               String url = readString();

                               expectTag(TAG_REMOTE_END);

                               return resolveRemote(type, url);
                       }
                       case TAG_BOOLEAN: {
                               int value = parseInt();
                               expectTag(TAG_BOOLEAN_END);
                               return new Boolean(value != 0);
                       }

                       case TAG_INT: {
                               int value = parseInt();
                               expectTag(TAG_INT_END);
                               return new Integer(value);
                       }

                       case TAG_LONG: {
                               long value = parseLong();
                               expectTag(TAG_LONG_END);
                               return new Long(value);
                       }

                       case TAG_DOUBLE: {
                               double value = parseDouble();
                               expectTag(TAG_DOUBLE_END);
                               return new Double(value);
                       }

                       case TAG_DATE: {
                               long value = parseDate();
                               expectTag(TAG_DATE_END);
                               return new Date(value);
                       }

                       case TAG_XML: {
                               return parseXML();
                       }

                       case TAG_STRING: {
                               _sbuf.setLength(0);

                               String value = parseString(_sbuf).toString();

                               expectTag(TAG_STRING_END);

                               return value;
                       }

                       case TAG_BASE64: {
                               byte[] data = parseBytes();

                               expectTag(TAG_BASE64_END);

                               return data;
                       }
               }

               _peekTag = tag;

               Object value =
_serializerFactory.getDeserializer(cl).readObject(this);

               return value;
       }

in fact, all the code is copied from anther readObject method in this
file, and after this modification, all my unit tests passed
successfully.
Additional Information
Attached Files

- Relationships

There are no notes attached to this issue.

- Issue History
Date Modified Username Field Change
03-24-06 10:53 ferg New Issue
03-30-06 15:17 ferg Assigned To  => ferg
03-30-06 15:17 ferg Status new => closed
03-30-06 15:17 ferg Resolution open => fixed
03-30-06 15:17 ferg Fixed in Version  => 3.0.19


Mantis 1.0.0rc3[^]
Copyright © 2000 - 2005 Mantis Group
26 total queries executed.
24 unique queries executed.
Powered by Mantis Bugtracker