Jersey2+Spring4+Hibernate4
在Resource类中获取某一个id的User对象以xml方式显示在页面上时,提示如下异常:
Caused by: org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/xml, type=class entity.User_$$_jvst87_0, genericType=class entity.User.
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:247)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:106)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:86)
... 49 more
实体类User如下:
package entity;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import config.DateAdapter;
@Entity
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@XmlRootElement
@XmlType(name = "user", propOrder = {
"id",
"name",
"salary",
"birthday"}
)
public class User {
private long id;
private String name;
private Double salary;
private Date birthday;
public User() {
}
public User(long id, String name, Double salary, String birthday) {
super();
this.id = id;
this.name = name;
this.salary = salary;
try {
this.birthday = new SimpleDateFormat("yyyy-MM-dd").parse(birthday);
} catch (ParseException e) {
e.printStackTrace();
}
}
public User(String name, Double salary, String birthday) {
super();
this.name = name;
this.salary = salary;
try {
this.birthday = new SimpleDateFormat("yyyy-MM-dd").parse(birthday);
} catch (ParseException e) {
e.printStackTrace();
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
@XmlJavaTypeAdapter(DateAdapter.class)
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Id
@GeneratedValue
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Override
public String toString() {
String birthdayS = (new SimpleDateFormat("yyyy-MM-dd")).format(birthday);
return "User : id="+id+", Name="+name+", Salary="+salary+", Birthday="+birthdayS;
}
}
Reource类如下:
package resource;
import java.util.List;
import javax.annotation.Resource;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.MessageBodyWriter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import entity.User;
import service.UserService;;
@Singleton
@Path("user")
@Component //@Repository/@Service/@Controller
public class UserResource {
@Context
UriInfo uri;
@Context
HttpHeaders header;
private UserService userService; //Service which will do all data retrieval/manipulation work
public UserService getUserService() {
return userService;
}
@Resource
public void setUserService(UserService userService) {
this.userService = userService;
}
@GET
@Path("/list")
// @Produces(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_XML)
public List<User> listAllUsers() {
return userService.getUsers();
}
//-------------------Retrieve Single User--------------------------------------------------------
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_XML)
// @Produces({MediaType.APPLICATION_JSON})
public User getUser(@PathParam("id") long id) {
System.out.println("Fetching User with id " + id);
User user = userService.getUserById(id);
// User user = new User("n",5000.0,"2015-15-12");
System.out.println(user);
return user;
}
}
UserDaoImpl.java:
package dao;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.orm.hibernate4.HibernateTemplate;
import entity.User;
public class UserDaoImpl implements UserDao {
private HibernateTemplate hibernateTemplate;
public HibernateTemplate getHibernateTemplate() {
return hibernateTemplate;
}
@Resource
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
/* (non-Javadoc)
* @see dao.UserDao#checkUserExistsByUname(java.lang.String)
*/
@Override
public boolean checkUserExistsByUname(String name){
//String sql = "select count(*) from User where uname = '"+uname+"'";
String sql = "from User where name = '"+name+"'";
List list = (List) hibernateTemplate.find(sql);
if(list!=null&&list.size()>0){
return true;
}
return false;
}
/* (non-Javadoc)
* @see dao.UserDao#save(entiey.User)
*/
@Override
public void save(User user){
hibernateTemplate.save(user);
}
@Override
public List<User> getUsers() {
return (List<User>) hibernateTemplate.find("from User");
}
@Override
public User getUserById(long id) {
return hibernateTemplate.load(User.class, id);
}
@Override
public void updateUser(User user) {
hibernateTemplate.update(user);
}
@Override
public void deleteUserById(long id) {
// hibernateTemplate.delete(getUserById(id));
hibernateTemplate.bulkUpdate("delete User where id=?",id);
}
@Override
public void deleteAllUsers() {
hibernateTemplate.bulkUpdate("delete User");
}
}
后来根据异常足迹debug了下:WriterInterceptorExecutor-->MessageBodyFactory,到这个类时,里面有个方法如下:
这里的provider.isWriteable()返回的是false,因为type不是User类型,而是User的代理类(User_$$_rst101_0),User类因有@XmlRootElement,所以可由jersey自动转成xml类型,但User的代理类,jersey没有对应的MessageBodyWriter将其写出,故报异常。至此,原因已经清晰,解决方法就是让拿到的User对象是真正的User对象,而不是代理。由于在dao层获取某一个id的user对象是通过load()方法获取的。
hibernateTemplate.load(User.class, id)
load()拿到的是一个代理对象。这时只需改成get()即可。
hibernateTemplate.get(User.class, id)
小数据量、简单业务情况下,不要使用load(),使用get()。