2010-12-01 84 views
3

我正在嘗試設置一個玩具應用程序(可能有一天會轉向一個真實的應用程序)。我遇到了眨眼和傑克遜的問題。我有兩個應用程序:一個在碼頭上運行wink-server,似乎正在提供一些JSON數據;一個在jetty上運行wink-client並且收到JSON數據就好了。問題在於自動將JSON數據反序列化回Java bean。如何使用Wink客戶端註冊Jackson提供商?

下面是我在眨眼客戶機操作使用的代碼:

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客戶端。

是否有可能使第一個代碼片段正常運行?如果是這樣,怎麼樣?

(順便說一句,另一個問題可能是我失蹤在我的User類的註釋。現在根本就沒有什麼。也許我需要一些......)

回答

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.RestClientorg.apache.wink.client.ClientConfig。這使您可以將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建立一個ClientConfig豆和對你的行動注入它。然後,您可以每次撥打new RestClient(clientConfig),而不用擔心複製整個設置。

+0

這並沒有爲我工作。我的類有jaxb註釋,系統應用程序提供者似乎干擾傑克遜json提供程序。解決方案是在設置應用程序之前在ClientConfig上調用setLoadWinkApplications(false)。 – kldavis4 2013-03-16 03:17:37

0

我希望我能幫助與註冊;但就註釋而言,我認爲你不應該需要任何傑克遜試圖對價值進行反序列化。如果你缺少你需要的東西,你會得到不同的例外。

2

當我試圖編寫一些集成測試來爲我的rest插件發佈一個對象時,我遇到了這個問題。

而不是旋轉一個新的類,你可以提供一個內聯類的傑克遜提供商。

@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可以確保傑克遜是在測試類路徑(檢查是否有兼容版本):

<!-- 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>