NRaf
NRaf

Reputation: 7539

JAXB annotations for the following XML

I've spent a while trying to get this to work however I've had little luck.

I have the following XML:

<message>
  <buckets>
    <bucket>
      <channels>
         <channel>Test A</channel>
         <channel>Test B</channel>
      </channels>
      <messageText>This is sample text</messageText>
    </bucket>
    <bucket>
      ....
    </bucket>
  </buckets>
  <userId>10</userId>
 </message>

I'm trying to get this mapped to a POJO using JAXB annotations but am having trouble.

My class is as follows:

@XmlRootElement(name="message")
public class MessageRS {

  public static class Bucket {
    private List<String>channels;
    private String text;

    private Bucket() {}

    public List<String> getChannels() { .... }
    public void setChannels(List<String> channels) { .... }
    public String getText() { .... }
    public void setText(String text) { .... }
  }

  private List<Bucket> buckets;

  private Long userId;

  private MessageRS() { }

  public List<Bucket getBuckets() { .... }
  public void setBuckets(List<Bucket> buckets) { .... }
  public long geUserId() { .... }
  public void setUserId(long UserId { .... }
}

Unfortunately, this doesn't seem to be working correctly. How would I annotate this to correctly map the XML to this object (the desired mapping should be obvious)?

Nothing is set in stone here - I'm free to change both the XML and Java class structures at this point.

Upvotes: 1

Views: 1978

Answers (2)

jtahlborn
jtahlborn

Reputation: 53674

typically, jaxb uses wrapper objects around lists. so, you would have a Buckets class which has List<Bucket> getBuckets(), and you would have a Channels class with List<Channel> getChannels(). i believe there are extra annotations you can use to avoid the extra wrapper classes, but they are not frequently used (at least not by the common auto-generation tools).

personally, i find it much simpler to write the xml schema and use xjc to generate the java classes.

Upvotes: 0

Ryan Stewart
Ryan Stewart

Reputation: 128749

Try this:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.List;

public class JaxbStuff {
    public static void main(String[] args) throws Exception {
        MessageRS message = new MessageRS();
        message.setUserId(10);
        MessageRS.Bucket bucket1 = new MessageRS.Bucket();
        bucket1.setText("This is sample text");
        bucket1.setChannels(Arrays.asList("Test A", "Test B"));
        MessageRS.Bucket bucket2 = new MessageRS.Bucket();
        bucket2.setText("Some more text");
        bucket2.setChannels(Arrays.asList("1", "2"));
        message.setBuckets(Arrays.asList(bucket1, bucket2));
        StringWriter writer = new StringWriter();
        JAXBContext.newInstance(MessageRS.class).createMarshaller().marshal(message, writer);
        System.out.println(writer);
    }

    @XmlRootElement(name = "message")
    static class MessageRS {

        public static class Bucket {
            private List<String> channels;
            private String text;

            private Bucket() {}

            @XmlElementWrapper(name = "channels")
            @XmlElement(name = "channel")
            public List<String> getChannels() {
                return channels;
            }

            public void setChannels(List<String> channels) {
                this.channels = channels;
            }

            public String getText() {
                return text;
            }

            public void setText(String text) {
                this.text = text;
            }
        }

        private List<Bucket> buckets;

        private Long userId;

        private MessageRS() { }

        public List<Bucket> getBuckets() {
            return buckets;
        }

        public void setBuckets(List<Bucket> buckets) {
            this.buckets = buckets;
        }

        public long getUserId() {
            return userId;
        }

        public void setUserId(long UserId) {
            this.userId = UserId;
        }
    }

}

You also had a typo in getUserId(), which would make that property not work correctly. It was geUserId().

Also, it's dangerous to mix Long and long like that. If your userId is null and you call getUserId(), it'll throw a NullPointerException.

Upvotes: 3

Related Questions