How to define AutoBeanFactory?

1,317 views
Skip to first unread message

dhoffer

unread,
Oct 18, 2012, 4:46:32 PM10/18/12
to google-we...@googlegroups.com
I'm trying to figure out how to use AutoBeanFactory to decode a JSONString, e.g.

AutoBean<IPayload> autoBean = AutoBeanCodex.decode(myAutoBeanFactory, IPayload.class, jsonValue.stringValue());
IPayload payload = autoBean.as();

What I'm not clear on is how to define myAutoBeanFactory?

I understand that's an interface passed to GWT.create(MyAutoBeanFactory.class), but what methods does MyAutoBeanFactory need?

My IPayload and its content is defined as:

public interface IPayload extends Serializable {
    IGWTMessage[] getMessages();
    void setMessages(IGWTMessage[] messages);
}

public interface IGWTMessage extends IGWTMessage {
    IUUIDReference getMessageId();
    void setMessageId(IUUIDReference id);
}

Then there are about a dozen derived interfaces that extend IGWTMessage and then each of those has its concrete implementation class.

How can I handle this with AutoBeanFactory/JSON?

Btw, this used to be just Serialized and marshaled that way but now I'm trying to use a different approach that requires JSON.  Also, if there was a way to just do a regular Java binary serialization that would be fine too as I could then turn that into a Base64 encoded string and send just that via JSON...then do the reverse on the server.  (But I haven't yet seen a way to do Java binary serialization in the GWT client.) 

Thanks,
-Dave







Andrea Boscolo

unread,
Oct 19, 2012, 4:40:37 AM10/19/12
to google-we...@googlegroups.com
Have you read http://code.google.com/p/google-web-toolkit/wiki/AutoBean ?
I think this can help to get you started.

David Hoffer

unread,
Oct 19, 2012, 9:40:54 AM10/19/12
to google-we...@googlegroups.com
I did find that but it doesn't explain much at all. Regarding the
AutoBeanFactory it just says:

interface MyFactory extends AutoBeanFactory {
// Factory method for a simple AutoBean
AutoBean<Person> person();

// Factory method for a non-simple type or to wrap an existing instance
AutoBean<Person> person(Person toWrap);
}

There is no explanation of what person() is even in this overly simplified case.

Am I to assume that person() refers to getPerson() and
setPerson(Person) java bean methods on another object? If so, does
AutoBeanFactory require strict java beans naming conventions? In my
case I don't have Java beans, I just have a serailizable POJO with an
interface. E.g. getMessages() returns an IGWTMessage. How can I
configure AutoBeanFactory to handle this?

-Dave
> --
> You received this message because you are subscribed to the Google Groups
> "Google Web Toolkit" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/google-web-toolkit/-/pc_zKSdHe9YJ.
>
> To post to this group, send email to google-we...@googlegroups.com.
> To unsubscribe from this group, send email to
> google-web-tool...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/google-web-toolkit?hl=en.

Thomas Broyer

unread,
Oct 19, 2012, 10:04:28 AM10/19/12
to google-we...@googlegroups.com


On Friday, October 19, 2012 3:42:35 PM UTC+2, dhoffer wrote:
I did find that but it doesn't explain much at all.  Regarding the
AutoBeanFactory it just says:

interface MyFactory extends AutoBeanFactory {
  // Factory method for a simple AutoBean
  AutoBean<Person> person();

  // Factory method for a non-simple type or to wrap an existing instance
  AutoBean<Person> person(Person toWrap);
}

There is no explanation of what person() is even in this overly simplified case.

Am I to assume that person() refers to getPerson() and
setPerson(Person) java bean methods on another object?

Not at all. It's a factory method for an AutoBean<Person>, the implementation will be generated by the call to GWT.create() or AutoBeanFactorySource.create().
Person itself is an interface with property accessors (getters and setters). Yet again, the implementation of that interface will be generated; when you "generate" the AutoBeanFactory that has a method referencing it (when creating the AutoBeanFactory above, it needs an implementation of Person, so it'll generate it at the same time as the implementation of the AutoBeanFactory).
Actually, you don't have to actually call those factory methods, they can be there only so that the AutoBeanFactory knows the interface to be treated as an AutoBean, so that it'll generate an implementation for it and you'll be able to deserialize it from JSON.
 
If so, does
AutoBeanFactory require strict java beans naming conventions?  In my
case I don't have Java beans, I just have a serailizable POJO with an
interface.  E.g. getMessages() returns an IGWTMessage.  How can I
configure AutoBeanFactory to handle this?

interface MyAutoBeanFactory extends AutoBeanFactory {
    AutoBean<IPayload> payload();
}

But in your case that won't work: AutoBeans don't support arrays (IGWTMessage[]), only lists, sets and maps (e.g. List<IGWTMessage>)

dhoffer

unread,
Oct 19, 2012, 10:20:58 AM10/19/12
to google-we...@googlegroups.com
Thanks that really helps.  Is just defining the top level interface enough, e.g.

interface MyAutoBeanFactory extends AutoBeanFactory {
    AutoBean<IPayload> payload();
}

Or would I need to include factory methods for all nested interfaces contained/referenced by IPayload?  E.g.

interface MyAutoBeanFactory extends AutoBeanFactory {
    AutoBean<IPayload> payload();
    AutoBean<IGWTMessage> message();
    AutoBean<IGWTInitializationMessage> initializationMessage();
    AutoBean<IGWTViewInstruction> viewInstruction();
    AutoBean<IGWTViewReference> viewReference();
    AutoBean<IGWTViewInstructionParameter> viewInstructionParameter();
    AutoBean<IGWTViewInstructionResult> viewInstructionResult();
}

Regarding AutoBeans not supporting arrays, if I can get it to support my data structure types, I can convert the logic to use a List instead of the array.

Thanks,
-Dave

Thomas Broyer

unread,
Oct 19, 2012, 10:54:23 AM10/19/12
to google-we...@googlegroups.com


On Friday, October 19, 2012 4:20:58 PM UTC+2, dhoffer wrote:
Thanks that really helps.  Is just defining the top level interface enough, e.g.

interface MyAutoBeanFactory extends AutoBeanFactory {
    AutoBean<IPayload> payload();
}

Or would I need to include factory methods for all nested interfaces contained/referenced by IPayload?


AutoBeans cannot decode a IPayload if it doesn't know how to decode a IGWTMessage, so obviously dependencies are resolved transitively, and it's enough to just reference IPayload here. 

dhoffer

unread,
Oct 19, 2012, 4:16:23 PM10/19/12
to google-we...@googlegroups.com
With the factory created I'm not getting any json data decoded.  The decoded type is something like ipt.tas.app.ui.gwt.client.IPayloadAutoBean$2@2dbb24d0 instead of the expected IPayload.  I'm not sure what this is ...but all of the data that IPayload's methods should have contained is null.

However that was with, on the server, the data being encoded into JSON using Gson, e.g. 
Gson gson = new Gson();
String asJson = gson.toJson(str);

I figured that maybe the AutoBeans framework requires that it be used to encode the data if its being used to decode the data so I replaced the server code with:
AutoBean<IPayload> bean = AutoBeanUtils.getAutoBean(payload);
String asJson = AutoBeanCodex.encode(bean).getPayload();

However bean is always null so this doesn't work either.  I don't see a way to specify the same factory when encoding (like used when decoding).  So I'm at a lost how to use AutoBean, there are no compile time errors or warnings just doesn't work at runtime with no obvious reason.  It seems AutoBean can't encode or decode my domain objects.

I'm at a loss on how to convert my domain objects into JSON using GWT.

-Dave

Jens

unread,
Oct 19, 2012, 4:59:49 PM10/19/12
to google-we...@googlegroups.com
AutoBeanUtils.getAutoBean(payload); will only return an AutoBean<IPayload> instance if the method parameter already belongs to an AutoBean (see JavaDoc).

So things would look like the following (from memory, hopefully its correct):

//GWT client side
MyAutoBeanFactory factory = GWT.create(MyAutoBeanFactory.class);

//JVM = server side
MyAutoBeanFactory factory = AutoBeanFactorySource.create(MyAutoBeanFactory.class);

// now following code is the same on GWT client side and JVM/server side

// creates a new empty AutoBean
AutoBean<IPayload> payloadAutoBean = factory.getPayload();

// creates a new AutoBean that contains the same data as the provided parameter
AutoBean<IPayload> payloadAutoBean = factory.getPayload(yourPayloadPojoThatImplementsIPayload);



// Optional: Modify / get data from your bean
IPayload payload = payloadAutoBean.as();
payload.setData(...);


// serialize

// If you still have access to payloadAutoBean then use it
String json = AutoBeanCodex.encode(payloadAutoBean).getPayload();

// If you dont have access to payloadAutoBean but only to IPayload (maybe you are in a different method) 
// and you know 'payload' comes from an AutoBean
AutoBean<IPayload> bean = AutoBeanUtils.getAutoBean(payload);
String json = AutoBeanCodex.encode(bean).getPayload();


// deserialize
AutoBean<IPayload> deserializedAutoBean = AutoBeanCodex.decode(factory, IPayload.class, json);
IPayload deserializedPayload = deserializedAutoBean.as();


I hope that helps.

-- J.

David Hoffer

unread,
Oct 20, 2012, 2:31:39 PM10/20/12
to google-we...@googlegroups.com
Yeah that helps a ton. That's by far the best explanation of how to
use AutoBeans that I have seen, I recommend that this get added to the
current docs on the web.


That being said I'm still getting an error in one place. In this call
in my code AutoBeanCodex.encode(payloadAutoBean)...several levels down
in the call stack it makes this call:

AutoBeanUtils.getAutoBean(value) which returns null, and this result
is the input for the second parameter in the next method.

public static void doEncode(EncodeState state, AutoBean<?> bean) {
PropertyGetter e = new PropertyGetter(state);
try {
bean.accept(e);
} catch (HaltException ex) {
throw ex.getCause();
}
}

Which causes a NPE at bean.accept(e);

The 'value' parameter passed into AutoBeanUtils.getAutoBean(value)
above is a class defined as:

public class GWTInitializationMessage implements IGWTInitializationMessage {
private IGWTSessionReference sessionReference;
private IUUIDReference messageId;

public GWTInitializationMessage() {
this(null, null);
}

public GWTInitializationMessage(IUUIDReference messageId,
IGWTSessionReference sessionReference) {
this.sessionReference = sessionReference;
this.messageId = messageId;
}

public void setSessionReference(IGWTSessionReference sessionReference) {
this.sessionReference = sessionReference;
}

public IGWTSessionReference getSessionReference() {
return this.sessionReference;
}

public IUUIDReference getMessageId() {
return this.messageId;
}

public void setMessageId(IUUIDReference id) {
this.messageId = id;
}
}

public interface IUUIDReference extends Serializable {
String getUUIDAsString();
}

public interface IGWTSessionReference extends IsSerializable {
String getSessionId();
}

Which seems like it should be straightforward to handle...any ideas
why AutoBeans would fail to handle this?

Thanks,
-Dave
> --
> You received this message because you are subscribed to the Google Groups
> "Google Web Toolkit" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/google-web-toolkit/-/9Q1MicpiDeYJ.

Thomas Broyer

unread,
Oct 22, 2012, 5:19:42 AM10/22/12
to google-we...@googlegroups.com


On Saturday, October 20, 2012 8:33:04 PM UTC+2, dhoffer wrote:
Yeah that helps a ton.  That's by far the best explanation of how to
use AutoBeans that I have seen, I recommend that this get added to the
current docs on the web.


That being said I'm still getting an error in one place.  In this call
in my code AutoBeanCodex.encode(payloadAutoBean)...several levels down
in the call stack it makes this call:

AutoBeanUtils.getAutoBean(value) which returns null, and this result
is the input for the second parameter in the next method.

Reply all
Reply to author
Forward
0 new messages