Miniversal
Miniversal

Reputation: 129

JsonpRequestBuilder with typed response throws InCompatibleClassChangeError

I have an existing app that I'm adding a "Suggested Products" feature to and I'm having trouble with my JSONP response not being properly transformed to the typed JsArray. I'm hoping someone can give me an idea of what I'm doing wrong?

I have defined my type that will be returned from the server in its own class:

import com.google.gwt.core.client.JavaScriptObject;

public class SuggestedProduct extends JavaScriptObject {
    protected SuggestedProduct() {}
    public final native String getFormName();
    public final native String getImageURL();
}

I have a method that uses the JsonpRequestBuilder to fire off a request to get my JSON.

private void loadSuggestedProducts() {
        JsonpRequestBuilder builder = new JsonpRequestBuilder();
        builder.requestObject(buildSuggestedProductURL(), new AsyncCallback<JsArray<SuggestedProduct>>() {
            public void onFailure(Throwable caught) {
                //Handle errors
            }

            public void onSuccess(JsArray<SuggestedProduct> data) {
                if ( data == null) {
                    //Handle empty data
                    return;
                }
                SafeHtmlBuilder sb = new SafeHtmlBuilder();
                sb.appendHtmlConstant("<h4>Suggested Products:</h4>");
                for (int i=0; i < data.length(); i++) {
                    SuggestedProduct product = data.get(i); //<- This line throws the exception
                    sb.appendHtmlConstant("<div class=\"card\">");
                    sb.appendHtmlConstant("<img class=\"card-img-top\" src=\"" + product.getImageURL() + "\" alt=\"" + product.getFormName() + "\">");
                    sb.appendHtmlConstant("<div class=\"card-body\">");
                    sb.appendHtmlConstant("<h5 class=\"card-title\">" + product.getFormName() + "</h5>");
                    sb.appendHtmlConstant("<a onclick=\"javascript:addItems();\" class=\"cmd-add\">Add <i aria-hidden=\"true\" class=\"fa fa-plus-circle\"></i></a>");
                    sb.appendHtmlConstant("</div></div>");                  
                }
                view.getSuggestedProducts().setInnerSafeHtml(sb.toSafeHtml());
                }
            });
}

When I try to use a SuggestedProduct from the response, I get an error:

java.lang.IncompatibleClassChangeError: Found interface com.google.gwt.cor.client.JsArray, but class was expected

I've been following the guide in the GWT documentation. I don't see any difference between what I'm trying and what they say will work. When I debug, it looks as though the returned data is an array of SuggestedProducts, so I'm stumped as to how to proceed. Any help would be appreciated.

Upvotes: 0

Views: 36

Answers (1)

Miniversal
Miniversal

Reputation: 129

After closer inspection I realized my overlay type was missing method bodies for what fields to return from the JSON object they represented. The fix was to include the proper JSNI method definitions.

import com.google.gwt.core.client.JavaScriptObject;

public class SuggestedProduct extends JavaScriptObject {
    protected SuggestedProduct() {}
    public final native String getFormName() /*-{ return this.formname; }-*/;
    public final native String getImageURL() /*-{ return this.imageurl; }-*/;
}

Upvotes: 1

Related Questions