Domanda

Sto cercando di installare un'applicazione giocattolo (che può trasformare in una vera e propria applicazione un giorno). Io corro in un problema con Wink e Jackson. Ho due applicazioni: si corre Wink-server sul pontile e sembra essere fornendo alcuni dati JSON bene; si corre Wink-client sul pontile e riceve i dati JSON bene. Le bugie problematici in automagically deserializzazione parte posteriore dei dati JSON nel mio bean Java.

Ecco il codice che uso nel mio occhiolino un'azione client:

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

Ecco l'errore che ricevo quando provo a fare funzionare i Struts azione:

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)
...

Se sostituisco l'ultima riga del primo frammento di codice con la seguente riga, tutto funziona bene e dandy.

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

E 'chiaro che i dati sta diventando in tutto bene, ma il problema sembra risiedere con il fatto che la classe JacksonJsonProvider non è registrato con il cliente Wink. Ho visto un sacco di modi per registrare il provider con il server Wink, ma non il client Wink.

E 'possibile fare fare il primo frammento di codice funziona correttamente? Se sì, come?

(Per inciso, l'altro problema può essere che mi manca annotazioni sulla mia classe di utente. In questo momento non ce ne sono. Forse ho bisogno di un po '...)

È stato utile?

Soluzione

Passaggio 1:. Creare una classe che estende javax.ws.rs.core.Application che permette di single set

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;
    }
}

Passo 2: Nella vostra azione, creare un org.apache.wink.client.ClientConfig per il vostro org.apache.wink.client.RestClient. In questo modo si aggiunge il org.codehaus.jackson.jaxrs.JacksonJsonProvider alla tua lista provider.

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);

Passaggio 3: Creare il org.apache.wink.client.Resource, utilizzare il metodo get(Class<T> responseEntity) e tutto ora funziona come previsto.

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

Se si vuole essere davvero chiazza di petrolio su di esso, è possibile utilizzare Spring per impostare un fagiolo ClientConfig e iniettare in alle vostre azioni. Quindi, si può chiamare new RestClient(clientConfig) ogni volta e non preoccuparsi di replicare l'intero setup.

Altri suggerimenti

Mi sono imbattuto in questo problema quando si cerca di scrivere alcuni test di integrazione che il POST un oggetto per il mio plugin di riposo.

Invece di girare una nuova classe è possibile fornire il fornitore di Jackson con una classe in linea.

  @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);

}

Quindi è possibile inviare e consumare gli oggetti annotati.

@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());

}

Se stai usando Maven è possibile assicurarsi che Jackson è nel classpath di test (controllo per le versioni compatibili):

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

Vorrei poter aiutare con la registrazione; ma per quanto riguarda le annotazioni, non credo che si dovrebbe bisogno di alcuna per Jackson tenta di deserializzare il valore. Se vi manca qualcosa che è necessario che si ottiene diversi tipi di eccezione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top