2016-03-23 3 views
0

Mein Webservice erhält ein XML von einer Drittanbieter-Quelle, die eine! DOCTYPE-Deklaration enthält. Daher muss ich die zweite Methode in meinem Controller verwenden, um die XML-Dokument zu analysieren, die erste gibt mir diese Ausnahme: Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not unmarshal to [class com.example.MeterBusXml]: null; nested exception is javax.xml.bind.UnmarshalException - with linked exception: [org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 48; DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" set to true.]spring mvc verarbeitung xml mit relativem pfad zu dtd

Ich habe keine Kontrolle über die Anwendung der xml welche Beiträge, also muss ich meine WebService anpassen zu analysieren es mit der dtd.

Meine Frage ist, was ist die Feder-Framework-Art der Injektion der EntityResolver in jede XMLReader Instanz?

@RestController 
public class MeterBusDataController { 

    @RequestMapping (
    consumes = APPLICATION_XML_VALUE, 
    method = POST, 
    path = "/meterbus1" 
) 
    public void method1(@RequestBody MeterBusXml xml) { 
    System.out.println(xml); 
    } 

    @RequestMapping(
    method = POST, 
    path = "/meterbus2" 
) 
    public void method2(HttpServletRequest rq) throws IOException, ParserConfigurationException, SAXException, JAXBException { 
    JAXBContext jc = newInstance(MeterBusXml.class); 
    Unmarshaller um = jc.createUnmarshaller(); 
    SAXParserFactory spf = SAXParserFactory.newInstance(); 
    spf.setNamespaceAware(true); 
    spf.setValidating(true); 
    SAXParser sp = spf.newSAXParser(); 
    XMLReader xr = sp.getXMLReader(); 
    xr.setEntityResolver(new EntityResolver() { 
     @Override 
     public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { 
     return new InputSource(new StringReader("")); 
     } 
    }); 
    BufferedReader reader = rq.getReader(); 
    InputSource inputSource = new InputSource(reader); 
    SAXSource saxSource = new SAXSource(xr, inputSource); 
    MeterBusXml xml = (MeterBusXml)um.unmarshal(saxSource); 
    System.out.println(xml); 
    } 
} 

Siehe das folgende Dokument für ein Beispiel des mbus.xml ich zu entpacken bin versucht. http://prevodniky.sk/products/product_EthMBus_common/download/Ethernet_converters_exports_v1_02_EN.pdf

Antwort

0

Ich habe die Wurzel des Problems gefunden. Zuerst habe ich versucht, eine Jaxb2Marshaller-Bean zu erstellen und zu konfigurieren, aber das hat nicht geklappt. Dann erkannte ich, ich brauche einen HttpMessageConverter, also musste ich die extendMessageConverters Methode in der WebMvcConfigurerAdapter Klasse überschreiben und die erforderlichen Eigenschaften auf Jaxb2RootElementHttpMessageConverter setzen. Dieser Nachrichtenkonverter verwendet kein Jaxb2Marshaller, aber die internen Abläufe sind sehr ähnlich.

setSupportDtd (true) ist erforderlich, um den Parser zur Annahme der! DOCTYPE-Deklaration zu zwingen.

setProcessExternalEntities (false) ist erforderlich, denn wenn diese Eigenschaft false ist, verwendet der Konverter ein leeres EntityResolver, genau wie in method2.

@Configuration 
public class WebConfiguration extends WebMvcConfigurerAdapter { 

    @Override 
    public void extendMessageConverters(List<HttpMessageConverter<Jaxb2RootElementHttpMessageConverter?>> converters) { 
    for (final Iterator<HttpMessageConverter<?>> iterator = converters.iterator(); iterator.hasNext();) { 
     HttpMessageConverter<?> next = iterator.next(); 
     if (next instanceof Jaxb2RootElementHttpMessageConverter) { 
     Jaxb2RootElementHttpMessageConverter jaxbConverter = (Jaxb2RootElementHttpMessageConverter) next; 
     jaxbConverter.setProcessExternalEntities(false); 
     jaxbConverter.setSupportDtd(true); 
     } 
    } 
    } 
} 
Verwandte Themen