Sorin Adrian Carbunaru
Sorin Adrian Carbunaru

Reputation: 618

Serialize a java.util.list in JAX-RS

I have the class book:

@Entity
@Table(name = "books")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType

public class Book {
    @Id
    @XmlAttribute
    private String isbn;

    private String title;
    private String authors;
    private int year;

    @OneToMany(mappedBy="reservedBook")
    private List<Reservation> bookReservations;

    //Getters, setters, addReservation, remove Reservation
        ......................
}

Then, I have class Reservation

@Entity
@Table(name = "reservations")
@XmlRootElement

public class Reservation {

    private String username;
    private String isbn;
    @Temporal(TemporalType.DATE)
    private Date date;

    @ManyToOne
    @JoinColumn(name = "isbn")
    private Book reservedBook;

    @ManyToOne
    @JoinColumn(name = "username")
    private User userWhoReserved;

        //Getters and setters

        ...........
 }

In the resource class I try to get a specific book like this:

@GET
@Path("/{isbn}")
@Produces(MediaType.TEXT_XML)
public Book getBookByIsbn(@PathParam("isbn") String isbn) {

    Book book = entityManager.find(Book.class, isbn);

    if (book != null) {
        return book;

    }

}

Now, it doesn't serialize field List bookReservations. I've tried a lot of ideas found on the internet, like annotating the getter for the list with @XmlElement or using other annotations in other places (I don't remember them now), but nothing worked.

EDIT: This is how a response looks like:

<book isbn="3333333333">
    <title>Mere Christianity</title>
    <authors>C. S. Lewis</authors>
    <year>2000</year>
</book>

but I also want to show the reservations.

What seems to be the solution? Thanks! Sorin

Upvotes: 3

Views: 1240

Answers (5)

Sorin Adrian Carbunaru
Sorin Adrian Carbunaru

Reputation: 618

Solved! But the problem was not the serializing, but the fact that method find() called by the EntityManager could not extract the reservations and put them into my book object, so the list remained empty and its corresponding element was not displayed. So, instead of using find(), it seems that one should use Query:

Query query = entityManager.createQuery("SELECT book FROM Book book WHERE book.isbn = :_isbn ");
query.setParameter("_isbn", isbn);


//if getSingleResult() doesn't find a book, an exception will be thrown
try {
        Book book = (Book)query.getSingleResult();
        return book;
    }
    catch(RuntimeException e)
    {
        //do something
    }

Also, the @XmlAccessorType(XmlAccessType.FIELD) must be deleted from the Book class and the getter for the list should be annotated with @XmlElementWrapper(name = "reservations") and @XmlElement(name = "reservation").

Upvotes: 0

Jin Kwon
Jin Kwon

Reputation: 21978

Wrap with an @XmlRootelement with nillable="true" then an empty <reservations> will be there.

@XmlElement
@XmlElementWrapper(nillable=true)
private List<Reservation> bookReservations;

Upvotes: 0

Thinhbk
Thinhbk

Reputation: 2214

My wild guest is that it's the problem of lazy loading, you may adding fetch = FetchType.EAGER in OneToMany and ManyToOne annotations.

public class Book {
    @Id
    @XmlAttribute
    private String isbn;

    private String title;
    private String authors;
    private int year;

    @OneToMany(mappedBy="reservedBook",fetch = FetchType.EAGER)
    private List<Reservation> bookReservations;

    //Getters, setters, addReservation, remove Reservation
        ......................
    }

And in Reservation class:

 public class Reservation {

    private String username;
    private String isbn;
    @Temporal(TemporalType.DATE)
    private Date date;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "isbn")
    private Book reservedBook;

    @ManyToOne
    @JoinColumn(name = "username")
    private User userWhoReserved;

        //Getters and setters

        ...........
 }

Upvotes: 1

bdoughan
bdoughan

Reputation: 148977

Use @XmlAccessorType.PROPERTY instead of FIELD. The JPA impl may be lazy loading the list of reservations, this action will be triggered by accessing the property (get method).

For More Information

Upvotes: 0

Narendra Pathai
Narendra Pathai

Reputation: 41935

I think the problem may be with the list bookReservations being null.

class A{

    private List<String> someList = new ArrayList<String>();

    @XmlElement(name = "some-tag")
    public List<String> getList() {
        return someList;
    }

    public void setSomeList(List<String> someOtherList) {
        this.someList = someOtherList;
    }
}

I use this code everyday and works for me (Ignore other annotations that I have not provided).

I have faced problem in these cases but only found that due to the list being null for some reason it is not serialized. Try checking whether the list is being set by JAXB in the setter method by debugging at that method.

Upvotes: 3

Related Questions