Reputation: 1442
I attempt to serealize and to deserialize LocalDateTime via jackson. I use hibernate + restful webservices. It is my entity:
@Entity
@Table(name = "USERS")
@NamedQueries(value = {
@NamedQuery(name = "getUser", query = "from User user where userId = ?")
})
public class User extends ResourceSupport implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "USER_ID")
private long userId;
@Column(name = "USER_NAME")
private String userName;
@Column(name = "USER_CREATED")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime userCreated;
@Column(name = "USER_PHONE")
private String userPhone;
public User(){}
@JsonCreator
public User(@JsonProperty("userId") long userId,
@JsonProperty("userName") String userName,
@JsonProperty("phone") String phone) {
super();
this.userId = userId;
this.userName = userName;
this.userPhone = phone;
this.userCreated = LocalDateTime.now();
}
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public LocalDateTime getUserCreated() {
return userCreated;
}
public void setUserCreated(LocalDateTime userCreated) {
this.userCreated = userCreated;
}
public String getUserPhone() {
return userPhone;
}
public void setUserPhone(String userPhone) {
this.userPhone = userPhone;
}
@Override
public boolean equals(Object user){
boolean result = false;
if((user==null)||!(user instanceof User))
result = false;
else{
User otherUser = (User)user;
result = this.getUserId() == otherUser.getUserId() &&
this.getUserName() == otherUser.getUserName() &&
this.getUserPhone() == otherUser.getUserPhone()&&
this.getUserCreated() == otherUser.getUserCreated();
}
return result;
}
@Override
public int hashCode(){
return Long.hashCode(userId) ;
}
It is my serializer:
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime>{
@Override
public void serialize(LocalDateTime arg0, JsonGenerator arg1, SerializerProvider arg2)
throws IOException, JsonProcessingException {
// TODO Auto-generated method stub
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDateTime = arg0.format(formatter);
arg1.writeString(formattedDateTime);
}
}
It is my deserializer:
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser arg0, DeserializationContext arg1)
throws IOException, JsonProcessingException {
// TODO Auto-generated method stub
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.parse(arg0.getText(), formatter);
return localDateTime;
}
}
It is my DAO class:
@Repository
public class UserDAOImpl implements UserDAO{
@Autowired
private SessionFactory sessionFactory;
public UserDAOImpl(){}
public UserDAOImpl(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
@Override
public User getUser(long userId) {
//Session session = sessionFactory.getCurrentSession();
Session session = sessionFactory.openSession();
Query query = session.getNamedQuery("getUser");
query.setParameter(0, userId);
return (User)query.uniqueResult();// this string invokes error
}
@Override
public void addUser(User user) {
// TODO Auto-generated method stub
Session session = sessionFactory.openSession();
user.setUserCreated(LocalDateTime.now());
session.save(user);
session.flush();
session.close();
}
It is value of USER_CREATED field of my saved user:
ACED00057372000D6A6176612E74696D652E536572955D84BA1B2248B20C00007870770E05000007E004110F261012C684C078
When I add user to db, adding operation is executing succesfully, but when I attempt get user from DB I get error:
java.io.StreamCorruptedException: invalid stream header: 41434544
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:806) ~[na:1.8.0_73]
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:299) ~[na:1.8.0_73]
at org.hibernate.internal.util.SerializationHelper$CustomObjectInputStream.<init>(SerializationHelper.java:309) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.internal.util.SerializationHelper$CustomObjectInputStream.<init>(SerializationHelper.java:299) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.internal.util.SerializationHelper.doDeserialize(SerializationHelper.java:218) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.internal.util.SerializationHelper.deserialize(SerializationHelper.java:287) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.type.descriptor.java.SerializableTypeDescriptor.fromBytes(SerializableTypeDescriptor.java:138) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.type.descriptor.java.SerializableTypeDescriptor.wrap(SerializableTypeDescriptor.java:113) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.type.descriptor.java.SerializableTypeDescriptor.wrap(SerializableTypeDescriptor.java:27) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.type.descriptor.sql.VarbinaryTypeDescriptor$2.doExtract(VarbinaryTypeDescriptor.java:53) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:47) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:238) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:234) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:224) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:300) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2727) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1728) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1654) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.loader.Loader.getRow(Loader.java:1543) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:727) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.loader.Loader.processResultSet(Loader.java:972) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.loader.Loader.doQuery(Loader.java:930) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:336) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.loader.Loader.doList(Loader.java:2611) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.loader.Loader.doList(Loader.java:2594) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2423) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.loader.Loader.list(Loader.java:2418) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:501) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:371) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:216) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1326) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:87) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.hibernate.internal.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:960) ~[hibernate-core-5.0.5.Final.jar:5.0.5.Final]
at org.company.dao.UserDAOImpl.getUser(UserDAOImpl.java:30) ~[classes/:na]
at org.company.dao.UserDAOImpl$$FastClassBySpringCGLIB$$d4b6a590.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.company.dao.UserDAOImpl$$EnhancerBySpringCGLIB$$21463096.getUser(<generated>) ~[classes/:na]
at org.company.service.UserServiceImpl.getUser(UserServiceImpl.java:39) ~[classes/:na]
at org.company.controller.UserController.getUser(UserController.java:43) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_73]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_73]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_73]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_73]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:817) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:731) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:859) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844) ~[spring-webmvc-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.0.32.jar:8.0.32]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.5.RELEASE.jar:4.2.5.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) ~[tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) [tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522) [tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095) [tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672) [tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) [tomcat-embed-core-8.0.32.jar:8.0.32]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) [tomcat-embed-core-8.0.32.jar:8.0.32]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_73]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_73]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.0.32.jar:8.0.32]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_73]
Upvotes: 0
Views: 7042
Reputation: 718886
I have an idea what is going on here. Here are the clues.
The number 41434544 (hexadecimal) decodes as the letters "A", "C", "E", "D".
A Java object serialization starts with a 16 bit magic number whose value in hexadecimal is ACED. (Reference: https://docs.oracle.com/javase/6/docs/platform/serialization/spec/protocol.html)
So it looks like you have done the following:
The problem is that step 5 is wrong. You need to convert the text to bytes by splitting the string into pairs of characters (hex digits) and converting each pair to a byte.
UPDATE - apparently, Hibernate is doing the serialization behind the scenes, and the correct solution is to stop it happening; see @JB Nizet's answer.
Upvotes: 4
Reputation: 691755
Hibernate doesn't support LocalDateTime, unless you add an additional jar to your classpath.
That means that without it, it treats LocalDateTime as any serializable class, and uses native Java serialization to store the value into a binary column of the table. You really, really don't want that.
Also, don't compare objects with ==
. And note that this has nothing to do with JSON and Jackson.
Upvotes: 3