Tôi mới ở các dịch vụ an toàn và có khởi đầu khá tốt, cho đến khi tôi quyết định chơi với một số đối tượng phức tạp. Vấn đề tôi đang nhấn là về việc unmarshalling một đối tượng đến máy chủ (tạo đối tượng từ XML ở phía máy chủ).CXF Đối tượng phức tạp dịch vụ không ổn định không hoạt động
Dưới đây là mẫu (đại diện) triển khai dịch vụ của tôi.
Đây là loại dữ liệu "đối tượng phức tạp" của tôi.
package data;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class ComplexType {
private long id;
private String name;
private Boolean isRegistered;
public ComplexType() {
super();
}
public ComplexType(long id, String name, Boolean isRegistered) {
super();
this.id = id;
this.name = name;
this.isRegistered = isRegistered;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean getIsRegistered() {
return isRegistered;
}
public void setIsRegistered(Boolean isRegistered) {
this.isRegistered = isRegistered;
}
}
Đây là dịch vụ của tôi API
package api;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import data.ComplexType;
public interface Service {
@GET
@Path("/nummembers")
int getNumElements();
@GET
@Path("/member/{id}")
ComplexType getMember(@PathParam("id") long id);
@POST
@Path("/member")
boolean addMember(@FormParam("member") ComplexType member);
}
Và đây là việc thực hiện các dịch vụ:
package impl;
import java.util.HashMap;
import java.util.Map;
import data.ComplexType;
import api.Service;
public class ServiceImpl implements Service {
Map<Long, ComplexType> data;
public ServiceImpl() {
System.out.println("TestApp Starting");
data = new HashMap<Long, ComplexType>();
}
@Override
public int getNumElements() {
return data.size();
}
@Override
public ComplexType getMember(long id) {
if (data.containsKey(id)) {
return data.get(id);
}
ComplexType ct =
new ComplexType(id, "NAME" + new Long(id).toString(), (id % 2 == 1));
data.put(id, ct);
return ct;
}
@Override
public boolean addMember(ComplexType member) {
int preSize = data.size();
data.put(member.getId(), member);
return preSize < data.size(); // True if added
}
}
Vì vậy, khi tôi gọi getNumElements()
không có vấn đề. Khi tôi gọi số getMember(long id)
, tôi nhận được một "Kiểu chữ" được sắp xếp theo hàng loạt. Khi tôi serialize một loại phức tạp và vượt qua nó như FormParam để addMember(ComplexType member)
, tôi luôn luôn có được Parameter Class data.ComplexType has no constructor with single String parameter, static valueOf(String) or fromString(String) methods
tôi đã cố gắng để cung cấp cung cấp tùy chỉnh của tôi, bằng cách viết các lớp sau đây:
package impl;
import javax.ws.rs.ext.ContextResolver;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import data.ComplexType;
public class JaxbXmlContextResolver implements ContextResolver<Object> {
private static final Class<?>[] classes = new Class[] {ComplexType.class};
private static final JAXBContext context = initContext();
public static JAXBContext initContext() {
JAXBContext context = null;
try {
context = JAXBContext.newInstance(classes);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
return context;
}
@Override
public Object getContext(Class<?> arg0) {
return context;
}
}
Và đối với phần còn lại của cấu hình , đây là web.xml của tôi:
<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>TestApp</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:cxf.xml</param-value>
</context-param>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
Và cxf.xml nó đề cập đến:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.0.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<bean id="myservice" class="impl.ServiceImpl" />
<bean id="jaxbXmlProvider" class="impl.JaxbXmlContextResolver" />
<jaxrs:server id="connectionService" address="/" >
<jaxrs:serviceBeans>
<ref bean="myservice" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="xml" value="application/xml" />
</jaxrs:extensionMappings>
<jaxrs:providers>
<ref bean="jaxbXmlProvider" />
</jaxrs:providers>
</jaxrs:server>
</beans>
Và để có đầy đủ, đây là tệp pom.xml tôi đang sử dụng để tạo ứng dụng.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<modelVersion>4.0.0</modelVersion>
<groupId>TESTAPP</groupId>
<artifactId>testApp</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>Test Application</name>
<url>http://www.mycompany.com</url>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>2.4.1</version>
<exclusions>
<exclusion>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>net.sf.kxml</groupId>
<artifactId>kxml2</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Bất kỳ trợ giúp (giải pháp, con trỏ hoặc bất kỳ hướng nào) sẽ được đánh giá cao.
Ồ, tôi đang sử dụng cxf 2.4.1 và Spring 3.0.5.RELEASE. Đây là bản sao chính xác của ứng dụng được triển khai của tôi.
Cảm ơn.
Theo: http://cxf.547215.n5.nabble.com/MessageBodyReader-not-picked-up-td564496.html params được đánh dấu @FormParam không được xử lý bởi người đọc tin nhắn, và yêu cầu một ParameterHandler cụ thể. Vì vậy, tôi đã viết một trình xử lý tùy chỉnh và nó hoạt động tốt. Nó làm phiền tôi rằng tôi phải viết một xử lý cho mọi obj tôi mong đợi để nhận được trong một hình thức. Nếu có một giải pháp, tôi sẽ đánh giá cao nó. Ngoài ra, một trong những lo ngại của tôi là, tôi muốn hỗ trợ cả xml và json trong dịch vụ của tôi. Tôi không chắc làm thế nào tôi có thể viết hai xử lý cho cùng một obj, hoặc cho dù tôi nên viết xử lý của tôi để xử lý cả hai định dạng. –