Restlet - Post Object (даже с Jaxb) не работает
Я попробовал оба: опубликовать объект как объект или завернутый в JAXBElement. Ничто не работает для меня.
//Create Object
Estate DTO estateOne = new EstateDTO("Hotel", "StreetOne", 1, 111111, "England", 1);
///setting up xstream
XStream xstream = new XStream();
xstream.processAnnotations(EstateResourceIF.class);
xstream.processAnnotations(EstateDTO.class);
xstream.autodetectAnnotations(true);
xstream.setClassLoader(new EstateDTO().getClass().getClassLoader());
xstream.alias("estateDTO", EstateDTO.class);
xstream.alias("estateId", Integer.class);
xstream.alias("estateName", String.class);
//post object
service.post(estateOne).write(System.out);
Я даже попытался обернуть это в JAXB:
JAXBElement<EstateDTO> estate = new JAXBElement<EstateDTO>(new QName("estate"), EstateDTO.class, estateOne);
Те же проблемы: я получаю:
Problem creating Marshaller
javax.xml.bind.JAXBException: "com.bachelor.facade.object" doesnt contain ObjectFactory.class or jaxb.index
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:197)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:128)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:277)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:372)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:337)
at org.restlet.ext.jaxb.JaxbRepresentation.getContext(JaxbRepresentation.java:97)
at org.restlet.ext.jaxb.internal.Marshaller$1.initialValue(Marshaller.java:68)
at org.restlet.ext.jaxb.internal.Marshaller$1.initialValue(Marshaller.java:64)
at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:141)
at java.lang.ThreadLocal.get(ThreadLocal.java:131)
at org.restlet.ext.jaxb.internal.Marshaller.getMarshaller(Marshaller.java:163)
at org.restlet.ext.jaxb.internal.Marshaller.marshal(Marshaller.java:216)
at org.restlet.ext.jaxb.JaxbRepresentation.write(JaxbRepresentation.java:530)
at org.restlet.engine.io.BioUtils$1.run(BioUtils.java:305)
at org.restlet.service.TaskService$1$1.run(TaskService.java:132)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Unable to locate marshaller.
JAXB marshalling error caught.
javax.xml.bind.JAXBException: Unable to locate marshaller.
at org.restlet.ext.jaxb.internal.Marshaller.getMarshaller(Marshaller.java:166)
at org.restlet.ext.jaxb.internal.Marshaller.marshal(Marshaller.java:216)
at org.restlet.ext.jaxb.JaxbRepresentation.write(JaxbRepresentation.java:530)
at org.restlet.engine.io.BioUtils$1.run(BioUtils.java:305)
at org.restlet.service.TaskService$1$1.run(TaskService.java:132)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Problem creating Marshaller
javax.xml.bind.JAXBException: "failure" doesnt contain ObjectFactory.class or jaxb.index
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:197)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:128)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:277)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:372)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:337)
at org.restlet.ext.jaxb.JaxbRepresentation.getContext(JaxbRepresentation.java:97)
at org.restlet.ext.jaxb.internal.Marshaller$1.initialValue(Marshaller.java:68)
at org.restlet.ext.jaxb.internal.Marshaller$1.initialValue(Marshaller.java:64)
at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:141)
at java.lang.ThreadLocal.get(ThreadLocal.java:131)
at org.restlet.ext.jaxb.internal.Marshaller.getMarshaller(Marshaller.java:163)
at org.restlet.ext.jaxb.internal.Marshaller.marshal(Marshaller.java:216)
at org.restlet.ext.jaxb.JaxbRepresentation.write(JaxbRepresentation.java:538)
at org.restlet.engine.io.BioUtils$1.run(BioUtils.java:305)
at org.restlet.service.TaskService$1$1.run(TaskService.java:132)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:206)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Unable to locate marshaller.
Даже если я попробую это с:
EstateResourceIF estateResource = service.wrap (EstateResourceIF.class);
List<Preference<MediaType>> acceptedMediaTypes = new ArrayList<Preference<MediaType>>();
acceptedMediaTypes.add(new Preference(MediaType.APPLICATION_JSON));
service.getClientInfo().setAcceptedMediaTypes(acceptedMediaTypes);
estateResource.postEstate(estateOne);
Еще несколько фактов для решения:
EstateDTO класс:
@XmlRootElement
//JAX-RS supports an automatic mapping from JAXB annotated class to XML and JSON
@XmlAccessorType(XmlAccessType.FIELD)
public class EstateDTO implements Serializable{
/**
*
*/
private static final long serialVersionUID = -8545841080597549468L;
@XmlElement(name="estateId")
private String estateId;
@XmlElement(name="owner")
private String owner;
@XmlElement(name="estateName")
private String estateName;
@XmlElement(name="street")
private String street;
@XmlElement(name="number")
private int number;
@XmlElement(name="extraAddressLine")
private String extraAddressLine;
@XmlElement(name="zip")
private int zip;
@XmlElement(name="country")
private String country;
private int space;
private List<String> tenants = new ArrayList<String>();
public EstateDTO() {
}
public EstateDTO(String estateName, String street, int number, int zip, String country, int space) {
this.estateName = estateName;
this.street = street;
this.number = number;
this.zip = zip;
this.country = country;
this.space = space;
}
РЕДАКТИРОВАТЬ:
Сервер Sided Post
@POST
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response postEstate(EstateDTO c) {
//EstateDTO c = estate.getValue();
System.out.println(c);
String generatedId = generateID();
c.setEstateId(generatedId);
c.setOwner(sec.getUserPrincipal().getName());
return postAndGetResponse(c);
}
система на Cosole говорит
EstateDTO [estateId=null, owner=null, estateName=null, street=null, number=0, extraAddressLine=null, zip=0, country=null, space=0, tenants=[]]
Метод postAndGetResponse:
private Response postAndGetResponse(EstateDTO estate) {
Response res;
System.out.println(estate);
if(EstateDAO.instance.getEstateDao().containsKey(estate.getEstateId())) {
res = Response.serverError().status(409).build();
} else {
res = Response.created(UriBuilder.fromUri(uriInfo.getAbsolutePath() + "/" + estate.getEstateId()).build()).entity(estate).build();
EstateDAO.instance.getEstateDao().put(estate.getEstateId(), estate);
}
return res;
}
зависимости:
<dependency>
<groupId>org.restlet.jee</groupId>
<artifactId>org.restlet</artifactId>
<version>${restlet.version}</version>
</dependency>
<dependency>
<groupId>org.restlet.jee</groupId>
<artifactId>org.restlet.ext.xstream</artifactId>
<version>${restlet.version}</version>
</dependency>
<dependency>
<groupId>org.restlet.jee</groupId>
<artifactId>org.restlet.ext.jackson</artifactId>
<version>${restlet.version}</version>
</dependency>
<dependency>
<groupId>org.restlet.jee</groupId>
<artifactId>org.restlet.ext.jaxb</artifactId>
<version>${restlet.version}</version>
</dependency>
<dependency>
<groupId>org.restlet.jee</groupId>
<artifactId>org.restlet.ext.json</artifactId>
<version>${restlet.version}</version>
</dependency>
<dependency>
<groupId>org.restlet.jee</groupId>
<artifactId>org.restlet.ext.xml</artifactId>
<version>${restlet.version}</version>
</dependency>
<!-- Jersey JAXB -->
<!-- <dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.12</version>
</dependency>-->
1 ответ
Ваши отображения JAXB кажутся правильными, и так как вы сопоставили свой класс с @XmlRootElement
Вам не нужно оборачивать объект в JAXBElement
, Я также дважды проверил, и ваши сопоставления XStream, кажется, совпадают с вашими сопоставлениями JAXB (см. Ниже). Моя текущая догадка заключается в том, что проблема заключается в вашем методе публикации Не могли бы вы добавить метод сообщения из службы на ваш вопрос?
EstateDTO
Я упростила твой EstateDTO
класс, используя преимущества JAXB, являющегося конфигурацией в порядке исключения. Это означает, что вам нужно добавлять аннотации только там, где поведение отличается от отображения по умолчанию.
пакет forum11410653;
import java.io.Serializable;
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
//JAX-RS supports an automatic mapping from JAXB annotated class to XML and JSON
@XmlAccessorType(XmlAccessType.FIELD)
public class EstateDTO implements Serializable{
/**
*
*/
private static final long serialVersionUID = -8545841080597549468L;
private String estateId;
private String owner;
private String estateName;
private String street;
private int number;
private String extraAddressLine;
private int zip;
private String country;
private int space;
private List<String> tenants = new ArrayList<String>();
public EstateDTO() {
}
public EstateDTO(String estateName, String street, int number, int zip, String country, int space) {
this.estateName = estateName;
this.street = street;
this.number = number;
this.zip = zip;
this.country = country;
this.space = space;
}
}
демонстрация
Ниже приведен некоторый автономный код JAXB, чтобы убедиться, что все работает.
package forum11410653;
import java.io.*;
import javax.xml.bind.*;
import com.thoughtworks.xstream.*;
public class Demo {
public static void main(String[] args) throws Exception {
EstateDTO estateDTO = new EstateDTO("Hotel", "StreetOne", 1, 111111,
"England", 1);
// setting up xstream
XStream xstream = new XStream();
xstream.processAnnotations(EstateDTO.class);
xstream.autodetectAnnotations(true);
xstream.setClassLoader(new EstateDTO().getClass().getClassLoader());
xstream.alias("estateDTO", EstateDTO.class);
xstream.alias("estateId", Integer.class);
xstream.alias("estateName", String.class);
StringWriter writer = new StringWriter();
xstream.toXML(estateDTO, writer);
String xml = writer.toString();
System.out.println(xml);
// setting up JAXB
JAXBContext jc = JAXBContext.newInstance(EstateDTO.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
EstateDTO unmarshalled = (EstateDTO) unmarshaller
.unmarshal(new StringReader(xml));
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(unmarshalled, System.out);
}
}
Выход
Как вы видете estateName
, street
, а также country
заселены.
<estateDTO>
<estateName>Hotel</estateName>
<street>StreetOne</street>
<number>1</number>
<zip>111111</zip>
<country>England</country>
<space>1</space>
<tenants/>
</estateDTO>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<estateDTO>
<estateName>Hotel</estateName>
<street>StreetOne</street>
<number>1</number>
<zip>111111</zip>
<country>England</country>
<space>1</space>
<tenants></tenants>
</estateDTO>