Santosh Ravi Teja
Santosh Ravi Teja

Reputation: 247

I have @xmlrootelement , but keep getting this exception: unable to marshal type as an element because it is missing an @XmlRootElement

I am trying to marshall/unmarshall a class which does not have @xmlrootelement. Can anyone help ? The marshaller I am using is of type Jaxb2Marshaller of the Spring's org.springframework.oxm.jaxb Most of the solutions present are of type javax.xml.bind Marshaller and JAXBContext. Need help in marshalling a Java Class which does not have any @xmlrootelement provided, generated from XML using Spring's JAXB2MARSHALLER.

I am not able to add the @xmlrootelement because this is an external .jar

I have tried all these solutions which actually provide a way of marshalling/unmarshalling using javax instead of spring

unable to marshal type as an element because it is missing an @XmlRootElement annotation for auto generated classes

Unable to marshal type as XML element because @XmlRootElement annotation is missing

Including this which has a very neat explanation but uses Marshaller instead of JaxB2Marshaller

https://howtodoinjava.com/jaxb/marshal-without-xmlrootelement/

Class need to undergo Marshalling without @xmlrootelement

PartnerRequest.java class which has @xmlrootelement

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(
    name = "",
    propOrder = {"partnerCdId", "clientProductCode"}
)
@XmlRootElement(
    name = "PartnerRequest"
)
public class PartnerRequest



    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(
        name = "Partner",
       )
    public class Partner{
    }

Exception I am getting is as below:

[com.sun.istack.internal.SAXException2: unable to marshal type "com.svc.partner.v1.PartnerRequest" as an element because it is missing an @XmlRootElement annotation]
    at org.springframework.oxm.jaxb.Jaxb2Marshaller.convertJaxbException(Jaxb2Marshaller.java:933)
    at org.springframework.oxm.jaxb.Jaxb2Marshaller.marshal(Jaxb2Marshaller.java:709)
    at org.springframework.ws.support.MarshallingUtils.marshal(MarshallingUtils.java:81)
    at org.springframework.ws.client.core.WebServiceTemplate$2.doWithMessage(WebServiceTemplate.java:395)
    at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:573)
    at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:539)
    at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:386)
    at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:380)
    at com.vmd.services.BaseService.marshallSendAndReceive(BaseService.java:53)
    at com.vmd.services.PartnerServiceImpl.getPartner(PartnerServiceImpl.java:27)
    at com.vmd.services.PartnerServiceImplTest.ShouldGetPartner(PartnerServiceImplTest.java:36)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: javax.xml.bind.MarshalException: null
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:311)
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236)
    at org.springframework.oxm.jaxb.Jaxb2Marshaller.marshal(Jaxb2Marshaller.java:705)
    ... 39 common frames omitted
Caused by: com.sun.istack.internal.SAXException2: unable to marshal type "com.svc.partner.v1.PartnerRequest" as an element because it is missing an @XmlRootElement annotation
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:234)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:323)
    at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:479)
    at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:308)
    ... 41 common frames omitted

Also, Remember we need to Marshall it using Jaxb2Mashaller not Marshaller. This is an external jar/dependency not editable code.

Thanks in Advance.

Upvotes: 1

Views: 5892

Answers (4)

Begui
Begui

Reputation: 2856

In spring boot 2, I uses the usually

@Bean
MessageConverter getMessageConveter() {
    Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
    jaxb2Marshaller.setContextPath(ObjectFactory.class.getPackage().getName());
    Map<String, Object> prop = new HashMap<>();
    prop.put(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    jaxb2Marshaller.setMarshallerProperties(prop);
    jaxb2Marshaller.setCheckForXmlRootElement(false);
    return new MarshallingMessageConverter(jaxb2Marshaller);
}

However was still receiving the error. It wasn't until I discovered the I was trying to marshal complex type.. Once I wrapped this Object up in a

<xs:element name="..."

it generated an @XMLRootElement annotation as expected.

Upvotes: 0

Santosh Ravi Teja
Santosh Ravi Teja

Reputation: 247

I was finally able to resolve the issue, The issue was with the Package name and I have seemed to be importing the wrong package, for which it was complaining about partnerRequest missing the @xmlrootelement.

So, finally, we need to be careful, when we have two classes of same name and when Importing with correct packages. Thanks everyone!

Upvotes: 0

Amith Kumar
Amith Kumar

Reputation: 4882

Marshalling & Unmarshalling can't be done without parser to know the root element. So when you don't have @XmlRootElement in the data class, you circumvent using JAXBElement, where you provide your model class wrapped in it, so the marshaller know the what source class structure to refer when parsing.

I have included below the working example of using JAXBElement with spring Jaxb2Marshaller.

@SpringBootApplication
public class XmlTransformationNoRoot {

    public static void main(String[] args) {
        SpringApplication.run(XmlTransformationNoRoot.class, args);
    }

}

@Component
class TestTransformation implements CommandLineRunner {

    public void run(String[] args) throws JAXBException {

        //marshalling
        String testXML = marshallXml(new Partner("HelloWorld"));
        System.out.println("Marshalled : " + testXML);

        //unmarshalling
        System.out.println("Unmarshalled : " + unmarshallXml(testXML, Partner.class));
    }

    public <T> String marshallXml(T object) throws JAXBException {
        StringWriter sw = new StringWriter();
        Result result = new StreamResult(sw);
        jaxb2Marshaller().marshal(new JAXBElement(
                new QName(object.getClass().getPackage().getName(), object.getClass().getSimpleName()),
                object.getClass(), object), result);
        return sw.toString();
    }

    @SuppressWarnings("unchecked")
    public <T> T unmarshallXml(String source, Class<T> clazz) throws JAXBException {
        Jaxb2Marshaller marshaller = jaxb2Marshaller();
        //this line voids singleton use of Jaxb2Marshaller
        marshaller.setMappedClass(clazz);
        return (T) marshaller.unmarshal(new StreamSource(new StringReader(source)));
    }

    public Jaxb2Marshaller jaxb2Marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setMarshallerProperties(new HashMap() {{
            put(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true);
        }});
        marshaller.setClassesToBeBound(new Class[]{Partner.class});
        return marshaller;
    }
}

Hope this helps. Executable source code available at my github repo.

Upvotes: 0

Shivesh Kumar
Shivesh Kumar

Reputation: 108

I fixed the similar exception using JAxBElement:

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

Please try it once, if it is not working then kindly share a sample XSD for further investigation.

Upvotes: 0

Related Questions