1

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.

Santosh Ravi Teja
  • 247
  • 1
  • 7
  • 18
  • Did it resolve your query ? – Amith Kumar Feb 01 '19 at 17:48
  • It actually did not resolve my Query, But seems that I have a PartnerRequest class, which is as follows: `@XmlAccessorType(XmlAccessType.FIELD) @XmlType( name = "", propOrder = {"partnerCdId", "clientProductCode"} ) @XmlRootElement( name = "PartnerRequest" ) public class PartnerRequest` This has `@xmlrootelement` but still it is complaining about missing annotation – Santosh Ravi Teja Feb 01 '19 at 17:59
  • Updated my issue. Do let me know, I have `@xmlrootelement` in the PartnerRequest, still exception shows issue for Partner Request not having it – Santosh Ravi Teja Feb 01 '19 at 18:03
  • Having a `@XmlRootElement`completely reverted the original question. My original solution works for no `@XmlRootElement`. Let me include handling of one with `@XmlRootElement`. – Amith Kumar Feb 01 '19 at 19:02
  • I updated my git repo with the example for one with root element as well. If you still see the issue look for how the Jaxb2Marshaller is initialized & what classes/packages are bound in the context ? Also if you don't have conflict in the PartnerRequest class in the application. If root element is present, it should work without any issues. – Amith Kumar Feb 01 '19 at 19:23
  • Did it resolve you query ? Were you able to achieve the desired result ? Please see [What should I do when someone answers my question?](https://stackoverflow.com/help/someone-answers). As the asker, you have a special privilege: you may accept the answer that you believe is the best solution to your problem. – Amith Kumar Feb 02 '19 at 16:50
  • I was able to resolve it, but definitely your concern helped. Thank you – Santosh Ravi Teja Feb 04 '19 at 15:01
  • Glad I was able to help. Welcome to Stack Overflow. Please note that the preferred way of saying 'thanks' around here is by up-voting good questions and helpful answers (once you have enough reputation to do so), and by accepting the most helpful answer to any question you ask (which also gives you a small boost to your reputation) – Amith Kumar Feb 04 '19 at 17:40

4 Answers4

0

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.

סטנלי גרונן
  • 2,917
  • 23
  • 46
  • 68
0

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.

Amith Kumar
  • 4,400
  • 1
  • 21
  • 28
0

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!

Santosh Ravi Teja
  • 247
  • 1
  • 7
  • 18
0

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.

Begui
  • 2,726
  • 3
  • 22
  • 17