RestyGWT with remote RESTful API

Introduction

I quite like the concept of GWT to convert Java code into optimised Javascript that runs on major browsers out of the box.

Last weekend I read the RestyGWT documentation and tried to fulfil my goals using it.

My goal

Invoking a web service directly from the Javascript-GWT-compiled on the client side.

Invoking the API directly from the compiled Javascript

In order to fulfil my requirement, I imported RestyGWT into my 'RestExternalApi.gwt.xml' module config:

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

created an interface extending 'RestService' as suggested by the documentation in the 'client' module of GWT:

@Path("/api/hellos")
public interface HelloClient extends RestService {   
   @GET   public void getHellos(MethodCallback<List<Hello>> callback);   
}

and added the lines invoking the remote* API directly from the EntryPoint:

public class RestExternalApi implements EntryPoint {
 
  public void onModuleLoad() {
    
   Defaults.setServiceRoot("http://localhost:8070");
     
   HelloClient client = GWT.create(HelloClient.class);
   
   client.getHellos(new MethodCallback<List<Hello>>() {
      
      public void onSuccess(Method method, List<Hello> response) {
         for (Hello hello : response) {
            Label label = new Label(hello.getName());
            RootLayoutPanel.get().add(label);
} } public void onFailure(Method method, Throwable exception) { Label label = new Label("Error"); RootLayoutPanel.get().add(label); } }); }

Trying to invoke the API as above would always invoke the callback 'onFailure(...)' with response status code '0'.

The solution that works for me

In the end this is what worked for me:

On the 'client' module:

Again, the interface extending 'RestService':

package org.usesoft.gwtrestapp.client.api.client;

import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

import org.fusesource.restygwt.client.MethodCallback;
import org.fusesource.restygwt.client.RestService;
import org.usesoft.gwtrestapp.shared.domain.Hello;

@Path("/api/hellos")
public interface HelloClient extends RestService {   
   @GET   public void getHellos( MethodCallback<List<Hello>> callback);   
}

the EntryPoint, as it was before:

package org.usesoft.gwtrestapp.client;

import java.util.List;

import org.fusesource.restygwt.client.Defaults;
import org.fusesource.restygwt.client.Method;
import org.fusesource.restygwt.client.MethodCallback;
import org.usesoft.gwtrestapp.client.api.client.HelloClient;
import org.usesoft.gwtrestapp.shared.domain.Hello;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

public class RestExternalApi implements EntryPoint {
 
  public void onModuleLoad() {
    
   Defaults.setServiceRoot(GWT.getHostPageBaseURL());
     
   HelloClient client = GWT.create(HelloClient.class);
   
   client.getHellos(new MethodCallback<List<Hello>>() {
      
      public void onSuccess(Method method, List<Hello> response) {
         VerticalPanel panel = new VerticalPanel();
         for (Hello hello : response) {
            Label label = new Label(hello.getName());
            panel.add(label);
         }
         RootLayoutPanel.get().add(panel);
      }
      
      public void onFailure(Method method, Throwable exception) {
         Label label = new Label("Error");
         RootLayoutPanel.get().add(label);
      }
   });
     }
}

with the difference that, this time, I actually have an end point in the 'server' module of GWT. From this end point, I invoke my remote* API

@Path("hellos")
public class HelloResource {
   
   Map<String, Hello> database;
   public HelloResource() {
      database = new HashMap<String, Hello>();
      Hello hello1 = new Hello("1", "Ronan");
      Hello hello2 = new Hello("2", "John");
      
      database.put(hello1.getId(), hello1);
      database.put(hello2.getId(), hello2);
   }
   
   @GET   @Produces("application/json")
   public Collection<Hello> get() {
      final Client client = ClientBuilder.newClient().register(JacksonJsonProvider.class);
      final WebTarget target = client.target("http://localhost:8070").path("/promotions/test");

      final Response response = target.request(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).get();
      final String otherName = response.readEntity(String.class);

      database.put("3", new Hello("3", otherName));
      final Collection<Hello> values = database.values();

      return values;
   }
}

Conclusion

It is possible to easily invoke a remote* RESTful API from GWT, but not so easy/clean without first going through its own 'server' side code.

* meaning a project completely independent from the module containing GWT

Comments