【问题标题】:Jersey client unable to convert ArrayList to xmlJersey 客户端无法将 ArrayList 转换为 xml
【发布时间】:2015-07-04 12:46:17
【问题描述】:

我使用 jersey 和 spring 开发了一个宁静的 web 服务。

以下是通过接受登录对象列表来服务请求的服务方法。

服务类中的方法

@POST
@Path(value = "/login")
@Produces(MediaType.APPLICATION_XML)
public String getLogin(Login login);    

@POST
@Path(value = "/update")
@Consumes(MediaType.APPLICATION_XML)
public void updatePassword(List<Login> userList)

登录

@XmlRootElement
public class Login {
//some code
}

我正在使用 jersey 客户端来使用这个 web 服务,如下所示。

loginList = ArrayList of Login objects
Client client = Client.create();
WebResource webResource = client.resource("http://localhost:8080/user/update");
ClientResponse response = webResource.accept(MediaType.APPLICATION_XML).type(MediaType.APPLICATION_XML).post(ClientResponse.class, loginList);

但下面是我得到的例外。

原因:com.sun.jersey.api.client.ClientHandlerException:找不到 Java 类型、java.util.ArrayList 类和 MIME 媒体类型 application/xml 的消息正文编写器 在 com.sun.jersey.api.client.RequestWriter.writeRequestEntity(RequestWriter.java:288) 在 com.sun.jersey.client.urlconnection.URLConnectionClientHandler._invoke(URLConnectionClientHandler.java:204) 在 com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:147)

但我的 /login 即 getLogin 方法运行良好。

我无法弄清楚究竟是什么导致了这个问题。

谁能帮我看看这可能是什么问题。

提前致谢。

【问题讨论】:

    标签: java rest generics jersey jersey-client


    【解决方案1】:

    我猜你需要将GenericEntity 用于泛型类型,因为类型擦除。 JAXB 需要知道类型。 GenericEntity stores the type 通过它的参数。所以基本上,你只需要这样做

    .post(ClientResponse.class, new GenericEntity<List<Login>>(list){});
    

    更新

    使用 Jersey 测试框架完成测试

    <dependency>
        <groupId>com.sun.jersey.jersey-test-framework</groupId>
        <artifactId>jersey-test-framework-grizzly2</artifactId>
        <version>1.19</version>
        <scope>test</scope>
    </dependency>
    

    登录

    @XmlRootElement
    public class Login {
    
        private String name;
        private String password;
    
        public Login() {
        }
    
        public Login(String name, String password) {
            this.name = name;
            this.password = password;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        public String toString() {
            return "Login{" + "name=" + name + ", password=" + password + '}';
        }
    }
    

    测试

    import com.sun.jersey.api.client.ClientResponse;
    import com.sun.jersey.api.core.DefaultResourceConfig;
    import com.sun.jersey.spi.container.servlet.WebComponent;
    import com.sun.jersey.test.framework.JerseyTest;
    import com.sun.jersey.test.framework.WebAppDescriptor;
    import com.sun.jersey.test.framework.spi.container.TestContainerFactory;
    import com.sun.jersey.test.framework.spi.container.grizzly2.web.GrizzlyWebTestContainerFactory;
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    import javax.ws.rs.Consumes;
    import javax.ws.rs.POST;
    import javax.ws.rs.Path;
    import javax.ws.rs.core.GenericEntity;
    import javax.ws.rs.core.MediaType;
    import org.junit.Test;
    
    public class ArrayTest extends JerseyTest {
        
       
        @Path("/login")
        public static class LoginResource {
            
            @POST
            @Consumes(MediaType.APPLICATION_XML)
            public String post(List<Login> logins) {
                return new HashSet<>(logins).toString();
            }
        }
        
        public static class AppConfig extends DefaultResourceConfig {
            public AppConfig() {
                super(LoginResource.class);
            }
        }
        
        @Override
        public TestContainerFactory getTestContainerFactory() {
            return new GrizzlyWebTestContainerFactory();
        }
    
        @Override
        public WebAppDescriptor configure() {
            return new WebAppDescriptor.Builder()
                    .initParam(WebComponent.RESOURCE_CONFIG_CLASS, 
                               AppConfig.class.getName())
                    .build();
        }
        
        @Test
        public void doTest() {
            List<Login> list = new ArrayList<>();
            list.add(new Login("pee", "skillet"));
            ClientResponse response = resource().path("login")
                    .type(MediaType.APPLICATION_XML)
                    .post(ClientResponse.class, new GenericEntity<List<Login>>(list){});
            
            System.out.println("Status " +  response.getStatus());
            System.out.println(response.getEntity(String.class));
        }  
    }
    

    如果您删除GenericEntity,您将收到错误消息。

    【讨论】:

    • 在我将其更改为 GenericEntity 后,它会出现相同的异常。
    • 对我来说效果很好。在没有GenericEntity 的情况下得到了异常并且可以正常工作。我将发布我的整个测试。
    • 我有一种方法 public List getPasswords() 从 web 服务服务器返回 XML 列表。这非常有效。此列表转换在服务器端运行良好。但它不能在客户端工作。是否缺少任何依赖项或 API?
    • 应该不是依赖问题。 XML 绑定支持应该包含在核心框架中
    • 最初,在将 List 转换为 xml 以响应 getPasswords() 方法时,我在服务器端遇到了同样的错误。但是在我添加了 jersey-media-jaxb jar 之后,错误就消失了。
    猜你喜欢
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    • 2012-04-25
    相关资源
    最近更新 更多