Default Date value Hibernate - mysql

I am inserting some data on a MySQL db without any problem. Now I want to add one more column "date" and I want to insert as default the Date of the insert. How can I do that?
"FbData.hbm.xml" :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.hibernate.FbData" table="dataresponse" catalog="karma">
<id name="idData" type="java.lang.Integer">
<column name="idData" />
<generator class="identity" />
</id>
<property name="likes" type="java.lang.Long">
<column name="likes" not-null="false" unique="false" />
</property>
<property name="shares" type="java.lang.Long">
<column name="shares" not-null="false" unique="false" />
</property>
<property name="time" type="string">
<column name="time" not-null="false" unique="false" />
</property>
<property name="idPage" type="string">
<column name="idPage" not-null="false" unique="false" />
</property>
</class>
</hibernate-mapping>
And my Class with getters and setters:
public class FbData implements Serializable{
private static final long serialVersionUID = 1L;
private Integer idData;
private Long likes;
private Long shares;
private String time;
private String idPage;
}
Thanks in Advance!!!

The Hibernate specific way to do this is to use the #CreationTimestamp annotation.
#Entity
public class SomeEntity {
#CreationTimestamp
private Date date;
}
From the javadoc found here:
Marks a property as the creation timestamp of the containing entity. The property value will be set to the current JVM date exactly once when saving the owning entity for the first time.
Supported property types:
java.util.Date
Calendar
java.sql.Date
Time
Timestamp
If you want to do this using a JPA-specific solution, you can do this two ways:
Apply an Entity Listener handler.
Apply a #PrePersist callback method on the entity
To apply an entity listener:
// A simple interface
public interface CreationTimestampAware {
void setCreationTime(Date date);
Date getCreationTime();
}
// Define the entity listener
public class CreationTimestampListener {
#PrePersist
public void onPrePersist(Object entity) {
// entity implements a CreationTimestampAware interface that exposes
// the single method #setCreationTime which we call here to set
// the value on the entity.
//
// Just annotate the entities you want with this functionality
// and implement the CreationTimestampAware interface
if ( CreationTimestampAware.class.isInstance( entity ) ) {
( (CreationTimestampAware) entity ).setCreationTime( new Date() );
}
}
}
// Link to your entity
#EntityListeners({CreationTimestampListener.class})
public class SomeEntity implements CreationTimeAware {
// specify your date property and implement the interface here
}
If you need the functionality across multiple entities, you can easily hook into this with minimal effort and manage the functionality in one place rather than in multiple entities.
But that's a lot of work for a simple, single entity feature. If that is the case, you can use the other suggested answer with just adding an annotated JPA callback method on the entity itself
#PrePersist
private void onPersistCallback() {
// just set the value here
// this will only ever be called once, on a Persist event which
// is when the insert occurs.
this.date = new Date();
}

You can use #PrePersist annotation to assign current date to the attribute before inserting the row to database
#PrePersist
protected void onCreate() {
if (date == null) {
date = new Date();
}
}
This way, if you don't set the value of the date and try to persist the object to the DB, you'll get current date as a value.

Related

Null value in json whereas retrieving all the values in log in struts,spring and hibernate

I am using Struts,Spring and Hibernate Integration. I have written a method in DAO implementation to return list object from db.When I trigger the action to call the DAO ,I get correct values in log whereas i get null values in json file. Kindly suggest me some solution.
My basic requirement is that I want to get Json response(for List object) to be sent from action to jsp.
Thanks in advance.
Struts.xml
<action name="loadJsonAction" class="loadJsonActionClass"
method="loadGrid">
<result name="success" type="json">/pages/jsp/index.jsp
</result>
<result name="error">/pages/jsp/index.jsp
</result>
</action>
Application Context.xml
<bean id="deviceDao" class="com.example.daoImpl.DeviceDaoImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"></property>
</bean>
<bean id="deviceService"
class="com.example.serviceImpl.DeviceServiceImpl">
<property name="deviceDao" ref="deviceDao" />
<property name="transactionManager" ref="transactionManager"></property>
</bean>
<bean id="loadJsonActionClass" class="com.example.action.DeviceInfoAction">
<property name="deviceService" ref="deviceService" />
</bean>
Code in Action Class
public String loadGrid() {
getDeviceService().getDeviceInfoById(1);
return "success";
}
Code in Service Class
#Override
public List<Device> getDeviceInfoById(Integer id) {
return getDeviceDao().getDeviceInfoById(id);
}
Code in Dao Class
#Override
public List<Device> getDeviceInfoById(final Integer id) {
return this.hibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session) {
Device deviceInfo;
Criteria criteria = session.createCriteria(Device.class);
criteria.add(Restrictions.eq("id", id));
List<Device> deviceList = criteria.list();
if (deviceList .size() != 0) {
logger.debug("device name from db "
+ deviceList .get(0).getDeviceName());
deviceInfo = deviceList .get(0);
}
return deviceList ;
}
});
}
JSON Respose
{"accountId":null,"androidVersion":null,"baseLocationId":null,"basebandVersion":null,"bluetoothAddress":null,"brand":null,"buildNumber":null,"device":null,"deviceAddedDate":null,"deviceDetails":null,"deviceFileInfo":null,"deviceId":null,"deviceImageUrl":null,"deviceName":null,"deviceNetworkInfo":null,"deviceSettingsInfo":null,"deviceType":null,"emailId":null,"firstName":null,"groupId":null,"imeiNo1":null,"imeiNo2":null,"isDeviceTracked":null,"isDualMode":null,"isSdCardAvailable":null,"kernelVersion":null,"lastName":null,"lastUpdateBy":null,"lastUpdatedDate":null,"manufacturer":null,"model":null,"nickName":null,"osVersion":null,"phoneNumber":null,"product":null,"rowStatus":null,"screensize":null,"serialNumber":null}
values in log
DEBUG[DeviceDaoImpl$2]: device name from db: generic
Since I am using Spring and ModelDriven in Action, it processes everything as a Model.As there was no field for deviceList before in model,I was not able to get the response as List. Now I added deviceList to model class and set the deviceList to the value retrieved from database using the following code :
deviceBean.setDeviceList(getDeviceService().getDeviceInfoById(1));
Now it works fine

Spring Data Rest - Configure pagination

Using Spring Data REST with JPA in version 2.1.0.
How can I configure the pagination in order to have the page argument starting at index 1 instead of 0 ?
I have tried setting a custom HateoasPageableHandlerMethodArgumentResolver with an mvc:argument-resolvers, but that doesn't work:
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.data.web.HateoasPageableHandlerMethodArgumentResolver">
<property name="oneIndexedParameters" value="true"/>
</bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>
Note that this behaviour is perfectly coherent with the documentation for mvc:argument-resolver that says:
Using this option does not override the built-in support for
resolving handler method arguments. To customize the built-in support
for argument resolution configure RequestMappingHandlerAdapter
directly.
But how can I achieve this ? If possible, in a clean and elegant way ?
The easiest way to do so is to subclass RepositoryRestMvcConfiguration and include your class into your configuration:
class CustomRestMvcConfiguration extends RepositoryRestMvcConfiguration {
#Override
#Bean
public HateoasPageableHandlerMethodArgumentResolver pageableResolver() {
HateoasPageableHandlerMethodArgumentResolver resolver = super.pageableResolver();
resolver.setOneIndexedParameters(true);
return resolver;
}
}
In your XML configuration, replace:
<bean class="….RepositoryRestMvcConfiguration" />
with
<bean class="….CustomRestMvcConfiguration" />
or import the custom class instead of the standard one in your JavaConfig file.
I have configured the RequestMappingHandlerAdapter using a BeanPostProcessor, however I believe that's neither clean, nor elegant. That looks more like a hack. There must be a better way ! I'm giving the code below just for reference.
public class RequestMappingHandlerAdapterCustomizer implements BeanPostProcessor {
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof RequestMappingHandlerAdapter) {
RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter)bean;
List<HandlerMethodArgumentResolver> customArgumentResolvers = adapter.getCustomArgumentResolvers();
if(customArgumentResolvers != null) {
for(HandlerMethodArgumentResolver customArgumentResolver : customArgumentResolvers) {
if(customArgumentResolver instanceof HateoasPageableHandlerMethodArgumentResolver) {
HateoasPageableHandlerMethodArgumentResolver hateoasPageableHandlerMethodArgumentResolver = (HateoasPageableHandlerMethodArgumentResolver)customArgumentResolver;
hateoasPageableHandlerMethodArgumentResolver.setOneIndexedParameters(true);
}
}
}
}
return bean;
}
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
}
<beans ...>
<bean class="util.spring.beanpostprocessors.RequestMappingHandlerAdapterCustomizer" />
</beans>
I use to do it using a customizer, which is something that they keep adding for more and more components with every new version:
#Bean
public PageableHandlerMethodArgumentResolverCustomizer pageableResolverCustomizer() {
return resolver -> resolver.setOneIndexedParameters(true);
}
You can put this in any #Configuration class, but ideally you should put it (with any other customization) in one that implements RepositoryRestConfigurer.

Spring 3.0 exception converting String to java.util.Date on POST

I'm hoping someone can help me since I have been banging my head against a wall for a couple of days on a issue which seems straightforward and which has been documented in other threads on the web.
I am using Smart GWT client (3.0) in conjunction with Spring 3.1 server and using JSON to communicate (with Jackson API 1.9).
The issue is that when I attempt to save a date from my SmartGWT client and it is sent to the server I get the following exception:
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'comment' on field 'dateAdded': rejected value [2012-06-27T10:57:47+0100]; codes [typeMismatch.comment.dateAdded,typeMismatch.dateAdded,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [comment.dateAdded,dateAdded]; arguments []; default message [dateAdded]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'dateAdded'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type java.util.Date for value '2012-06-27T10:57:47+0100'; nested exception is java.lang.IllegalArgumentException]
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:110)
I have seen this issue in a few other posts, but most relate to not having formatted the Date in the correct format, but I have tried various formats:
- yyyy-MM-dd
- yyyy-MM-dd'T'HH:mm:ssZ
- yyyyMMddHHmmssZ (as per suggestion here: http://code.google.com/p/usersapi/issues/detail?id=8)
So in my code I have done the following:
Configured a CustomObjectMapper:
`
public class CustomObjectMapper extends ObjectMapper {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
public CustomObjectMapper() {
super();
configure(Feature.WRITE_DATES_AS_TIMESTAMPS, false);
setDateFormat(formatter);
getDeserializationConfig().setDateFormat(formatter);
}
}
`
Spring app context thusly:
`
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<constructor-arg ref="jaxbMarshaller" />
<property name="supportedMediaTypes" value="application/xml"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
<property name="supportedMediaTypes" value="application/json" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<context:component-scan base-package="com.jpmorgan.creditriskreporting.server" />
<bean id="marshallingConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<constructor-arg ref="jaxbMarshaller" />
<property name="supportedMediaTypes" value="application/xml"/>
</bean>
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
<bean id="jacksonObjectMapper" class="com.jpmorgan.creditriskreporting.server.util.CustomObjectMapper" />
<!-- Client -->
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<ref bean="marshallingConverter" />
<ref bean="jsonConverter" />
</list>
</property>
</bean>
`
Bean object:
`
import java.util.Date;
#JsonAutoDetect
public class Comment {
private int id;
private String comment;
private Date dateAdded;
public Comment() {}
public Comment(int id) {
this.id = id;
}
...
//#JsonSerialize(using=JsonDateSerializer.class) -- I had previously tried to use these custom Date serializer class
public Date getDateAdded() {
return dateAdded;
}
//#JsonDeserialize(using=JsonDateDeserializer.class)
public void setDateAdded(Date dateAdded) {
this.dateAdded = dateAdded;
}
`
EDIT:
Controller Class
This may be where the issue lies, since when I use #RequestBody it works from my Integration tests, however, my Abstract RestDataSource in SmartGWT only works with #ModelAttribute, so I'm not sure how to proceed.
#RequestMapping(value="/", method=RequestMethod.POST)
public #ResponseBody Comment createNewComment2(#ModelAttribute Comment comment) {
log.info("calling createComment with comment: {}", comment);
comment.setDateAdded(new Date());
Comment added = commentDao.create(comment);
log.info("created comment: {}", added);
return commentDao.get(comment);
}
So I can fetch data from the server and the date is displayed in SmartGWT fine. It's only when I do the add data that I get the issue. From Smart GWT Developer Console:
{
"dataSource":"CommentDS",
"operationType":"add",
"componentId":"isc_DynamicForm_1",
"data":{
"userAdded":"sharper",
"dateAdded":"2012-06-27T10:57:47+0100",
"comment":"sample"
},
"callback":{
"target":[DynamicForm ID:isc_DynamicForm_1],
"methodName":"saveEditorReply"
},
"showPrompt":true,
"prompt":"Saving form...",
"oldValues":{
},
"clientContext":{
},
"requestId":"CommentDS$6272"
}
Any help with this is hugely appreciated.
Cheers,
Steve
I found out the issue thanks to http://vkubushyn.wordpress.com/2011/05/31/smart-gwt-restful-spring-mvc
Had to use Spring's InitBinder
#InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
You should add DateFormat into your model.
#DateTimeFormat(pattern = "dd.MM.yyyy")
private Date beginDate;
#DateTimeFormat(pattern = "dd.MM.yyyy")
private Date endDate;
as a function parameter
void functionName** (#RequestParam("beginDate") #DateTimeFormat(pattern = "dd.MM.yyyy")Date beginDate, #RequestParam("endDate") #DateTimeFormat(pattern = "dd.MM.yyyy")Date endDate)
I might be wrong, but as far as I remember the Z stands for timezone in ISOwhoknowswhatformat. And that's 4 chars wide, so I would try this:
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZ");
By the way: if this is the issue you should've catched it in your unit tests. You do have unit test for CustomObjectMapper don't you? :P

Spring #ResponseBody Jackson JsonSerializer with JodaTime

I have below Serializer for JodaTime handling:
public class JodaDateTimeJsonSerializer extends JsonSerializer<DateTime> {
private static final String dateFormat = ("MM/dd/yyyy");
#Override
public void serialize(DateTime date, JsonGenerator gen, SerializerProvider provider)
throws IOException, JsonProcessingException {
String formattedDate = DateTimeFormat.forPattern(dateFormat).print(date);
gen.writeString(formattedDate);
}
}
Then, on each model objects, I do this:
#JsonSerialize(using=JodaDateTimeJsonSerializer.class )
public DateTime getEffectiveDate() {
return effectiveDate;
}
With above settings, #ResponseBody and Jackson Mapper sure works. However, I don't like the idea where I keep writing #JsonSerialize. What I need is a solution without the #JsonSerialize on model objects. Is it possible to write this configuration somewhere in spring xml as a one configuration?
Appreciate your help.
Although you can put an annotation for each date field, is better to do a global configuration for your object mapper. If you use jackson you can configure your spring as follow:
<bean id="jacksonObjectMapper" class="com.company.CustomObjectMapper" />
<bean id="jacksonSerializationConfig" class="org.codehaus.jackson.map.SerializationConfig"
factory-bean="jacksonObjectMapper" factory-method="getSerializationConfig" >
</bean>
For CustomObjectMapper:
public class CustomObjectMapper extends ObjectMapper {
public CustomObjectMapper() {
super();
configure(Feature.WRITE_DATES_AS_TIMESTAMPS, false);
setDateFormat(new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'ZZZ (z)"));
}
}
Of course, SimpleDateFormat can use any format you need.
#Moesio pretty much got it. Here's my config:
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven/>
<!-- Instantiation of the Default serializer in order to configure it -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapterConfigurer" init-method="init">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</list>
</property>
</bean>
<bean id="jacksonObjectMapper" class="My Custom ObjectMapper"/>
<bean id="jacksonSerializationConfig" class="org.codehaus.jackson.map.SerializationConfig"
factory-bean="jacksonObjectMapper" factory-method="getSerializationConfig" />
The bit that got me is that <mvc:annotation-driven/> makes its own AnnotationMethodHandler and ignores the one you make manually. I got the BeanPostProcessing idea from http://scottfrederick.blogspot.com/2011/03/customizing-spring-3-mvcannotation.html to configure the one that gets used, and voilà! Works like a charm.
Same using JavaConfig of Spring 3:
#Configuration
#ComponentScan()
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter
{
#Override
public void configureMessageConverters(final List<HttpMessageConverter<?>> converters)
{
converters.add(0, jsonConverter());
}
#Bean
public MappingJacksonHttpMessageConverter jsonConverter()
{
final MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
converter.setObjectMapper(new CustomObjectMapper());
return converter;
}
}
If you are using Spring Boot, try this in application.yml :
spring:
jackson:
date-format: yyyy-MM-dd
time-zone: Asia/Shanghai
joda-date-time-format: yyyy-MM-dd
If you simply have the Jackson JARs on your classpath, and return a #ResponseBody, Spring will automatically convert the Model object to JSON. You don't need to annotate anything in the Model to get this to work.

Jackson serializationConfig

I am using Jackson JSON in a Spring 3 MVC app. To not serialize each and every single Date field, I created a custom objectmapper that uses a specific DateFormat:
#Component("jacksonObjectMapper")
public class CustomObjectMapper extends ObjectMapper
{
Logger log = Logger.getLogger(CustomObjectMapper.class);
#PostConstruct
public void afterProps()
{
log.info("PostConstruct... RUNNING");
//ISO 8601
getSerializationConfig().setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SZ"));
}
//constructors...
}
This custom ObjectMapper is injected into the JsonConverter:
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json" />
<property name="objectMapper" ref="jacksonObjectMapper" /> <!-- defined in CustomObjectMapper -->
</bean>
There is no exception in the logs and serialization works, but it is not picking up the dateformat, it simple serializes to a timestamp. The #PostConstruct annotation works, the log statement in the method is in the logs.
Does anyone know why this fails?
You may also need to specify that you want textual Date serialization, by doing:
configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
(although I was assuming setting non-null date format might also trigger it, but maybe not)
Also, you can do configuration of mapper directly from constructor (which is safe). Not that it should change behavior, but would remove need for separate configuration method.
I've done the below which works to get around compatability with Java / PHP timestamps. Java uses milliseconds since EPOCH and PHP uses seconds so was simpler to use ISO dates.
I declare the below message adapters:
<bean id="messageAdapter"
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean id="jacksonJsonMessageConvertor"
class="my.app.MyMappingJacksonHttpMessageConverter"/>
</list>
</property>
</bean>
And MyMappingJacksonHttpMessageConverter looks like the below:
public class MyMappingJacksonHttpMessageConverter extends MappingJacksonHttpMessageConverter {
public MyMappingJacksonHttpMessageConverter(){
super();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(Feature.WRITE_DATES_AS_TIMESTAMPS, false);
setObjectMapper(objectMapper);
}
}
With the above all dates are written out in ISO format.
For Spring config application.properties
spring.jackson.serialization.fail-on-empty-beans=false