resty-gwt

"Abstract classes must be annotated with JsonTypeInfo" compiling DTO structure


I have a quite simple DTO structure composed of an interface, an abstract class implementing it and a hierarchy of classes under the abstract class. The interface:

public interface InterfaceDTO {}

The abstract class:

import org.codehaus.jackson.annotate.JsonSubTypes;
import org.codehaus.jackson.annotate.JsonSubTypes.Type;
import org.codehaus.jackson.annotate.JsonTypeInfo;

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "json_type")
@JsonSubTypes({
    @Type(value = DataDTO.class, name = "DataDTO"),
    @Type(value = VectorDTO.class, name = "VectorDTO") })
public abstract class AbstractDTO implements InterfaceDTO {}

First level classes:

public class DataDTO extends AbstractDTO {
  private Short answerId;
  private String clientKey;
  private String answerText;
  .....

public class VectorDTO extends AbstractDTO {
  private Vector<InterfaceDTO> answers;

  public VectorDTO() {
    answers = new Vector<InterfaceDTO>();
  }

Second level class:

public class DataWithReplyDTO extends DataDTO {
  private String replyData;

And finally, restygwt JSON enc/dec code:

public interface InterfaceDTOCodec extends JsonEncoderDecoder<InterfaceDTO> {}
...
InterfaceDTOCodec codec = GWT.create(InterfaceDTOCodec.class);      
VectorDTO dto = new VectorDTO();
JSONValue json = codec.encode(dto);
InterfaceDTO other = codec.decode(json);
...

When I compile from eclipse with GWT 2.6.1 and restygwt I get:

Compiling module com.test.web.MyApp
  Computing all possible rebind results for 'com.test.web.client.activity.InitActivity.InterfaceDTOCodec'
    Rebinding com.test.web.client.activity.InitActivity.InterfaceDTOCode
      Invoking generator org.fusesource.restygwt.rebind.JsonEncoderDecoderGenerator
        Generating: com.test.web.client.activity.InitActivity_InterfaceDTOCodec_Generated_ExtendedJsonEncoderDecoder_
          checking: org.fusesource.restygwt.client.JsonEncoderDecoder, type: class com.google.gwt.dev.javac.typemodel.JParameterizedType
          Generating: com.test.web.shared.dto.InterfaceDTO_Generated_JsonEncoderDecoder_
            [ERROR] Abstract classes must be annotated with JsonTypeInfo
  [ERROR] Errors in 'com/test/web/client/activity/InitActivity.java'
    [ERROR] Line 55: Failed to resolve 'com.test.web.client.activity.InitActivity.InterfaceDTOCodec' via deferred binding
  [WARN] For the following type(s), generated source was never committed (did you forget to call commit()?)
    [WARN] com.test.web.client.activity.InitActivity_InterfaceDTOCodec_Generated_ExtendedJsonEncoderDecoder_
    [WARN] com.test.web.shared.dto.InterfaceDTO_Generated_JsonEncoderDecoder_

Following the guide, I added annotations to the abstract class but still the strange error message. Any help?

References: http://resty-gwt.github.io/documentation/restygwt-user-guide.html RestyGWT Polymorphic Encode/Decode issues when using an interface instead of an abstract class


Solution

  • I ended up with the classic Trial and error and kind of ignoring the docs from restygwt. Here is what I did in order to make it work:

    1. Deleted the abstract class and moved the annotations to the interface. This behaviour is not very clear in the official doc: "The super class that the other classes inherit must be an abstract class and annotated like the example below"
    2. Of course changed classes to implement the interface instead of extending the abstract class
    3. Added @Type(value = DataWithReplyDTO.class, name = "DataWithReplyDTO"), to the interface @JsonSubTypes list

    I used the following encoder/decoder declaration in my unit test and it worked:

    public interface InterfaceDTOEncoderDecoder extends JsonEncoderDecoder<InterfaceDTO> {}
    

    Bottom line: it seems you can have several levels of inheritance under an interface and it still works as long as you declare all types in the interface as @JsonSubTypes