Problem getting polymorphism to work

210 views
Skip to first unread message

David Nouls

unread,
Mar 24, 2016, 6:36:26 AM3/24/16
to RestyGWT
I am using restygwt 2.1.1 (with GWT 2.8.0-beta1) and it does not seem to properly handle polymorphism. It's probably something I am doing wrong, but I followed the documentation and it still does not work.

We have event objects that all implement this interface:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
@JsonTypeIdResolver(EventTypeIdResolver.class)
public interface IEvent {
}



I created a resty resolver like this:

public class EventTypeIdGeneratorResty implements RestyJsonTypeIdResolver {
 
private final static Map<String, Class<?>> TYPE_MAP;
 
static {
   TYPE_MAP
= Maps.newHashMap();
   TYPE_MAP
.put(MessageLoad.class.getName(), MessageLoad.class);  
   TYPE_MAP
.put(MessageHandled.class.getName(), MessageHandled.class);
 
}

  @Override

 public Class<? extends TypeIdResolver> getTypeIdResolverClass() {

   return EventTypeIdResolver.class;

 }


 
@Override

 public Map<String, Class<?>> getIdClassMap() {

   System.out.println("getIdClassMap is called during GWT compilation");

   return TYPE_MAP;

 }

}


 



And I have the following in my application gwt.xml file: (sorry paste in groups on IE11 seems to be really bad, it does not allow me to remove these magic whitespace that are not in the orginal)

   <inherits name="org.fusesource.restygwt.RestyGWT"/>

   <extend-configuration-property

        name="org.fusesource.restygwt.jsontypeidresolver"

        value="




com.acme.cloud.ui.demo.server.api.EventTypeIdGeneratorResty"

/>


when I compile (using mvn) I don't see the System.out so I guess the class is not used at all.

the compiler gives me:

 Adding '5' new generated units

[INFO]       Tracing compile failure path for type 'com.acme.cloud.event.msghandler.MessageLoad_Generated_JsonEncoderDecoder_'

[INFO]          [ERROR] Errors in 'generated://61A2FB0EF300D37B474A4C68DC94E3C1/com/acme/cloud/event/msghandler/MessageLoad_Generated_JsonEncoderDecoder_.java'

[INFO]             [ERROR] Line 7: This method must return a result of type JSONValue

[INFO]             [ERROR] Line 14: This method must return a result of type MessageLoad

[INFO]       See snapshot: C:\Users\dnouls\AppData\Local\Temp\com.acme.cloud.event.msghandler.MessageLoad_Generated_JsonEncoderDecoder_9174915194281980093.java

[INFO]    [ERROR] Errors in 'generated://61A2FB0EF300D37B474A4C68DC94E3C1/com/acme/cloud/event/msghandler/MessageLoad_Generated_JsonEncoderDecoder_.java'

[INFO]       [ERROR] Line 7: This method must return a result of type JSONValue

[INFO]       [ERROR] Line 14: This method must return a result of type MessageLoad

[INFO]       See snapshot: C:\Users\dnouls\AppData\Local\Temp\com.acme.cloud.event.msghandler.MessageLoad_Generated_JsonEncoderDecoder_1156780688736935193.java

[INFO]    Tracing compile failure path for type 'com.acme.cloud.event.msghandler.MessageLoad_Generated_JsonEncoderDecoder_'

[INFO]       [ERROR] Errors in 'generated://61A2FB0EF300D37B474A4C68DC94E3C1/com/acme/cloud/event/msghandler/MessageLoad_Generated_JsonEncoderDecoder_.java'

[INFO]          [ERROR] Line 7: This method must return a result of type JSONValue

[INFO]          [ERROR] Line 14: This method must return a result of type MessageLoad

[INFO]    [ERROR] Hint: Check that the type name 'com.acme.cloud.event.msghandler.MessageLoad_Generated_JsonEncoderDecoder_' is really what you meant

[INFO]    [ERROR] Hint: Check that your classpath includes all required source roots


The generated files look like this:


package com.acme.cloud.event.msghandler;
public class MessageLoad_Generated_JsonEncoderDecoder_ extends org.fusesource.restygwt.client.AbstractJsonEncoderDecoder<com.acme.cloud.event.msghandler.MessageLoad> {
   public static final MessageLoad_Generated_JsonEncoderDecoder_ INSTANCE = new MessageLoad_Generated_JsonEncoderDecoder_();
 
  public com.google.gwt.json.client.JSONValue encode(com.acme.cloud.event.msghandler.MessageLoad value) {
    if( value==null ) {
      return getNullType();
    }
    com.google.gwt.json.client.JSONObject rc = new com.google.gwt.json.client.JSONObject();
  }
 
  public MessageLoad decode(com.google.gwt.json.client.JSONValue value) {
    if( value == null || value.isNull()!=null ) {
      return null;
    }
    com.google.gwt.json.client.JSONObject object = toObject(value);
  } 
}

What I am missing ?



David Nouls

unread,
Mar 24, 2016, 10:24:26 AM3/24/16
to RestyGWT
I got one step further.

I'm now using JsonTypeInfo.Id.CUSTOM and now it seems to pickup the JsonTypeIdResolver and the resty generator.

The implementation of JsonTypeIdResolver is using Reflections to find all subtypes of the given IEvent.class.
So now it seems to be able to generate the Json converters.... however... now it blows up with an IndexOutOfBounds during compilation:
[WARNING] Reflections found 25 IEvent subtypes
[WARNING] EventTypeIdGeneratorResty was created
[WARNING] Reflections found 25 IEvent subtypes
[WARNING] getIdClassMap is called during GWT compilation
[INFO]    Computing all possible rebind results for 'com.acme.cloud.ui.demo.client.api.IMessagesService'
[INFO]       Rebinding com.acme.cloud.ui.demo.client.api.IMessagesService
[INFO]          Invoking generator org.fusesource.restygwt.rebind.RestServiceGenerator
[INFO]             [ERROR] Generator 'org.fusesource.restygwt.rebind.RestServiceGenerator' threw an exception while rebinding 'com.acme.cloud.ui.demo.client.api.IMessagesService'
[INFO] java.lang.ArrayIndexOutOfBoundsException: -1
[INFO]  at java.util.ArrayList.elementData(ArrayList.java:418)
[INFO]  at java.util.ArrayList.get(ArrayList.java:431)
[INFO]  at org.fusesource.restygwt.rebind.JsonEncoderDecoderClassCreator.generateDecodeMethod(JsonEncoderDecoderClassCreator.java:475)
[INFO]  at org.fusesource.restygwt.rebind.JsonEncoderDecoderClassCreator.generate(JsonEncoderDecoderClassCreator.java:123)
[INFO]  at org.fusesource.restygwt.rebind.BaseSourceCreator.create(BaseSourceCreator.java:216)
[INFO]  at org.fusesource.restygwt.rebind.JsonEncoderDecoderInstanceLocator.getEncoderDecoder(JsonEncoderDecoderInstanceLocator.java:154)
[INFO]  at org.fusesource.restygwt.rebind.JsonEncoderDecoderInstanceLocator.encodeDecodeExpression(JsonEncoderDecoderInstanceLocator.java:198)
[INFO]  at org.fusesource.restygwt.rebind.JsonEncoderDecoderInstanceLocator.encodeExpression(JsonEncoderDecoderInstanceLocator.java:181)
[INFO]  at org.fusesource.restygwt.rebind.JsonEncoderDecoderClassCreator$1.execute(JsonEncoderDecoderClassCreator.java:319)
[INFO]  at org.fusesource.restygwt.rebind.JsonEncoderDecoderClassCreator$1.execute(JsonEncoderDecoderClassCreator.java:293)
[INFO]  at org.fusesource.restygwt.rebind.BaseSourceCreator.branch(BaseSourceCreator.java:150)
[INFO]  at org.fusesource.restygwt.rebind.BaseSourceCreator.branch(BaseSourceCreator.java:143)
[INFO]  at org.fusesource.restygwt.rebind.JsonEncoderDecoderClassCreator.generateEncodeMethod(JsonEncoderDecoderClassCreator.java:293)
[INFO]  at org.fusesource.restygwt.rebind.JsonEncoderDecoderClassCreator.generate(JsonEncoderDecoderClassCreator.java:121)
[INFO]  at org.fusesource.restygwt.rebind.BaseSourceCreator.create(BaseSourceCreator.java:216)
[INFO]  at org.fusesource.restygwt.rebind.JsonEncoderDecoderInstanceLocator.getEncoderDecoder(JsonEncoderDecoderInstanceLocator.java:154)
[INFO]  at org.fusesource.restygwt.rebind.JsonEncoderDecoderInstanceLocator.encodeDecodeExpression(JsonEncoderDecoderInstanceLocator.java:198)
[INFO]  at org.fusesource.restygwt.rebind.JsonEncoderDecoderInstanceLocator.encodeExpression(JsonEncoderDecoderInstanceLocator.java:181)
[INFO]  at org.fusesource.restygwt.rebind.RestServiceClassCreator.writeMethodImpl(RestServiceClassCreator.java:688)
[INFO]  at org.fusesource.restygwt.rebind.RestServiceClassCreator.generate(RestServiceClassCreator.java:304)
[INFO]  at org.fusesource.restygwt.rebind.BaseSourceCreator.create(BaseSourceCreator.java:216)
[INFO]  at org.fusesource.restygwt.rebind.RestServiceGenerator.generate(RestServiceGenerator.java:38)
[INFO]  at com.google.gwt.core.ext.IncrementalGenerator.generateNonIncrementally(IncrementalGenerator.java:40)
[INFO]  at com.google.gwt.dev.javac.StandardGeneratorContext.runGeneratorIncrementally(StandardGeneratorContext.java:745)
[INFO]  at com.google.gwt.dev.cfg.RuleGenerateWith.realize(RuleGenerateWith.java:103)
[INFO]  at com.google.gwt.dev.shell.StandardRebindOracle$Rebinder.rebind(StandardRebindOracle.java:78)
[INFO]  at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:262)
[INFO]  at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:251)
[INFO]  at com.google.gwt.dev.PrecompilationContextCreator$1.getAllPossibleRebindAnswers(PrecompilationContextCreator.java:86)
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.createStaticRebindExpression(UnifyAst.java:494)
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.createRebindExpression(UnifyAst.java:464)
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.handleMagicMethodCall(UnifyAst.java:589)
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.endVisit(UnifyAst.java:294)
[INFO]  at com.google.gwt.dev.jjs.ast.JMethodCall.traverse(JMethodCall.java:249)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
[INFO]  at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:118)
[INFO]  at com.google.gwt.dev.jjs.ast.JDeclarationStatement.traverse(JDeclarationStatement.java:49)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor$ListContext.traverse(JModVisitor.java:88)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.acceptWithInsertRemove(JModVisitor.java:331)
[INFO]  at com.google.gwt.dev.jjs.ast.JBlock.traverse(JBlock.java:92)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
[INFO]  at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:139)
[INFO]  at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:135)
[INFO]  at com.google.gwt.dev.jjs.ast.JMethodBody.traverse(JMethodBody.java:83)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
[INFO]  at com.google.gwt.dev.jjs.ast.JMethod.visitChildren(JMethod.java:730)
[INFO]  at com.google.gwt.dev.jjs.ast.JMethod.traverse(JMethod.java:722)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
[INFO]  at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst.mainLoop(UnifyAst.java:1378)
[INFO]  at com.google.gwt.dev.jjs.impl.UnifyAst.exec(UnifyAst.java:876)
[INFO]  at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.unifyJavaAst(JavaToJavaScriptCompiler.java:1442)
[INFO]  at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.constructJavaAst(JavaToJavaScriptCompiler.java:1254)
[INFO]  at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.precompile(JavaToJavaScriptCompiler.java:1174)
[INFO]  at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.precompile(JavaToJavaScriptCompiler.java:255)
[INFO]  at com.google.gwt.dev.Precompile.precompile(Precompile.java:255)
[INFO]  at com.google.gwt.dev.Precompile.precompile(Precompile.java:202)
[INFO]  at com.google.gwt.dev.Precompile.precompile(Precompile.java:143)
[INFO]  at com.google.gwt.dev.Compiler.run(Compiler.java:197)
[INFO]  at com.google.gwt.dev.Compiler.run(Compiler.java:156)
[INFO]  at com.google.gwt.dev.Compiler$1.run(Compiler.java:117)
[INFO]  at com.google.gwt.dev.CompileTaskRunner.doRun(CompileTaskRunner.java:55)
[INFO]  at com.google.gwt.dev.CompileTaskRunner.runWithAppropriateLogger(CompileTaskRunner.java:50)
[INFO]  at com.google.gwt.dev.Compiler.main(Compiler.java:124)
[INFO]    [ERROR] Errors in 'gen/com/acme/cloud/ui/demo/client/api/com_gwtplatform_mvp_client_DesktopGinjector_DesktopGinjectorGinjector_fragment.java'
[INFO]       [ERROR] Line 17: Failed to resolve 'com.acme.cloud.ui.demo.client.api.IMessagesService' via deferred binding
[INFO]    [WARN] For the following type(s), generated source was never committed (did you forget to call commit()?)
[INFO]       [WARN] com.acme.cloud.event.msghandler.MessageLoad_Generated_JsonEncoderDecoder_
[INFO]       [WARN] com.acme.cloud.ui.demo.client.api.IMessagesService_Generated_RestServiceProxy_
[INFO]       [WARN] com.acme.cloud.event.Timestamp_Generated_JsonEncoderDecoder_
...

David Nouls

unread,
Mar 25, 2016, 4:49:06 AM3/25/16
to RestyGWT
Since nobody seems to be listening, I did some more investigation.

RestyGWT should really be more resilient and verbose when generating the json serialisation classes, I need to reverse engineer resty to know when there is something it does not like when creating the serializers.
In this case I think the root cause seems to be that Resty does not support something like this:

  @JsonCreator

  public Id(String pId) {

    Preconditions.checkNotNull(pId);

    mId = pId;

  }

 

  @JsonValue

  public String getId() {

    return pId;

  }


We often do this in our java classes to enforce typesafety, but in the Json output we only see the string.

However RestyGWT seems to assume that a JsonCreator is supposed to have a JsonProperty on all the creator parameters.

Jackson does not require this.


christian

unread,
Mar 25, 2016, 8:45:11 AM3/25/16
to rest...@googlegroups.com
sorry, I was listening :) but did not speak out.

yes, resty does not implement the complete jackson annotations. implementation happens more or less on demand.

just looked at the previous messages of yours, looks like it is not a complete example. if you can provide a complete example of your POJOs which fails, I could look into implementing it. OR you are most welcome to see if you can implement your use-case and submit a pull request :)

there are still some quirks around @JsonCreator in conjuction with @JsonProperties

-christian

christian

unread,
Mar 25, 2016, 8:46:09 AM3/25/16
to christian, rest...@googlegroups.com
I saw your issue on github - will look into this

David

unread,
Mar 25, 2016, 12:27:43 PM3/25/16
to rest...@googlegroups.com, christian
I switched to GWTP + GWT-Jackson, this combination seems to have no issues with my REST API and POJOS.


On Fri, Mar 25, 2016 at 1:46 PM christian <m.kri...@web.de> wrote:
I saw your issue on github - will look into this

--
You received this message because you are subscribed to the Google Groups "RestyGWT" group.
To unsubscribe from this group and stop receiving emails from it, send an email to restygwt+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Arash Kamangir

unread,
Oct 26, 2016, 8:25:42 PM10/26/16
to RestyGWT, m.kri...@web.de
Hi guys,
I also was facing the same Problem with ArrayIndexOutOfBoundsException, as David mentioned before.
After comparing Ronan Quilleveres older, working RestyGWT example settings I found out
that he has used an older version of RestiGWT: 1.4.
After some configuration I found out, that the ArrayIndexOutOfBoundsException appears from version 2.X.
However, I'm fine with 1.5 for now :)

Arash Kamangir

unread,
Oct 26, 2016, 8:41:42 PM10/26/16
to RestyGWT, m.kri...@web.de
I'm wondering whether there is a related issue to that exception on github.
I couldn't find any.
Reply all
Reply to author
Forward
0 new messages