Question

Je suis en train de mettre en place une application de jouet (qui peut se transformer pour une application réelle un jour). Je suis en cours d'exécution dans un problème avec Clin d'oeil et Jackson. J'ai deux applications: un clin d'oeil court-serveur sur la jetée et semble fournir des données JSON très bien; un clin d'oeil court-client sur la jetée et reçoit les données JSON très bien. Les mensonges de problème dans désérialisation automagiquement le dos de données JSON dans mon bean Java.

Voici le code que j'utilise dans mon action client wink:

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

Voici l'erreur que je reçois lorsque je tente d'exécuter l'action 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)
...

Si je remplace la dernière ligne dans le premier extrait de code avec la ligne suivante, tout fonctionne très bien et dandy.

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

Il est clair que les données devient à travers bien, mais le problème semble être le fait que la classe JacksonJsonProvider est pas enregistré avec le client Wink. Je l'ai vu beaucoup de façons d'enregistrer le fournisseur avec le serveur Wink, mais pas le client Wink.

Est-il possible de faire faire le premier extrait de code fonctionne correctement? Si oui, comment?

(En aparté, l'autre problème peut être que je me manque des annotations sur ma classe utilisateur. En ce moment, il n'y en a pas. Peut-être que j'ai besoin ...)

Était-ce utile?

La solution

Étape 1:. Créer une classe qui étend javax.ws.rs.core.Application qui vous permet de définir singletons

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

Étape 2: Dans votre action, créez un org.apache.wink.client.ClientConfig pour votre org.apache.wink.client.RestClient. Cela vous permet d'ajouter le org.codehaus.jackson.jaxrs.JacksonJsonProvider à votre liste de fournisseurs.

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

Étape 3: Créez le org.apache.wink.client.Resource, utilisez la méthode de get(Class<T> responseEntity) et tout va maintenant fonctionner comme prévu.

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

Si vous voulez être vraiment habile à ce sujet, vous pouvez utiliser Spring pour mettre en place un grain de ClientConfig et l'injecter dans vos actions. Ensuite, vous pouvez simplement appeler new RestClient(clientConfig) chaque fois et ne pas se reproduire toute l'installation.

Autres conseils

Je suis tombé sur ce problème en essayant d'écrire des tests d'intégration que le POST un objet pour mon plugin repos.

Plutôt que de tourner une nouvelle classe, vous pouvez fournir le fournisseur Jackson avec une classe en ligne.

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

}

Ensuite, vous pouvez poster et consommer vos objets annotés.

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

}

Si vous utilisez Maven, vous pouvez vous assurer que Jackson est sur le chemin de classe de test (vérification des versions compatibles):

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

Je voudrais pouvoir aider à l'enregistrement; mais en ce qui concerne les annotations, je ne pense pas que vous avez besoin pour une Jackson pour essayer de deserialize valeur. Si vous manque quelque chose dont vous avez besoin, vous obtiendrez différents types d'exception.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top