What is the work around for Hibernate 4 persistence support for org.joda.time.contrib.hibernate.PersistentDateTime - spring

Hi All I am new to Spring and am building application using the following dependencies
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time-hibernate</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.7.Final</version>
</dependency>
<spring.framework.version>3.1.2.RELEASE</spring.framework.version>
I am not able to persist the objects with fields with datatype DateTime from the class org.joda.time.contrib.hibernate.PersistentDateTime.
#Column(name = "LAST_MODIFIED_DATE")
#Type(type = "org.joda.time.contrib.hibernate.PersistentDateTime")
public DateTime getLastModifiedDate() {
return lastModifiedDate;
}
Can anybody suggest how to use the joda DateTime.

I had been trying this for entire day finally got the solution as the following. org.joda.time.contrib.hibernate.PersistentDateTime class persistence is not supported by higher versions of hibernate. Rather we use some very specific libraries like the
<dependency>
<groupId> org.jadira.usertype </groupId>
<artifactId> usertype.core </artifactId>
<version> 3.0.0.CR3 </version>
</dependency>
This is how we can persist the data in the database for audit purpose.
#Column(name = "CREATED_DATE")
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
public DateTime getCreatedDate() {
return createdDate;
}

Related

Spring boot connection with mysql workbecnch

I created a spring boot maven project using STS eclipse
In application.properties
spring.datasource.url = jdbc:mysql://localhost:3306/crud
spring.datasource.username = root
spring.datasource.password = root
spring.jpa.hibernate.ddl-auto = update
I created Player entity class, then I run the project but in my workbench there is no table created. Is that because spring boot not connect with db? Then how can I overcome this problem.
This is my pom.xml
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
This is player Entity
#Entity
#Table(name = "PLAYER")
public class Player {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "PLAYER_ID")
private int id;
#Column(name = "PLAYER_NAME")
private String playerName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPlayerName() {
return playerName;
}
public void setPlayerName(String playerName) {
this.playerName = playerName;
}
}
Maybe you didn't create the Database.
You try to create the database or replace the connection string with the following:
spring.datasource.url = jdbc:mysql://localhost:3306/crud?createDatabaseIfNotExist=true
UPDATE
Please add the following dependency in your pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
and delete the following dependency:
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>

Configure LocaldateTime in Spring Rest API

I use Java 10 with latest Spring spring-boot-starter-parent 2.1.0.RELEASE
POM configuration:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.9.7</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.7</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.9.7</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.9.7</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
<version>4.4.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0.1</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.2.0.Final</version>
</dependency>
<dependency>
<groupId>org.jxls</groupId>
<artifactId>jxls-poi</artifactId>
<version>1.0.15</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
</dependencies>
Rest Endpoint:
#GetMapping("{id}")
public ResponseEntity<?> get(#PathVariable String id) {
return transactionRepository
.findById(Integer.parseInt(id))
.map(mapper::toDTO)
.map(ResponseEntity::ok)
.orElseGet(() -> notFound().build());
}
DTO:
public class PaymentTransactionsDTO {
private Integer id;
private String status;
private LocalDateTime created_at;
private String merchant;
.... getters and setters
}
But when I try to return JSON data for LocalDateTime created_at I get empty result. I suppose that LocalDateTime is not properly converted into JSON value.
Can you advice how I can fix this issue?
JSON serialization is driven by Jackson's ObjectMapper, which I recommend configuring explicitely. For proper serialization of the Java 8 date and time objects, make sure to
register the JavaTimeModule
disable writing dates as timestamps
setting the date format (use StdDateFormat)
Description of StdDateFormat:
Default DateFormat implementation used by standard Date
serializers and deserializers. For serialization defaults to using an
ISO-8601 compliant format (format String "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
and for deserialization, both ISO-8601 and RFC-1123.
Recommended configuration:
#Configuration
public class JacksonConfig {
#Bean
public ObjectMapper objectMapper() {
return new ObjectMapper()
.setAnnotationIntrospector(new JacksonAnnotationIntrospector())
.registerModule(new JavaTimeModule())
.setDateFormat(new StdDateFormat())
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
}
}
Examples of serialized date and time objects:
LocalDate: 2018-11-21
LocalTime: 11:13:13.274
LocalDateTime: 2018-11-21T11:13:13.274
ZonedDateTime: 2018-11-21T11:13:13.274+01:00
Edit: standalone dependencies (already included transitively in spring-boot-starter-web):
com.fasterxml.jackson.core:jackson-annotations
com.fasterxml.jackson.core:jackson-databind
com.fasterxml.jackson.datatype:jackson-datatype-jsr310
Try using #JsonFormat on your created_at field.
#JsonFormat(pattern="yyyy-MM-dd")
#DateTimeFormat(iso = DateTimeFormat.ISO.TIME)
private LocalDateTime created_at;
You need to add converter and register in spring eg.
baeldung.com/spring-mvc-custom-data-binder
You can type your PaymentTransactionsDTO "created_at" attribute as a String and use a converter to convert the String to LocalDate (type of the attribute created_at of your entity "PaymentTransactions")
#Component
public class PaymentTransactionsConverter implements Converter<PaymentTransactionsDTO, PaymentTransactions> {
#Override
public PaymentTransactions convert(PaymentTransactionsDTO paymentTransactionsDTO) {
PaymentTransactions paymentTransactions = new PaymentTransactions();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
...
paymentTransactions.setCreated_at(LocalDate.parse(paymentTransactionsDTO.getCreated_at(), formatter));
return paymentTransactions;
}
}
My dates defined as LocalDateTime were been serializaded as an array like this:
"timestamp": [
2023,
2,
15,
10,
30,
45,
732425200
],
So following the Peter Walser answer and using some code of that topic, here is what I did in my WebConfig.java:
#Configuration
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
// other configs
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
WebMvcConfigurer.super.extendMessageConverters(converters);
converters.add(new MappingJackson2HttpMessageConverter(
new Jackson2ObjectMapperBuilder()
.dateFormat(new StdDateFormat())
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build()));
}
}
Now everything is good again:
"timestamp": "2023-02-15T10:32:06.5170689",
Try play around with some Jackson builder properties, hope it's been helpful.

Springboot with Localdatetime and resteasy client

I using springboot to return one LocalDateTime and LocalDate parameter, so in my back I put:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-java8</artifactId>
<version>5.0.12.Final</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.8.2</version>
</dependency>
and in application properties :
spring.jackson.serialization.write_dates_as_timestamps=false
so now my back return this 2 type:
entrada": "2017-01-01T22:00:00", // LocalDateTime
"previsao": "2017-01-01",//LocalDate
in my front I using:
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.8.6</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.1.2.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>3.1.2.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.1.2.Final</version>
</dependency>
and in my class:
ResteasyClient client;
ProtocoloClient protocoloClient;
public ProtocoloClientImpl() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule())
;
client = new ResteasyClientBuilder().register(mapper).build();
ResteasyWebTarget target = client.target("http://localhost:8181/");
protocoloClient = target.proxy(ProtocoloClient.class);
}
So when I call my back I got the erro:
javax.ws.rs.client.ResponseProcessingException: javax.ws.rs.ProcessingException: org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [simple type, class java.time.LocalDateTime] from JSON String; no single-String constructor/factory method (through reference chain: br.com.exmart.indicadorRTDPJ.service.rest.vo.ProtocoloVO["entrada"])
I alredy try to put in my
public class ProtocoloVO {
#JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
private LocalDateTime entrada;
but got the same error
I alredy try to put
#JsonSerialize(using = LocalDateTimeSerializer.class)
#JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime entrada;

How can I use the #Past annotation on a jpa entity?

Without the #Past it is working, but when I use this
#Past
#Temporal(TemporalType.DATE)
private Date birthday;
then I get:
java.lang.ClassNotFoundException: org.joda.time.ReadableInstant
my pom.xml contains
<dependencies>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.8.1</version>
</dependency>
When I copy the joda-time-2.8.1.jar to C:\Program Files\glassfish-4.1\glassfish\modules then I get the same exception.

Spring Bean Validation with Hibernate: validation not happening on update

I have a class defined as follows:
import org.hibernate.validator.constraints.NotBlank;
public class Game {
#GeneratedValue(strategy = GenerationType.AUTO)
#Id
#Column(name = "id")
Long id;
#NotBlank
#Column(name = "title")
String title;
...
However, when I execute the following test, no validation exception is thrown:
#Test(expected = ConstraintViolationException.class)
public void thatExistingGameGivenBlankTitleCannotBeSaved(){
Game game = new Game("SimCity 2000");
gameDAO.save(game);
game.setTitle(" "); //game.setTitle(null) doesn't work either
gameDAO.save(game);
}
How can I make the validator trigger when saving an already persisted object? Preferably through Java configuration.
My validation dependencies:
<!-- validation -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.0.Final</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-cdi</artifactId>
<version>5.1.0.Final</version>
</dependency>
Your JPA implementation has to integrate bean validation. If you're using Hibernate this will happen automatically by putting the validation provider in the class path. If not read 10.1.3. JPA. Given your tags I assume you're using JPA/Hibernate and it should work.
I don't know what gameDAO.save() is calling on your JPA implementation. Hibernate's integration is event based. If your save() is none of these events there will be no validation by default:
PreInsertEvent
PreUpdateEvent
PreDeleteEvent

Resources