views:

472

answers:

3

Not sure if the title makes any sense. I have an object that I want to marshal using JAXB that looks like this:

@XmlRootElement(name = "subscriptionRequest")
    public class RegistrationRequest {

    private Long id;
    private RegistrationSource registrationSource;
    }

The RegistrationSource object:

 public class RegistrationSource {

    private Integer id;
    private String code;
}

I want to create an xml that has the following layout:

<subscriptionRequest registrationSource="0002">
    ...
</subscriptionRequest>

where the registrationSource attribute value is the code field value from the RegistrationSource object.

What xml annotations do I need to use?

+3  A: 

@XmlAttribute on registrationSource, @XmlValue on code. Note that in this case you also should have @XmlTransient on other fields of RegistrationSource, such as id

EDIT: This works:

@XmlRootElement(name = "subscriptionRequest") 
public class RegistrationRequest { 

    private Long id; 
    private RegistrationSource registrationSource; 

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

    @XmlAttribute
    public RegistrationSource getRegistrationSource() { return registrationSource; }
    public void setRegistrationSource(RegistrationSource registrationSource)
    {
        this.registrationSource = registrationSource;
    }
}

-

public class RegistrationSource { 

    private Integer id; 
    private String code; 

    @XmlTransient
    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }

    @XmlValue
    public String getCode() { return code; }
    public void setCode(String code) { this.code = code; }
}
axtavt
I get the following exception: Exception in thread "main" com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions @XmlValue is not allowed on a class that derives another class.
Imhotep
@Imhotep: I added the working code.
axtavt
Before you write down this code I put the annotations on the fields declaration. After I saw your code and applied the changes, I get these:Exception in thread "main" com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 5 counts of IllegalAnnotationExceptions@XmlValue is not allowed on a class that derives another class..If a class has @XmlElement property, it cannot have @XmlValue property..@XmlAttribute/@XmlValue need to reference a Java type that maps to text in XML..Class has two properties of the same name "registrationSource".Class has two properties of the same name "code"
Imhotep
I guess this implementation would work only for marshal right? What if I wanted it to work for unmarshalling too? Shouldn't the annotation's be on the fields' declarations?Thanks a lot for your time. I will be able to respond to any posts by tomorrow.
Imhotep
This code works fine for both marshalling and unmarshalling (hovewer, in `RegistrationService` only `code` field is unmarshalled, because if you use `@XmlValue`, you should mark other fields `@XmlTransient`)
axtavt
A: 

The lame approach would be to add something like

@XmlAttribute(name = "registrationSource")
private String getCode() {
    return registrationSource.code;
}

to your RegistrationSource -- but there must be a more elegant way...

netzwerg
This one works, but as you say it's a bit lame. I'll wait for responses to the other suggestions and if no other possible solution is given, I will mark this as the accepted one. Thanksps: it's like the second solution sb mentioned before you, but it seems he erased his post.
Imhotep
I have to note that in this occasion I also have to put the @XmlTransient annotation on registrationSource object, so that it doesn't show up as an element too.
Imhotep
A: 

If you want to generate this class automatically using some tools , then try this - Generate xsd from your xml using tools like Trang, and then generate java file from xsd using jaxb. Life would be much simpler :)

netlogger