quarks
quarks

Reputation: 35346

Errai-jaxrs - Bad Request

I'm having quite an issue for running Errai-jaxrs with my app I'm getting this error from the GWT Dev Mode:

org.jboss.errai.enterprise.client.jaxrs.api.ResponseException: Bad Request    
at org.jboss.errai.enterprise.client.jaxrs.AbstractJaxrsProxy$1.onResponseReceived(AbstractJaxrsProxy.java:132)    
at com.google.gwt.http.client.Request.fireOnResponseReceived(Request.java:287)    
at com.google.gwt.http.client.RequestBuilder$1.onReadyStateChange(RequestBuilder.java:395)    
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)    
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)    
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)    
at java.lang.reflect.Method.invoke(Method.java:474)    
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)    
at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)    
at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)    
at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:337)    
at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:218)    
at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)    
at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)    
at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)    
at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)    
at com.google.gwt.core.client.impl.Impl.apply(Impl.java)    
at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:213)    
at sun.reflect.GeneratedMethodAccessor56.invoke(Unknown Source)    
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)    
at java.lang.reflect.Method.invoke(Method.java:474)    
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)    
at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)    
at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)    
at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:292)    
at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:546)    
at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:363)    
at java.lang.Thread.run(Thread.java:722)

On the server side:

[INFO] Caused by: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "^EncodedType" (Class com.mycompany.client.shared.Customer), not marked as ignorable
[INFO]  at [Source: org.mortbay.jetty.HttpParser$Input@115194d; line: 1, column: 18] (through reference chain: com.mycompany.client.shared.Customer["^EncodedType"])
[INFO]  at org.codehaus.jackson.map.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:53)
[INFO]  at org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException(StdDeserializationContext.java:267)
[INFO]  at org.codehaus.jackson.map.deser.std.StdDeserializer.reportUnknownProperty(StdDeserializer.java:673)
[INFO]  at org.codehaus.jackson.map.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:659)
[INFO]  at org.codehaus.jackson.map.deser.BeanDeserializer.handleUnknownProperty(BeanDeserializer.java:1365)
[INFO]  at org.codehaus.jackson.map.deser.BeanDeserializer._handleUnknown(BeanDeserializer.java:725)
[INFO]  at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:703)
[INFO]  at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:580)
[INFO]  at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2704)

From the stacktrace it looks like a Bad Request. The backend for this one is RestEasy + Guice which pretty much configured properly, since before I tried using errai-jaxrs I am just using plain GWT RequestBuilder which works fine. I'm not sure where the problem is but here is my code:

CustomerService.java

@Path("/customerservice")
public interface CustomerService {
    @GET
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)     
    public Customer getCustomer(String id);

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.TEXT_PLAIN)
    public String createCustomer(Customer Customer);
}

CustomerServiceImpl.java

@Singleton
public class CustomerServiceImpl implements CustomerService {
    @Override
    public Customer getCustomer(String id) {
        return new Customer();
    }

    @Override
    public String createCustomer(Customer Customer) {
        return "1";
    }
}

On the client side:

@Inject
private Caller<CustomerService> customerService;

@EventHandler("submit")
public void createCustomer(ClickEvent event) {   
    event.preventDefault();
    Customer customer = new Customer();
    customerService.call(new RemoteCallback<String>() {
        @Override
        public void callback(String response) {
            Window.alert("Customer created: " + response);
        }
    }).createCustomer(customer);
}

What could be the problem?

Upvotes: 0

Views: 542

Answers (1)

Jonathan Fuerth
Jonathan Fuerth

Reputation: 2190

I can see from the stack trace that you're using Jackson for marshalling request and response data on the server side, but the client is using Errai's default marshalling format.

You will have to decide whether you want to use Errai's marshalling format or Jackson.

Errai Marshalling

The advantage of Errai's marshalling format is that it includes more type information on the wire (like the "^EncodedType" property you see the Jackson parser complaining about). This is the best choice when your JAX-RS API will primarily be used be Errai clients. It's also the only way you will be able to send an object like this over the wire:

@Portable class TypeWithPolymorphicField {
  private Object foo = new Foo();
}

To enable Errai marshalling (rather than Jackson) on the server-side, you need to deploy errai-jaxrs-provider-[version].jar with your app. From the Errai Reference Guide:

<dependency>
  <groupId>org.jboss.errai</groupId>
  <artifactId>errai-jaxrs-provider</artifactId>
  <version>${errai.version}</version>
</dependency>

Jackson Marshalling

On the other hand, if your JAX-RS API is meant to be used by non-Errai clients, they might find the Jackson marshalling more pleasant and familiar. If you choose that, you need to tell the client to use Jackson marshalling instead of the default. From the Errai Reference guide:

The following options are available for activating Jackson marshalling on the client. Note that this is a client-side configuration, the JAX-RS endpoint is assumed to already return a Jackson representation (Jackson is supported by all JAX-RS implementations). The errai-jaxrs-provider.jar does not have to be deployed on the server in this case!

<script type="text/javascript">
  erraiJaxRsJacksonMarshallingActive = true;
</script>

or by using a JSNI method:

private native void setJacksonMarshallingActive(boolean active) /*-{  
  $wnd.erraiJaxRsJacksonMarshallingActive = active;
}-*/;

or by simply invoking:

RestClient.setJacksonMarshallingActive(true);

Final note: don't do both of the above, or you will be stuck with the opposite problem! You have to configure either the client or the server away from its natural default.

Upvotes: 4

Related Questions