Wie melde ich den Jackson-Anbieter mit dem Wink-Client?
-
30-09-2019 - |
Frage
Ich versuche, eine Spielzeug-Anwendung einrichten (die zu einem realen Anwendung eines Tag drehen-in). Ich laufe in ein Problem mit Wink und Jackson. Ich habe zwei Anwendungen bekommt: ein Lauf wink-Server auf Anlegestelle und scheint ganz gut einige JSON-Daten zu bieten; läuft man blinzeln-Client auf Anlegestelle und empfängt die Daten JSON just fine. Das Problem liegt in automagically die JSON-Daten zurück in meinen Java Bean Deserialisieren.
Hier ist der Code, den ich in meinem Zwinkern Client-Aktion verwenden:
RestClient client = new RestClient();
Resource resource = client.resource("http://localhost:8081/helloworld");
User user = resource.accept(MediaType.APPLICATION_JSON).get(User.class);
Hier ist der Fehler, den ich erhalte, wenn ich versuche, die Struts Aktion auszuführen:
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)
...
Wenn ich die letzte Zeile in dem ersten Codeausschnitt mit der folgenden Zeile ersetzen, funktioniert alles schön und gut.
String message = resource.accept(MediaType.APPLICATION_JSON).get(String.class);
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(message, User.class);
Es ist klar, dass die Daten über ganz gut bekommen, aber das Problem scheint darin zu liegen, dass die JacksonJsonProvider Klasse nicht mit Wink-Client registriert ist. Ich habe eine Menge von Möglichkeiten gesehen, den Anbieter mit dem Wink-Server zu registrieren, aber nicht das Wink-Client.
Ist es möglich, den ersten Code zu tun, macht Schnipsel richtig funktionieren? Wenn ja, wie?
(Nebenbei kann das andere Problem, dass ich auf meine Anmerkungen User-Klasse fehlt bin. Im Moment gibt es keine. Vielleicht brauche ich einige ...)
Lösung
Schritt 1:. Erstellen Sie eine Klasse, die javax.ws.rs.core.Application
erstreckt, die Sie Satz Singletons erlaubt
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;
}
}
Schritt 2: In Ihrer Aktion, erstellen Sie eine org.apache.wink.client.ClientConfig
für Ihre org.apache.wink.client.RestClient
. Dadurch können Sie die org.codehaus.jackson.jaxrs.JacksonJsonProvider
auf Ihren Provider-Liste hinzufügen.
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);
Schritt 3: Erstellen Sie die org.apache.wink.client.Resource
, verwenden Sie die get(Class<T> responseEntity)
Methode und alles wird jetzt wie erwartet.
Resource resource = client.resource("http://localhost:8081/helloworld");
User user = resource.accept(MediaType.APPLICATION_JSON).get(User.class);
Wenn Sie wirklich glatt über sie sein wollen, können Sie Frühling verwenden, um eine ClientConfig
Bohne einzurichten und zu injizieren sie in auf Ihre Aktionen. Dann können Sie nur new RestClient(clientConfig)
rufen jedes Mal, und nicht die Sorge um die gesamte Einrichtung zu replizieren.
Andere Tipps
Ich lief in dieses Problem bei dem Versuch, einige Integrationstests, dass POST ein Objekt für meine Ruhe Plugin zu schreiben.
Rather dann eine neue Klasse Spinnen aus Sie den Jackson-Provider mit einer Inline-Klasse zur Verfügung stellen können.
@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);
}
Dann können Sie Beiträge verfassen und verbrauchen Ihre kommentierten Objekte.
@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());
}
Wenn Sie mit maven Sie sicherstellen können, Jackson auf dem Test Classpath ist (Check für kompatible Versionen):
<!-- 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>
Ich wünschte, ich mit der Registrierung helfen könnte; aber in Bezug auf Anmerkungen, ich glaube nicht, dass Sie jede für Jackson zu deserialisieren Wert zu versuchen brauchen sollten. Wenn Sie etwas vermissen müssen Sie Sie andere Art der Ausnahme erhalten würde.