2013-03-30 2 views
1

Я пытаюсь получить GWT + RESTlet для связи с службой RESTful, которая не является «GWT aware».RESTlet на GWT не удалось получить ресурс RESTful, не поддерживаемый сервером с поддержкой GWT

На клиенте GWT, я что-то вроде

Reference ref = new Reference("http://localhost:8080/control/programs/"); 
ProgramListResourceProxy clientResource = GWT.create(ProgramListResourceProxy.class); 
clientResource.setReference(proxyRef); 
clientResource.setFollowingRedirects(true); 
clientResource.accept(MediaType.APPLICATION_JSON ); 
clientResource.accept(MediaType.APPLICATION_XML ); 

ProgramListResourceProxy resource = RestClient.createProgramListResource(); 
resource.retrieve(new Result<ArrayList<ProgramRef>>() 
{ 
    @Override 
    public void onFailure(Throwable caught) 
    { 
     while(caught != null) 
     { 
      Window.alert("Error retrieving programs.\n" + caught.getMessage()); 
      caught = caught.getCause(); 
     } 
    } 

    @Override 
    public void onSuccess(ArrayList<ProgramRef> result) 
    { 
     Window.alert("Programs: " + result); 
     programs = result; 
     view.setRowData(toStringList(result)); 
    } 
}); 

Если я прошу ресурс из браузера, я получаю

[{"name":"niclas","link":{"action":"GET","path":"/control/programs/niclas/"}}] 

, как и ожидалось.

Но когда вы делаете код выше в GWT, я получаю всплывающее предупреждение, сообщающее мне, что есть проблема, и во вложенном исключении;

Error retrieving programs. 
Can't parse the enclosed entity because of its media type. 
Expected <application/x-java-serialized-object+gwt> but was 
<application/json>. Make sure you have added the 
org.restlet.client.ext.gwt.jar file to your server. 

MediaTypes соответствует запросу/ответу, и трафик выглядит следующим образом.

Запрос;

GET /control/programs/ HTTP/1.1 
Host: localhost:8080 
Connection: keep-alive 
Cache-Control: max-age=0 
Accept: application/json, application/xml 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22 
Referer: http://localhost:8080/connect/Connect.html 
Accept-Encoding: gzip,deflate,sdch 
Accept-Language: en-US,en;q=0.8 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 

Реакция;

HTTP/1.1 200 OK 
Date: Sat, 30 Mar 2013 15:46:04 GMT 
Content-Type: application/json; charset=UTF-8 
Date: Sat, 30 Mar 2013 15:46:04 GMT 
Accept-Ranges: bytes 
Server: Restlet-Framework/2.1.2 
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept 
Transfer-Encoding: chunked 

4E 
[{"name":"niclas","link":{"method":"GET","path":"/control/programs/niclas/"}}] 

Может кто-нибудь объяснить, почему Restlet ожидает «применение/х-ява-сериализованная-объект + GWT», а не набор MediaType в ресурсе ??

Связано это с использованием org.restlet.client.resource.ClientProxy? Если да, есть ли другой способ выполнить эти асинхронные запросы с помощью RESTlet?

Я использую RESTlet 2.1.2 и GWT 2.2.0.

Спасибо заранее.

ответ

0

В конце дня было несколько проблем, связанных с этим, и я подумал, что лучше поделиться своими выводами;

  1. Я не понимал, что у меня возникла проблема «того же происхождения». Это было разрешено с помощью прозрачного прокси-сервера на порте обслуживания GWT на моем сервере останова. Это также, похоже, правильно перенаправляет аутентификацию сервера Rest в приложение GWT в браузере.

  2. Упаковка Restlet в изданиях кажется очень хорошей идеей. Но было очень сложно заставить IntelliJ IDEA иметь возможность настроить среду отладки GWT вместе с общим модулем DTO. Я думаю, что у меня были другие проблемы, связанные с тем, как использовать Restlet для определения того, какие типы контента используются, а что нет. В конце дня я убедил себя не беспокоиться об общей библиотеке DTO и вместо этого;

    • На стороне сервера используется расширение Джексона Restlet, а классы pojo - как DTO.
    • На стороне GWT я прошу Restlet использовать только тип представления и использовать функцию AutoBean в GWT для сериализации. (См ниже)

AutoBean велик;

public interface Program 
{ 
    String getName(); 

    void setName(String name); 

    List<Block> getBlocks(); 
    void setBlocks(List<Block> blocks); 

    List<Connection> getConnections(); 
    void setConnections(List<Connection> connections); 

    public static class Factory 
    { 
     public static Program make() { 
      AutoBean<Program> ref = ModelFactory.instance.program(); 
      return ref.as(); 
     } 

     public static String toJson(Program ref) { 
      AutoBean<Program> bean = AutoBeanUtils.getAutoBean(ref); 
      return AutoBeanCodex.encode(bean).getPayload(); 
     } 

     public static Program fromJson(String json) { 
      AutoBean<Program> bean = AutoBeanCodex.decode(ModelFactory.instance, Program.class, json); 
      return bean.as(); 
     } 
    } 
} 

Чтобы сделать выборку полной, мой ModelFactory есть методы создания для них, которые также полностью обрабатываются GWT;

public interface ModelFactory extends AutoBeanFactory 
{ 
    ModelFactory instance = GWT.create(ModelFactory.class); 
    AutoBean<Program> program(); 
    AutoBean<ProgramRefList> programRefList(); 
    : 
} 

Один вопрос, который не был очевиден в том, как обрабатывать списки JSON верхнего уровня, так как AutoBean соответствует ключи JSON с полями в интерфейсах. Но я нашел аккуратный маленький трюк, который можно увидеть в следующем фрагменте той же программы;

public interface ProgramRefList 
{ 
    List<ProgramRef> getList(); 

    public static class Factory 
    { 
     public static ProgramRefList make() 
     { 
      AutoBean<ProgramRefList> ref = ModelFactory.instance.programRefList(); 
      return ref.as(); 
     } 

     public static String toJson(ProgramRefList ref) 
     { 
      AutoBean<ProgramRefList> bean = AutoBeanUtils.getAutoBean(ref); 
      return AutoBeanCodex.encode(bean).getPayload(); 
     } 

     public static ProgramRefList fromJson(String json) 
     { 
      json = "{ \"list\": " + json + "}"; 
      AutoBean<ProgramRefList> bean = AutoBeanCodex.decode(ModelFactory.instance, ProgramRefList.class, json); 
      return bean.as(); 
     } 
    } 
} 

В списке верхнего уровня перенаправляется в другой объект с помощью одной клавиши («список» в данном случае), который затем можно добраться от метода GetList().

И это тогда очень просто используется в коде клиента Rest;

ClientResource resource = RestClient.createProgramList(new Uniform() 
    { 
     @Override 
     public void handle(Request request, Response response) 
     { 
      Logger.trace(this, "handle(" + request + "," + response + ")"); 
      try 
      { 
       if(response.isEntityAvailable()) 
       { 
        String jsonText = response.getEntity().getText(); 
        programs = ProgramRefList.Factory.fromJson(jsonText); 
        ArrayList<String> rowData = toStringList(programs); 
        view.setRowData(rowData); 
       } 
      } 
      catch(Exception e) 
      { 
       Logger.handleException(this, "loadProgramsList()", e); 
      } 
     } 
    }); 
    resource.get(); 
0

Я обычно использую JsonpRequestBuilder с типами наложения (в данном примере JsonVideoList):

JsonpRequestBuilder builder = new JsonpRequestBuilder(); 
builder.requestObject(url, new AsyncCallback<JsonVideoList>() { 
    @Override 
    public void onFailure(Throwable exception) { 
    } 

    @Override 
    public void onSuccess(JsonVideoList list) { 
    } 
}); 
+0

Благодарим за предложение. Я думаю, что нет никакого обучения лучше, чем ваша собственная борьба, и много вариантов. Я опубликовал длинный ответ на то, что я закончил, и теперь он довольно плавный. –

0

Я нашел this issue поиск вашей проблемы в гугле, это может быть связано.

Следующие могут быть неэффективными, но вы также можете взглянуть на restyGWT для совершения отдыха.

Смежные вопросы