Как настроить клиент Джерси с провайдером Jackson (2.x) для обработки POST-запроса

Я пытаюсь настроить клиент Джерси для тестирования запроса POST к ресурсу.

Мои зависимости Джерси и Джексона выглядят так:

<dependencies>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-grizzly2-http</artifactId>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.jaxrs</groupId>
        <artifactId>jackson-jaxrs-json-provider</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-client</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey</groupId>
            <artifactId>jersey-bom</artifactId>
            <version>${jersey.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Я использую Джерси 2.4 и Джексон 2.2.3.

Я настраиваю Client и WebTarget следующим образом:

client = JerseyClientBuilder.newBuilder().build();

target = client.target(Main.BASE_URI);

Я настраиваю сервер следующим образом:

ResourceConfig rc = new ResourceConfig().packages("com.my.package.is.here");
HttpServer httpServer = GrizzlyHttpServerFactory
                           .createHttpServer(URI.create(BASE_URI), rc);

Я пытаюсь проверить POST-запрос на ресурсе:

ClientResponse response = target.path(resourceIdentifier)
                             .request(MediaType.APPLICATION_JSON_TYPE)
                             .post(Entity.json(testObjectJSON.toString()), 
                                       ClientResponse.class);

В настоящее время я получаю следующую ошибку:

javax.ws.rs.ProcessingException: Error reading entity from input stream.
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:849)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:768)
at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:96)
at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:761)
at org.glassfish.jersey.client.JerseyInvocation.access$500(JerseyInvocation.java:90)
at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:671)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:422)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:667)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:423)
at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:326)
at com.my.package.is.here.test.MyResourceTest.testPOSTJSON(MyResourceTest.java:117)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not find a deserializer for non-concrete Map type [map type; class javax.ws.rs.core.MultivaluedMap, [simple type, class java.lang.String] -> [collection type; class java.util.List, contains [simple type, class java.lang.String]]]
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:272)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:247)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:146)
at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:305)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.findDeserializer(StdDeserializer.java:634)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:438)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:298)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:247)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:146)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:322)
at com.fasterxml.jackson.databind.ObjectReader._findRootDeserializer(ObjectReader.java:1326)
at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1174)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:635)
at com.fasterxml.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:660)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:188)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:134)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:988)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:833)
... 38 more
Caused by: java.lang.IllegalArgumentException: Can not find a deserializer for non-concrete Map type [map type; class javax.ws.rs.core.MultivaluedMap, [simple type, class java.lang.String] -> [collection type; class java.util.List, contains [simple type, class java.lang.String]]]
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.createMapDeserializer(BasicDeserializerFactory.java:945)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:382)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:354)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:267)
... 55 more

Однако, когда я тестирую POST-запрос на ресурсе с помощью curl, все работает нормально. Поэтому я думаю, что это может иметь какое-то отношение к настройке клиента Джерси.


person zazi    schedule 30.08.2013    source источник
comment
Похоже, это как-то связано с реализацией класса ClientResponse, т. е. прямой возврат результата не вызывал исключения. Итак, для успешного выполнения теста работают следующие строки кода: String responseString = target.path(resourceIdentifier + ).request(MediaType.APPLICATION_JSON_TYPE).post(Entity.json(testObjectJSON.toString()), String.class);   -  person zazi    schedule 30.08.2013


Ответы (2)


Похоже, это как-то связано с реализацией класса ClientResponse, т. е. прямой возврат результата не вызывал исключения. Таким образом, следующие строки кода работают, чтобы сделать тест успешным:

String responseString = target.path(resourceIdentifier).request(MediaType.APPLICATION_JSON_TYPE).post(Entity.json(testObjectJSON.toStr‌​ing()), String.class);
person zazi    schedule 02.01.2014
comment
Действие post не может напрямую возвращать ClientResponse.class? - person macemers; 30.06.2015

Попробуй это:

package myco.mypkg;

import static org.junit.Assert.assertEquals;

import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.glassfish.jersey.test.TestProperties;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.Test;
import org.springframework.http.MediaType;

/**
 *   Simple tests, with a simple endpoint/resource, no injections, to debug and document how JerseyTest works.
 *
 */
public class SimpleTest extends JerseyTest {

    public SimpleTest() {

        // Enable logging. This is really critical!
        enable(TestProperties.LOG_TRAFFIC);
        enable(TestProperties.DUMP_ENTITY);     
    }

    /** Start a Grizzly server */
    @Override
    protected TestContainerFactory getTestContainerFactory() {
        return new GrizzlyWebTestContainerFactory();
    }

    /** Tell the server to deploy the TestResource endpoint class */
    @Override
    protected DeploymentContext configureDeployment() {
        return ServletDeploymentContext.forServlet(new ServletContainer(new ResourceConfig(TestResource.class))).build();
    }

    /**
     * Make a test call.
     */
    @Test
    public void testGet() {
        WebTarget target = target("root");

        String s = target.request().get(String.class);
        assertEquals("GET", s);
    }

    @Test
    public void testGetSub() {
        WebTarget target = target("root/sub");

        String s = target.request().get(String.class);
        assertEquals("sub", s);
    }

    @Test
    public void testPost() {
        WebTarget target = target("root/mypost");

        Form form = new Form();
        form.param("id", "1234");
        form.param("description", "test"); 
        String s = target.request(MediaType.APPLICATION_FORM_URLENCODED_VALUE).post(Entity.form(form), String.class);
        assertEquals("posted", s);
    }

    @Test
    public void testPostWithParam() {
        WebTarget target = target("root/postparams");

        Form form = new Form();
        form.param("id", "1234");
        String s = target.request(MediaType.APPLICATION_FORM_URLENCODED_VALUE).post(Entity.form(form), String.class);
        assertEquals("posted1234", s);
    }
}

Эти вызовы следующие:

package myco.mypkg;

import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;

/**
 *      A test endpoint, for use with SimpleTest 
 */
@Path("root")
public class TestResource {

    @GET
    public String get() {
        return "GET";
    }

    @Path("sub")
    @GET
    public String getSub() {
        return "sub";
    }

    @Path("mypost")
    @POST
    public String post() {
        return "posted";
    }

    /** If you omit the @FormParam, id contains "id=1234" */
    @Path("postparams")
    @POST
    public String post(@FormParam("id") String id) {
        return "posted" + id;
    }
}

Я получил материал POST, набрав Entity. и ожидание всплывающей подсказки, чтобы показать мне, какие методы были.

Я использую Джерси 2.13.

person Community    schedule 21.11.2014