1

我试图让 GWT+RESTlet 与 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 期待“application/x-java-serialized-object+gwt”而不是资源中的 set MediaType?

是否与使用 org.restlet.client.resource.ClientProxy 有关?如果是这样,还有其他方法可以使用 RESTlet 执行这些异步请求吗?

我正在使用 RESTlet 2.1.2 和 GWT 2.2.0。

提前致谢。

4

3 回答 3

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) {
    }
});
于 2013-03-31T17:11:12.600 回答
0

我在谷歌搜索你的问题时发现了这个问题,这可能是连接的。

以下内容可能没有效率,但您也可以查看restyGWT进行休息调用。

于 2013-04-03T11:56:34.130 回答
0

归根结底,这其中包含了几个问题,我想我最好分享一下我的发现;

  1. 我没有意识到我有一个“同源”问题。这是通过在我的 Rest 服务器的 GWT 服务端口上使用透明代理解决的。这似乎也将 Rest 服务器的身份验证正确地转发到浏览器中的 GWT 应用程序。

  2. Restlet 在 Editions 中的包装似乎是一个非常好的主意。但是要让 IntelliJ IDEA 能够使用这些以及共享的 DTO 模块设置 GWT 调试环境真的很困难。我认为关于 Restlet 确定使用哪些内容类型以及不使用哪些内容类型的方式,我还有其他问题。一天结束时,我说服自己不要打扰共享的 DTO 库,而是;

    • 服务器端使用 Restlet 的 Jackson 扩展和 pojo 类作为 DTO。
    • 在 GWT 方面,我要求 Restlet 只处理 Representation 类型,并使用 GWT 中的 AutoBean 特性进行序列化。(见下文)

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();
于 2013-04-18T14:27:02.873 回答