4

我正在尝试设置一个玩具应用程序(有一天它可能会变成一个真正的应用程序)。我遇到了 Wink 和 Jackson 的问题。我有两个应用程序:一个在码头上运行 wink-server,似乎可以提供一些 JSON 数据;一个在码头上运行 wink-client 并接收 JSON 数据就好了。问题在于将 JSON 数据自动反序列化回我的 Java bean。

这是我在 wink 客户端操作中使用的代码:

RestClient client = new RestClient();
Resource resource = client.resource("http://localhost:8081/helloworld");
User user = resource.accept(MediaType.APPLICATION_JSON).get(User.class);

这是我尝试运行 Struts 操作时收到的错误:

java.lang.RuntimeException: No javax.ws.rs.ext.MessageBodyReader found for type class my.package.structure.User and media type application/json. Verify that all entity providers are correctly registered.
org.apache.wink.client.internal.handlers.ClientResponseImpl.readEntity(ClientResponseImpl.java:123)
org.apache.wink.client.internal.handlers.ClientResponseImpl.getEntity(ClientResponseImpl.java:65)
org.apache.wink.client.internal.handlers.ClientResponseImpl.getEntity(ClientResponseImpl.java:52)
org.apache.wink.client.internal.ResourceImpl.invoke(ResourceImpl.java:186)
org.apache.wink.client.internal.ResourceImpl.get(ResourceImpl.java:294)
my.package.structure.action.HelloWorldAction.execute(HelloWorldAction.java:29)
...

如果我用以下行替换第一个代码片段中的最后一行,一切正常且花花公子。

String message = resource.accept(MediaType.APPLICATION_JSON).get(String.class);
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(message, User.class);

很明显,数据传输得很好,但问题似乎在于 JacksonJsonProvider 类未向 Wink 客户端注册这一事实。我已经看到了很多向 Wink 服务器注册提供程序的方法,但不是 Wink 客户端。

是否可以使第一个代码段正常运行?如果是这样,怎么做?

(顺便说一句,另一个问题可能是我的用户类缺少注释。现在没有。也许我需要一些......)

4

3 回答 3

7

第 1 步:创建一个可扩展的类javax.ws.rs.core.Application,允许您设置单例。

import java.util.Collections;
import java.util.Set;
import javax.ws.rs.core.Application;

public class ClientApplication extends Application {

    private Set<Object> singletons = Collections.emptySet();

    @Override
    public Set<Object> getSingletons() {
        return singletons;
    }

    public void setSingletons(final Set<Object> singletons) {
        this.singletons = singletons;
    }
}

第 2 步:在您的操作中,org.apache.wink.client.ClientConfig为您的org.apache.wink.client.RestClient. 这允许您将其添加org.codehaus.jackson.jaxrs.JacksonJsonProvider到您的提供商列表中。

ClientApplication clientApplication = new ClientApplication();
Set<Object> s = new HashSet<Object>();
s.add(new JacksonJsonProvider());
clientApplication.setSingletons(s);
ClientConfig clientConfig = new ClientConfig().applications(clientApplication);
RestClient restClient = new RestClient(clientConfig);

第 3 步:创建org.apache.wink.client.Resource,使用该get(Class<T> responseEntity)方法,现在一切都将按预期工作。

Resource resource = client.resource("http://localhost:8081/helloworld");
User user = resource.accept(MediaType.APPLICATION_JSON).get(User.class);

如果您想真正了解它,可以使用 Spring 设置一个ClientConfigbean 并将其注入到您的操作中。然后,您可以new RestClient(clientConfig)每次都调用,而不必担心复制整个设置。

于 2010-12-07T17:02:22.320 回答
3

我在尝试编写一些为我的休息插件发布对象的集成测试时遇到了这个问题。

您可以为 Jackson 提供程序提供一个内联类,而不是创建一个新类。

  @Before
public void setup(){

    javax.ws.rs.core.Application app = new javax.ws.rs.core.Application() {
        public Set<Class<?>> getClasses() {
            Set<Class<?>> classes = new HashSet<Class<?>>();
            classes.add(JacksonJaxbJsonProvider.class);
            return classes;
        }

    };
    //create auth handler
    clientConfig = new ClientConfig();
    clientConfig.applications(app);
    BasicAuthSecurityHandler basicAuthSecurityHandler = new BasicAuthSecurityHandler();
    basicAuthSecurityHandler.setUserName(USERNAME);
    basicAuthSecurityHandler.setPassword(PASSWORD); 
    clientConfig.handlers(basicAuthSecurityHandler);
    //create client usin auth and provider
    client = new RestClient(clientConfig);

}

然后您可以发布和使用您的注释对象。

@Test
public void aReadWriteTokenCanBeCreatedAsRequested(){ 
    ClientResponse response = client.resource(resourceUrlToken).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).post(readAndWriteToken);
    assertEquals("Could not create token needed for test",200,response.getStatusCode());
    readAndWriteToken = response.getEntity(TokenResource.class);
    assertNotNull("Returned token does not have UUID",readAndWriteToken.getUuid());

}

如果您使用的是 maven,您可以确保 Jackson 在测试类路径中(检查兼容版本):

<!-- TEST DEPENDENCIES -->
  <dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.1</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-jaxrs</artifactId>
    <version>1.9.1</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.1</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-xc</artifactId>
    <version>1.9.1</version>
    <scope>test</scope>
  </dependency>
于 2014-08-01T15:16:34.680 回答
0

我希望我能帮助注册;但是关于注释,我认为杰克逊不需要任何注释来尝试反序列化价值。如果你遗漏了一些你需要的东西,你会得到不同类型的异常。

于 2010-12-03T17:15:58.990 回答