user2005533
user2005533

Reputation: 33

Using JAXB @XmlValue with @XmlElementRef

Is it possible to use @XmlValue annotation on a referenced object annotated with @XmlElementRef? The goal is to produce the following XML output:

    <foo>
       <bar>Blah</bar>
    </foo>

Given the following example JAXBContext initialization is throwing a NPE: at com.sun.xml.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:128)

Foo Class

     @XmlRootElement(name = "foo")
     public class Foo
     {
         @XmlElementRef
         private Bar bar;
     }

Bar Class

     @XmlRootElement(name = "bar")
     public class Bar extends BarBase // BarBase is annotated with @XmlTransient
     {
         @XmlValue
         private String value;
     }

Is there any way to achieve the desired output based on the implementation? I've been looking into Adapters, but haven't been successful at implement one. Thanks in advance!

Upvotes: 3

Views: 1340

Answers (3)

Jin Kwon
Jin Kwon

Reputation: 21978

I'm here for exactly the same issue. This issue is still alive with 1.8.0_77.

I bypassed with an additional dummy attribute as user3345125 mentioned.

@XmlAttribute
public String getNothing() {
    return null;
}

For anyone would like to trace. https://github.com/javaee/jaxb-v2/issues/1027

Upvotes: 0

user3345125
user3345125

Reputation: 11

@blaise - as a workaround create an optional @XmlAttribute or @XmlElement within the Bar class

Upvotes: 1

bdoughan
bdoughan

Reputation: 148977

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

JAXB RI Issue Confirmed

I have been able to confirm the issue you are seeing with the JAXB RI. I get the following stack trace:

Exception in thread "main" java.lang.NullPointerException
    at com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:113)
    at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:166)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:494)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:311)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:126)
    at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1148)
    at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:130)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:248)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:235)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:445)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:637)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584)
    at forum14490548.Demo.main(Demo.java:10)

This is a bug in the JAXB RI and I would recommend opening a ticket at the following link:

Option #1 - Use an Alternate Mapping with JAXB RI

The following mapping appears to work with the JAXB RI (using @XmlElement instead of @XmlElementRef.

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "foo")
public class Foo
{
    @XmlElement
    private Bar bar;
}

Option #2 - Use an Alternate JAXB (JSR-222) Provider

Your mappings are correct. If you use another JAXB (JSR-222) provider such as EclipseLink MOXy you will not get this exception. Below is a link that explains how to use MOXy as your JAXB provider:

Upvotes: 3

Related Questions