私はJerseyとMoxyでTomcat 7を使用しています。maven を使用して、jersey.server.jar、jersey.servlet.jar、jersey-core.jar、moxy (org.eclipse.persistence.moxy、バージョン 2.5.0) を追加しました。
インターフェイスがあります (パッケージ名: org.kkm.test.model):
public interface Model extends BaseModel {
public String getConsumerId();
public void setConsumerId(String consumerId);
}
@XmlRootElement(name="reading")
@XmlType(propOrder={"consumerId", "address", "reading", "readingDate", "rotation", "readingStatus"})
public interface Reading extends Model {
@XmlElement
public Address getAddress();
@XmlElement
public double getReading();
@XmlElement
public Date getReadingDate();
@XmlElement
public short getRotation();
@XmlElement
public ReadingStatus getReadingStatus();
public void setAddress(Address address);
public void setReading(double reading);
public void setReadingDate(Date readingDate);
public void setRotation(short rotation);
public void setReadingStatus(ReadingStatus readingStatus);
}
public interface Address {
public String getAddress1();
public String getAddress2();
public String getAddress3();
public String getAddress4();
public void setAddress1(String address1);
public void setAddress2(String address2);
public void setAddress3(String address3);
public void setAddress4(String address4);
}
ReadingImpl と AddressImpl (パッケージ名: org.kkm.test.model.impl) の実装があります。次のようなサービスクラスがあります。
@Path("/sample")
public class TestService {
@GET
@Produces(MediaType.APPLICATION_XML)
@Path("/readings")
public List<Reading> getReadings() {
Reading reading1 = DependencySupplier.getReading();
Address address = DependencySupplier.getAddress();
address.setAddress1("Moolekkadavil");
address.setAddress2("Kottuvallikad");
address.setAddress3("Moothakunnam.P.O");
address.setAddress4("683516");
reading1.setAddress(address);
reading1.setConsumerId("1234567890");
reading1.setReading(11.00);
reading1.setReadingDate(new Date());
reading1.setReadingStatus(ReadingStatus.BILLED);
reading1.setRotation((short) 1);
Reading reading2 = DependencySupplier.getReading();
reading2.setAddress(address);
reading2.setConsumerId("1234567890");
reading2.setReading(11.00);
reading2.setReadingDate(new Date());
reading2.setReadingStatus(ReadingStatus.BILLED);
reading2.setRotation((short) 1);
List<Reading> list = new ArrayList<Reading>();
list.add(reading1);
list.add(reading2);
return list;
}
@GET
@Produces(MediaType.APPLICATION_XML)
@Path("/reading")
public Reading getReading() {
Reading reading1 = DependencySupplier.getReading();
Address address = DependencySupplier.getAddress();
address.setAddress1("Moolekkadavil");
address.setAddress2("Kottuvallikad");
address.setAddress3("Moothakunnam.P.O");
address.setAddress4("683516");
reading1.setAddress(address);
reading1.setConsumerId("1234567890");
reading1.setReading(11.00);
reading1.setReadingDate(new Date());
reading1.setReadingStatus(ReadingStatus.BILLED);
reading1.setRotation((short) 1);
return reading1;
}
}
moxy を使用できるように、次の内容の jaxb.properties ファイルを org.kkm.test.model に配置しました。
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
私のweb.xmlは次のとおりです。
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Test JAX</display-name>
<servlet>
<servlet-name>testjax</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>org.kwa.test.service</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>testjax</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
私が直面している問題は次のとおりです。「/rest/sample/readings」を呼び出すと、XML で正しい表現が得られますが、「/rest/sample/reading」を呼び出すと、
com.sun.jersey.api.MessageException: Java クラスのメッセージ本文ライターなどのエラー。
次に、次のように MessageBodyWriter を作成しました。
public class MyMessageBodyWriter implements MessageBodyWriter {
private List<Class<?>> types;
public MyMessageBodyWriter() {
types = new ArrayList<Class<?>>();
types.add(ReadingImpl.class);
}
public long getSize(Object obj, Class type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
// TODO Auto-generated method stub
return -1;
}
public boolean isWriteable(Class type, Type genericType, Annotation[] annotations,
MediaType mediaType) {
return this.types.contains(type);
}
public void writeTo(Object target, Class type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap headers, OutputStream outputStream)
throws IOException, WebApplicationException {
try {
JAXBContext ctx = JAXBContext.newInstance(type);
Marshaller marshaller = ctx.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(target, outputStream);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
}
「/rest/sample/reading」を呼び出すと、次の XML が取得されます。
<?xml version="1.0" encoding="UTF-8"?>
<address>
<address1>Moolekkadavil</address1>
<address2>Kottuvallikad</address2>
<address3>Moothakunnam.P.O</address3>
<address4>683516</address4>
</address><consumerId>1234567890</consumerId><reading>11.0</reading><readingDate>2013-07-04T21:16:39.128</readingDate><readingStatus>BILLED</readingStatus><rotation>1</rotation>
ご覧のとおり、ルート要素はありません。そのため、「アドレス」をルート要素として取り、「アドレス」要素の後のコンテンツを「追加コンテンツ」と見なしてエラーとして表示します。