Question

I am using JAXB and RestEasy.

I am returning a Comprobante.class (JAXB generated class) from a xml file that needs to have:

<cfdi:Comprobante xmlns:cfdi="http://www.sat.gob.mx/cfd/3" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd">...</cfdi:Comprobante>

I have this at package declaration:

@XmlSchema(
    location = "http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd",
    namespace = "http://www.sat.gob.mx/cfd/3",
    elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
    attributeFormDefault = javax.xml.bind.annotation.XmlNsForm.UNQUALIFIED,

    xmlns={
        @XmlNs(
                prefix="cfdi",
                namespaceURI="http://www.sat.gob.mx/cfd/3"
                ),
        @XmlNs(
                prefix="xsi",
                namespaceURI="http://www.w3.org/2001/XMLSchema-instance"
                )
        }) 

But the result of the unmarshaling from the XML file to the JAXB class doesn't have the:

xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd"

It only prints

<cfdi:Comprobante 
xmlns:cfdi="http://www.sat.gob.mx/cfd/3" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">..</cfdi:Comprobante>

My code is:

File p = new File(servletContext.getRealPath("/")+factura.getXml().getCfdi());

JAXBContext context = JAXBContext.newInstance("foo.bar.Model.CFDIv32");
Unmarshaller u = context.createUnmarshaller();

return (foo.bar.Comprobante) u.unmarshal(p);

How can i tell to JAXB Unmarshaller to put the xsi:schemaLocation="" property.

Thank you.

EDIT: how i solved it

See my own answer

Was it helpful?

Solution

Rest easy has JAXB Decorators, so you can add to marshaller properties before marshalling.

1.- Create a DecoratorProcessor

@DecorateTypes({"application/xml"})
public class NameSpaceProcesor implements DecoratorProcessor<Marshaller, CustomMarshaller> {

/* Override method</br>
 * @see org.jboss.resteasy.spi.interception.DecoratorProcessor#decorate(java.lang.Object, java.lang.annotation.Annotation, java.lang.Class, java.lang.annotation.Annotation[], javax.ws.rs.core.MediaType)
 */
@Override
public Marshaller decorate(Marshaller target, CustomMarshaller arg1,
        @SuppressWarnings("rawtypes") Class arg2, Annotation[] arg3, MediaType arg4) {
    try {
        target.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        target.setProperty(Marshaller.JAXB_SCHEMA_LOCATION,"http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv32.xsd");
    } catch (PropertyException e) {
    }
    return target;
}
}

2.- Create your Decorated Annotation.

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Decorator(processor = NameSpaceProcesor.class, target = Marshaller.class)
public @interface CustomMarshaller {}

3.- Then annotate your method with the decorator.

    @GET
@CustomMarshaller
@Path("cfdi")
@Produces({"application/xml", "application/json"})
// /consulta/cfdi?uuid=0a7da89b-a328-4e54-9666-e1a3d7a10b0a
public Comprobante cfdi(...){}

Hope this help some one else.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top