I have made a simple CRUD app for learning purposes that uses webservices (with jersey), EJBs and JPA (eclipse link + mysql). I've at first obviously made an entity class called User
and tried to return it, after searching for it for example by ID (with namedquery) like that:
public User findById(Integer id) {
return em.createNamedQuery("User.findById", User.class).setParameter("id", id).getSingleResult();
}
and it works fine (just the finding bit), but upon returning it with:
@GET
@Path("/{id}")
@Produces(MediaType.APPLICATION_XML)
public User find(@PathParam("id") String id) {
return db.find(id);
}
(there is another layer between dao and this above) it always produces an internal server error, without any errors in glassfish console.
Response:
status: 500 Internal Server Error
Date: Mon, 02 Mar 2015 07:02:08 GMT
Server: GlassFish Server Open Source Edition 4.1
Connection: close
X-Powered-By: Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1 Java/Oracle Corporation/1.7)
Content-Length: 1154
The server encountered an internal error that prevented it from fulfilling this request.
My entity class was as follows:
import java.io.Serializable;
import java.lang.Integer;
import java.lang.String;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@Entity
@Table(name="Users")
@NamedQueries({ @NamedQuery(name="User.getAll",
query="SELECT u FROM User u"),
@NamedQuery(name="User.findByName",
query="SELECT u FROM User u WHERE u.name = :name"),
@NamedQuery(name="User.getCount",
query="SELECT COUNT(u) FROM User u"),
@NamedQuery(name="User.findById",
query="SELECT u FROM User u WHERE u.id = :id"),
})
@XMLRootElement
public class User implements Serializable{
@Id
@Column(name="Id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
@Column(name="Name")
private String name;
private static final long serialVersionUID = 1L;
public User() {
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
Now I have tried to extract interface from User, and call it user, rename entity to UserEntity and create a new class implementing User interface - UserXML. It's basic, just id/name fields with getters, setters and XML annotations. When I return user I now do something like this:
public User findById(Integer id) {
UserEntity user = em.createNamedQuery("User.findById", UserEntity.class).setParameter("id", id).getSingleResult();
System.out.println("returning " + user.toString());
User userxml = new UserXML();
userxml.setId(user.getId());
userxml.setName(user.getName());
return userxml;
}
And it works perfectly. Why? What did I do wrong in my first approach?