BeanPropertyRowMapper does not understand joda time types anymore since upgrading to spring boot 1.4 / spring cloud camden - spring-boot

I have a Spring Batch Job that defines a JdbcPagingItemReader with a BeanPropertyRowMapper :
JdbcPagingItemReader<RawNotice> reader = new JdbcPagingItemReader<>();
final SqlPagingQueryProviderFactoryBean sqlPagingQueryProviderFactoryBean = new SqlPagingQueryProviderFactoryBean();
sqlPagingQueryProviderFactoryBean.setDataSource(dataSource);
sqlPagingQueryProviderFactoryBean.setSelectClause("select *");
sqlPagingQueryProviderFactoryBean.setFromClause("from a_table");
sqlPagingQueryProviderFactoryBean.setWhereClause("state = :state");
sqlPagingQueryProviderFactoryBean.setSortKey("id");
Map<String, Object> parameters = new HashMap<>();
parameters.put("state", "interesting_state");
reader.setQueryProvider(sqlPagingQueryProviderFactoryBean.getObject());
reader.setDataSource(dataSource);
reader.setPageSize(10);
// The line below is the interesting one
reader.setRowMapper(new BeanPropertyRowMapper<>(MyEntity.class));
reader.setParameterValues(parameters);
return reader;
This used to work fine, but since we upgraded to spring boot 1.4 and spring cloud Camden, it throws an exception :
org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type [java.sql.Timestamp] to required type [org.joda.time.LocalDateTime] for property 'ADateColumn'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.sql.Timestamp] to required type [org.joda.time.LocalDateTime] for property 'ADateColumn': no matching editors or conversion strategy found
The column ADateColumn is declared as a Joda LocalDateTime and stored as a java.sql.Timestamp in the database.
I'm quite aware I could add my own joda converters to the BeanPropertyRawMapper conversionService for example, or create a PropertyEditor that understands Java LocalDateTime, but that looks rather like a configuration problem, like something isn't being registered right.
Anybody with a solution/suggestion to fix this problem ?
Thanks !
This is the part of the entity that poses problem :
#Entity
#EqualsAndHashCode(of = { "..." })
#ToString(of = { .... })
public class MyEntity {
#Getter
#Setter
#Id
#GeneratedValue
private Long id;
#Getter
#Version
#Column(nullable = false)
private int version;
//<--- snip --->
#Getter
#Setter
#Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime")
private LocalDateTime aDateColumn;
}
Hibernate is version 4.3.11.Final
JPA is version 2.1 with Hibernate Entity Manager 4.3.11.Final

So I finally ended up creating my own BeanPropertyRowMapper with custom Joda converters :/

Related

Ignore xml tags while serializing pojo fields to xml

I am using jackson library to map POJO to XML.
compile ('com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.0')
While serializing I need to ignore some of the fields. This is my POJO class. For example, the field lineNumber should be ignored.
#NoArgsConstructor
#AllArgsConstructor
#Getter
#XmlAccessorType(XmlAccessType.FIELD)
public class InvoiceLineItem {
#JacksonXmlProperty(localName = "LineNumber")
#XmlTransient
private Integer lineNumber;
#JacksonXmlProperty(localName = "ProductCode")
#XmlTransient
private String productCode;
#JacksonXmlProperty(localName = "ProductDescription")
#XmlTransient
private String productDescription;
}
I am using #XmlTransient with XmlAccessorType to ignore the fields. But the lineNumber field annotated with XmlTransient is not ignored while serializing.
Try adding the #JsonProperty(access = Access.WRITE_ONLY)
annotation to the lineNumber field.
Even thought it looks like a JSON thing,
the Jackson XmlMapper identifies the annotation and reacts accordingly.
Edit
The conclusion XmlMapper should support JSON serizlization is an example of the following, incorrect attempt at reasoning:
All men are mortal.
Socrates was mortal.
Therefore, all men are Socrates.
The XmlMapper is not a wrapper class around ObjectMapper.
It came after ObjectMapper and appears to share many features,
like the handling of some JSON annotation.

Spring mongo InvalidPersistentPropertyPath with #Version

I was migrating from spring boot 2.0.0 to 2.1.1. After migrating one of the several issues that I am facing is the InvalidPersistentPropertyPath for documents with certain fields and #version. This used to work previuosly with Spring boot 2.0.0
Below is the sample document that I want to save in mongo db:
#Document
#Data
#NoArgsConstructor
public class Report implements Serializable {
#Id
protected String id;
#NotNull
#Field("ReportName")
protected String reportName;
#Field("IA1Value")
private Long iA1Value = 0L;
#Field("IA2Value")
private Long iA2Value = 0L;
#Version
private Long version;
public Report(String reportName) {
this.reportName = reportName;
}
}
I wrote a test case to read and save to the mongo DB.
org.springframework.data.mapping.context.InvalidPersistentPropertyPath:
No property 'IA1Value' found on class
com.experiments.migration.mongo.Report! Did you mean:
IA2Value,IA1Value,iA2Value,iA1Value?
But if the #Version is commented it works....
I would like to know what the relation is with #Version.
The entire sample is there in :
https://github.com/KencyK/spring-boot-migration
NOTE : Please DO NOT suggest to keep the field name. Coz i know that would fix it. I would like to know why this works if I remove the #Version.
Also I have tried with older version of Lombok which was used in spring boot 2.0.0

Spring JPA naming query with orderBy doesn't work

I'm using Spring Boot 2, Spring JPA, Spring Data.
I'm trying to get the first result from a table in which I want to sort results by a int property asc.
This is my bean:
#Entity
public class DatabaseInstance extends AbstractEntity {
#NotNull
#Enumerated(EnumType.STRING)
#Column(nullable = false)
private Supplier supplier;
NotNull
#Column(nullable = false, columnDefinition = "INT DEFAULT 0.0")
private int databaseCount = 0;
and this is my repository:
#Transactional
public interface DatabaseInstanceRepository extends JpaRepository<DatabaseInstance, Long> {
public Optional<DatabaseInstance> findFirstOrderByDatabaseCountAsc();
}
According to Spring manual I can order by property name + asc word. At the same time I want the first result (so i get the instance with the lower databaseCount value).
I get this error:
Caused by: org.springframework.data.mapping.PropertyReferenceException: No property asc found for type int! Traversed path: DatabaseInstance.databaseCount.
I am not able to figure out what's wrong with my method name. Some advice?

Spring Data JPA native query result binding

Entity class:
#Entity
#SqlResultSetMapping(
name="hourMapping",
classes=#ConstructorResult(
targetClass=Representation.class,
columns={
#ColumnResult(name="hour", type=BigDecimal.class),
#ColumnResult(name="transactions", type=BigDecimal.class)
}
)
)
#NamedNativeQuery(name="MyEntity.reportByHour", query="SELECT hour,SUM(tran_per_hour) AS transactions FROM MY_ENTITY GROUP BY hour ORDER BY hour"
,resultSetMapping="hourMapping")
#Table(name="MY_ENTITY")
public class MyEntity implements Serializable {
Pojo class:
#Data //Lombok
#JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class Representation {
public Representation(BigDecimal hour, BigDecimal transactions) {
this.hour = hour;
this.transactions = transactions;
}
private BigDecimal hour;
private BigDecimal transactions;
Repository interface:
public interface MyEntityRepository extends JpaRepository<MyEntity, MyEntityPK> {
List<Representation> reportByHour();
}
When I run the endpoint which invokes the native query, I get exception:
Failed to convert from type [java.lang.Object[]] to type [com.representation.Representation] for value '{0, 198}'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.math.BigDecimal] to type [com.representation.Representation]
Now if I just have "hour" field returned from my native query (and relevant changes to POJO constructor etc) it works fine.
Any help appreciated.
Ok, false alarm. My hibernate dependencies were all messed up and causing conflicts so resulting in the above exception.
After fixing these dependency issues, works great!!
Long story short: let spring-boot-* handle most hibernate dependencies instead of overriding or managing your own.

spring boot, jackson and localdate

I use spring boot with mysql
in my application.properties
spring.jpa.generate-ddl=true
spring.jackson.serialization.write-dates-as-timestamps=false
In my build.gradle I have
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-data-rest')
compile('org.springframework.boot:spring-boot-starter-web')
compile 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
In my java class
import java.time.LocalDate;
#Entity
public class WebSite implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long webSiteId;
private LocalDate date;
...
}
When this table is created,
date field is created like a TINYBLOB
Why is not a date
This is not an issue with Jackson, but rather that whatever you are using for ORM doesn't know how to convert a Java LocalDate to a MySQL Date.
There are two ways to do this. If you are using Hibernate, you simply include org.hibernate:hibernate-java8 in your dependencies.
Alternatively, if you want just use JPA, you need to create an Attribute Converter. For example:
#Converter(autoApply = true)
public class LocalDateAttributeConverter implements AttributeConverter<LocalDate, Date> {
#Override
public Date convertToDatabaseColumn(LocalDate locDate) {
return (locDate == null ? null : Date.valueOf(locDate));
}
#Override
public LocalDate convertToEntityAttribute(Date sqlDate) {
return (sqlDate == null ? null : sqlDate.toLocalDate());
}
}
The Attribute Converter will handle converting between a Java LocalDate and MySQL Date.
See: http://www.thoughts-on-java.org/persist-localdate-localdatetime-jpa/

Resources