2013-12-20 5 views
2

Мы хотим реализовать RESTful-Web-сервис с JAX-RS и JAXB. У нас есть метод PUT, который потребляет XML, который выглядит следующим образом:JAXB: проблемы с JAXB

<mailAccount> 
    <id>-1</id> 
    <name>test</name> 
    <mailaddress>[email protected]</mailaddress> 
    <password>1234</password> 
    <servertype>IMAP</servertype> 
    <host>hallo</host> 
    <port>5678</port> 
    <encryption>SSL/TLS</encryption> 
    <authentication>true</authentication> 
    <interval>12</interval> 
</mailAccount> 

Мы также имеем MailAccount.class, который сопоставляется с XML.

@XmlRootElement 
public class MailAccount { 

private String name; 
private String mailaddress; 
private String password; 
private String servertype; 
private String host; 
private int port; 
private String encryption; 
private boolean authentication; 
private int interval; 
private int id; 

getter + setter... 
} 

Функции PUT-метод выглядит следующим образом:

@PUT() 
@Path("/addMailAccount") 
@Consumes(MediaType.APPLICATION_XML) 
@Produces(MediaType.TEXT_HTML) 
public Response addMailAccount(JAXBElement<MailAccount> mail) throws Exception{ 
    MailAccount mailAccounts = mail.getValue(); 

    StringWriter sw = new StringWriter(); 

    JAXBContext jaxbContext = JAXBContext.newInstance(MailAccount.class); 
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); 

    jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 

    jaxbMarshaller.marshal(mailAccounts, sw); 

    String xmlConsume = sw.toString(); 

    Source source = new StreamSource(new StringReader(xmlConsume)); 

    SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
    Schema schema = sf.newSchema(MailAccountService.class.getResource("/emailAddresses.xsd")); 

    Validator validator = schema.newValidator(); 

    //validator.validate(source); 

    return Response.status(200).entity(xmlConsume +"..."+ mailAccounts.getMailadress()).build(); 
} 

Наша цель состоит в том, чтобы сортировочная в JAXB-элемент, чтобы проверить его против XML-схемы. Но проблема заключается в сортировке: во-первых, элементы не в правильном порядке. Использование тегов propOrder каждый раз появляется во внутренней ошибке сервера.

Вторая проблема заключается в том, что элемент «mailaddress» пуст. Это не сортировка, и когда я помещаю ее в ответ этого метода, значение равно null.

Вот что PUT-метод возвращает:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<mailAccount> 
    <authentication>true</authentication> 
    <encryption>SSL/TLS</encryption> 
    <host>hallo</host> 
    <id>-1</id> 
    <interval>12</interval> 
    <name>test</name> 
    <password>1234</password> 
    <port>5678</port> 
    <servertype>IMAP</servertype> 
</mailAccount> 
...null 
+0

Не можете ли вы в алфавитном порядке сортировать теги в XML-файле, который вы его кормите? Это решит проблему заказа. –

ответ

3

Вот несколько пунктов, которые должны помочь:

propOrder

Ниже приведен пример применения propOrder к твой класс. Важно помнить, что вам нужно включить все сопоставленные поля/свойства, которые сопоставлены с элементами XML в propOrder.

import javax.xml.bind.annotation.*; 

@XmlRootElement 
@XmlType(propOrder={"id", "name", "mailaddress", "password", "servertype", "host", "port", "encryption", "authentication", "interval"}) 
@XmlAccessorType(XmlAccessType.FIELD) 
public class MailAccount { 

    private String name; 
    private String mailaddress; 
    private String password; 
    private String servertype; 
    private String host; 
    private int port; 
    private String encryption; 
    private boolean authentication; 
    private int interval; 
    private int id; 

} 

Ведение схема Validation как часть Маршала операция

Ниже приведен автономный пример, который показывает, как можно использовать проверку схемы в рамках операции маршала вместо того, чтобы делать это как отдельную операцию (см.: http://blog.bdoughan.com/2010/12/jaxb-and-marshalunmarshal-schema.html).

import java.io.File; 
import javax.xml.XMLConstants; 
import javax.xml.bind.*; 
import javax.xml.validation.*; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(MailAccount.class); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     File xml = new File("src/forum20699078/input.xml"); 
     MailAccount mailAccount = (MailAccount) unmarshaller.unmarshal(xml); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 

     SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
     Schema schema = sf.newSchema(MailAccountService.class.getResource("/emailAddresses.xsd")); 
     marshaller.setSchema(schema); 

     marshaller.marshal(mailAccount, System.out); 
    } 

} 
+1

Большое спасибо! Это решает обе проблемы, порядок элементов и теперь элемент emailaddress оценивается правильно !. Спасибо! – AKR

1

Для всех тех, кто должен осуществлять проверку XML с JAX-RS WebService, это мой PUT-метод после того, как подсказки сверху. Сейчас это работает отлично.

@PUT() 
@Path("/addMailAccount") 
@Consumes(MediaType.APPLICATION_XML) 
@Produces(MediaType.TEXT_HTML) 
public Response addMailAccount(JAXBElement<MailAccount> mail) throws MailAccountServiceException{ 
    String xmlConsume = ""; 

    try{ 
     MailAccount mailAccounts = mail.getValue(); 

     StringWriter sw = new StringWriter(); 

     JAXBContext jaxbContext = JAXBContext.newInstance(MailAccount.class); 
     Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); 

     jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 

     SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
     Schema schema = sf.newSchema(MailAccountService.class.getResource("/mailAccount.xsd")); 
     jaxbMarshaller.setSchema(schema); 

     jaxbMarshaller.marshal(mailAccounts, sw); 

     xmlConsume = sw.toString(); 
    } 
    catch(Exception e){ 
     throw new MailAccountServiceException("Fehlerhafte Anfrage: " + e.getCause().getMessage()); 
    } 

    return Response.status(200).entity(xmlConsume).build(); 
} 
+0

Это слишком поздно, но не создавайте новый экземпляр JAXBContext для каждого вызова. Создание нового каждый раз - это много накладных расходов, что может стать причиной больших проблем с производительностью. –