I think you did yourself a disservice by wrapping these two issues
into a single message - it ends up being way too much text to read and
otherwise eager volunteers just skip it.

The first issue looks like you're not detaching your entities before
serializing them.  This is a JDO issue.  I suggest dropping JDO and
using something simpler like Objectify ;-)

The issue with exceptions looks more serious.  This is something that
will need to be fixed in Hessian (or your custom serializer).  If you
cut down your issue to just this, you might get better results from
Caucho.

Jeff

On Tue, Jun 15, 2010 at 1:55 PM, dilbert <dilbert.elbo...@gmail.com> wrote:
> Hi Jeff. I was hoping to hear from You since I saw that You solved
> some GAE issues on the hessian-interest list. I already posted the
> issue on the hessian-interest list here:
> http://maillist.caucho.com/pipermail/hessian-interest/2010-June/000908.html
> I also posted several forum questions:
> http://forum.caucho.com/showthread.php?t=9999
> http://groups.google.com/group/google-appengine-java/browse_thread/thread/c4fb4f414c425ca1
> And a few bug reports:
> http://bugs.caucho.com/view.php?id=4061
> http://code.google.com/p/googleappengine/issues/detail?id=3305
> The posts actually describe two issues one with arraylist
> serialization and the other with exception serialization. The posts
> also include test projects with code that reproduces the issues. I
> also managed to solve the issue today by using a custom serializer.
> Here is how. First the Serializer:
>
> public class ThrowableSerializer extends AbstractSerializer {
>   �...@override
>    public void writeObject(Object obj, AbstractHessianOutput out)
> throws IOException {
>        if (obj != null) {
>            final Class cl = obj.getClass();
>            if (out.addRef(obj))
>                return;
>            int ref = out.writeObjectBegin(cl.getName());
>            Throwable tr = (Throwable) obj;
>            ByteArrayOutputStream bos = new ByteArrayOutputStream();
>            ObjectOutputStream oos = new ObjectOutputStream(bos);
>            try {
>                oos.writeObject(tr);
>
>                if (ref < -1) {
>                    out.writeString("value");
>                    out.writeBytes(bos.toByteArray());
>                    out.writeMapEnd();
>                } else {
>                    if (ref == -1) {
>                        out.writeInt(1);
>                        out.writeString("value");
>                        out.writeObjectBegin(cl.getName());
>                    }
>                    out.writeBytes(bos.toByteArray());
>                }
>            } finally {
>                oos.close();
>                bos.close();
>            }
>        } else
>            out.writeNull();
>    }
> }
>
> The other class we need is the Deserializer:
> public class ThrowableDeserializer extends AbstractDeserializer {
>    //private static final Logger l =
> Logger.getLogger(ThrowableDeserializer.class.getName());
>
>   �...@override
>    public Class getType() {
>        return Throwable.class;
>    }
>
>   �...@override
>    public Object readMap(AbstractHessianInput in) throws IOException
> {
>        int ref = in.addRef(null);
>        byte[] initValue = null;
>        while (!in.isEnd()) {
>            String key = in.readString();
>
>            if (key.equals("value"))
>                initValue = in.readBytes();
>            else
>                in.readString();
>        }
>
>        in.readMapEnd();
>        ByteArrayInputStream bis = new
> ByteArrayInputStream(initValue);
>        ObjectInputStream ois = new ObjectInputStream(bis);
>        try {
>            Object value = ois.readObject();
>            in.setRef(ref, value);
>            return value;
>        } catch (ClassNotFoundException e) {
>            throw new RuntimeException(e);
>        } finally {
>            ois.close();
>            bis.close();
>        }
>    }
>
>   �...@override
>    public Object readObject(AbstractHessianInput in, Object[]
> fieldNames)
>            throws IOException {
>        int ref = in.addRef(null);
>        byte[] initValue = null;
>        for (Object o : fieldNames) {
>            if (o instanceof String) {
>                final String key = (String) o;
>                if (key.equals("value"))
>                    initValue = in.readBytes();
>                else
>                    in.readObject();
>            }
>        }
>        ByteArrayInputStream bis = new
> ByteArrayInputStream(initValue);
>        ObjectInputStream ois = new ObjectInputStream(bis);
>        try {
>            Object value = ois.readObject();
>            in.setRef(ref, value);
>            return value;
>        } catch (ClassNotFoundException e) {
>            throw new RuntimeException(e);
>        } finally {
>            ois.close();
>            bis.close();
>        }
>    }
> }
> I'm not sure if the readMap part is actually needed since I rearranged
> this code from another example. Also, a ThrowableSerializerFactory is
> needed:
> public class ThrowableSerializerFactory extends
> AbstractSerializerFactory {
>   �...@override
>    public Serializer getSerializer(Class cl) throws
> HessianProtocolException {
>        if (Throwable.class.isAssignableFrom(cl)) {
>            return new ThrowableSerializer();
>        }
>        return null;
>    }
>
>   �...@override
>    public Deserializer getDeserializer(Class cl) throws
> HessianProtocolException {
>        if (Throwable.class.isAssignableFrom(cl)) {
>            return new ThrowableDeserializer();
>        }
>        return null;
>    }
> }
> What this code essentially does is take a Throwable (which implements
> Serializable), serializes it to a byte[] and pushes it over to the
> other side. This serialization does not use the problematic
> setAccessible method (like com.caucho.hessian.io.ThrowableSerializer)
> and works correctly on App engine (I tested it). The only part left to
> do is to plug all this into the servlet and the client. Here is how to
> do it on the servlet:
> public class Service extends HessianServlet implements IService {
>   �...@override
>    public void init(ServletConfig config) throws ServletException {
>        super.init(config);
>        getSerializerFactory().addFactory(new
> ThrowableSerializerFactory());
>    }
>    // implement IService methods...
> }
>
> And here is how to do it on the client:
> String url = "http://whatever.appspot.com/service";;
> HessianProxyFactory factory = new HessianProxyFactory();
> factory.getSerializerFactory().addFactory(new
> ThrowableSerializerFactory());
> IService service = (IService) factory.create(IService.class, url);
>
> I would like to hear your opinion on this solution. Do You see any
> problems with it? Also, when could we expect to see a solution in
> Hessian? If You need any other information please ask. Thank You for
> Your time.
>
> D.
> On Jun 15, 7:34 pm, Jeff Schnitzer <j...@infohazard.org> wrote:
>> Perhaps try posting the stacktrace to the hessian-interest list?
>> Someone (possibly me) might be able to fix this issue.
>>
>> Jeff
>>
>> On Thu, Jun 10, 2010 at 9:13 AM, dilbert <dilbert.elbo...@gmail.com> wrote:
>> > First I'd like to explain what I mean by RPC. I'd like to be able to
>> > write interfaces like this (simple Java interface):
>>
>> > public interface EchoService {
>> >  String echo(String message);
>> > }
>>
>> > The framework would allow the creation of client classes that would
>> > handle the serialization from/to the RPC service. Of course the
>> > framework should support the serialization of ArrayLists, HashMaps and
>> > other collections and should also support the serialization of objects
>> > marked with the "java.io.Serializable" interface (or some other
>> > interface).
>> > We would create the RPC Client this way:
>>
>> > EchoService echoService =
>> > RpcClientFactory.createInstance(EchoService.class,"http://bla.com/
>> > smartApp/echo");
>>
>> > And of course use it this way:
>>
>> > String echoMessage = echoService.echo("The message !!!");
>>
>> > The server side servlet would implement the previously mentioned
>> > interface.
>> > public class Service extends WhateverServlet implements EchoService {
>> >   �...@override
>> >    String echo(String message) {
>> >        return "server sends:" + message;
>> >    }
>> > }
>>
>> > A few additional nice features to have would be:
>> > -support for asynchronous calls (where the developer would provide a
>> > callback for handling the result, similar to GWT RPC)
>> > -the developers should be able to access the RPC client somehow to be
>> > able to handle Cookies or other http headers.
>> > -the client side should be usable from Android.
>>
>> > After a long search I have found that the framework that most closely
>> > matches these requirements is Hessian (http://hessian.caucho.com/). It
>> > uses a binary protocol so it should be very fast and it works on
>> > Android. AFAIK it does not support async calls. However, not all is
>> > well. The current Hessian implementation does not handle exceptions
>> > well. It throws a SecurityException like this:
>>
>> > java.lang.SecurityException: java.lang.IllegalAccessException:
>> > Reflection is not allowed on private java.lang.Throwable
>> > java.lang.Throwable.cause
>>
>> > I considered GWT RPC for a while but it does not have a proper Java
>> > client or I could not find one. So I wanted to ask is there any other
>> > library that could be used in this case? Could the App engine team
>> > write such a library and add it to the SDK. Any suggestions?
>>
>> > --
>> > You received this message because you are subscribed to the Google Groups 
>> > "Google App Engine for Java" group.
>> > To post to this group, send email to 
>> > google-appengine-j...@googlegroups.com.
>> > To unsubscribe from this group, send email to 
>> > google-appengine-java+unsubscr...@googlegroups.com.
>> > For more options, visit this group 
>> > athttp://groups.google.com/group/google-appengine-java?hl=en.
>>
>>
>
> --
> You received this message because you are subscribed to the Google Groups 
> "Google App Engine for Java" group.
> To post to this group, send email to google-appengine-j...@googlegroups.com.
> To unsubscribe from this group, send email to 
> google-appengine-java+unsubscr...@googlegroups.com.
> For more options, visit this group at 
> http://groups.google.com/group/google-appengine-java?hl=en.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to google-appengine-j...@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.

Reply via email to