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()。