Jersey2+Spring4+Hibernate4java
在Resource類中獲取某一個id的User對象以xml方式顯示在頁面上時,提示以下異常:spring
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以下:sql
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類以下:app
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:ide
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,到這個類時,裏面有個方法以下:
this
這裏的provider.isWriteable()返回的是false,由於type不是User類型,而是User的代理類(User_$$_rst101_0),User類因有@XmlRootElement,因此可由jersey自動轉成xml類型,但User的代理類,jersey沒有對應的MessageBodyWriter將其寫出,故報異常。至此,緣由已經清晰,解決方法就是讓拿到的User對象是真正的User對象,而不是代理。因爲在dao層獲取某一個id的user對象是經過load()方法獲取的。hibernate
hibernateTemplate.load(User.class, id)
load()拿到的是一個代理對象。這時只需改爲get()便可。debug
hibernateTemplate.get(User.class, id)
小數據量、簡單業務狀況下,不要使用load(),使用get()。代理