Я новичок в отдыхающих службах, и у меня было относительно хорошее начало, пока я не решил поиграть с некоторыми сложными объектами.Проблема, с которой я сталкиваюсь, заключается в том, чтобы демонтировать объект, поступающий на сервер (создание объекта из XML на стороне сервера).
Ниже приведен пример (пример) реализации службы.
Здесьмой тип данных "сложный объект".
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;
}
}
Это 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);
}
И это реализация сервиса:
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
}
}
Поэтому, когда я звоню getNumElements()
, проблем нет.Когда я звоню getMember(long id)
, я получаю сериализованный "ComplexType" просто отлично.Когда я сериализирую сложный тип и передаю его как FormParam в addMember(ComplexType member)
, я всегда получаю Parameter Class data.ComplexType has no constructor with single String parameter, static valueOf(String) or fromString(String) methods
Я пытался предоставить своего пользовательского провайдера, написав следующий класс:
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;
}
}
А для остальных конфигураций вот мой web.xml:
<?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>
И файл cxf.xml, к которому он относится:
<?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>
А для полноты здесьpom.xml Я использую для создания приложения.
<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>
Любая помощь (решения, указатели или любые другие направления) будет принята с благодарностью.
О, я использую cxf2.4.1 и Spring 3.0.5. ВЫПУСК.Это точная копия моего развернутого приложения.
Спасибо.