如何使用Jackson(2.x)提供程序设置Jersey客户端来处理POST请求

时间:2013-08-30 12:40:30

标签: json post jersey jackson jersey-client

我正在努力设置Jersey客户端来测试对资源的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>

我正在使用Jersey 2.4和Jackson 2.2.3。

我像这样设置了客户端和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

但是,当我用curl测试资源上的POST请求时,一切正常。所以我认为它可能与Jersey客户端设置有关。

2 个答案:

答案 0 :(得分:2)

看起来这与ClientResponse类的实现有关,即直接返回结果,不会导致异常。因此,以下代码行正在努力使测试成功:

String responseString = target.path(resourceIdentifier).request(MediaType.APPLICATION_JSON_TYPE).post(Entity.json(testObjectJSON.toStr‌​ing()), String.class);

答案 1 :(得分:0)

试试这个:

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

我通过输入Entity获得了POST的东西。并等待弹出窗口帮助向我展示方法是什么。

我正在使用Jersey 2.13。