2

I'm upgrading my application from Spring Boot 1.5 to 2.2. Now my db inits aren't working.

The culprit in my case seems to be the HibernateTransactionManager when using this my @PostConstruct or @EventListener(ApplicationReadyEvent.class)method isn't saving to db, even though the code is running. When removing the transactionManager bean the @PostConstruct code works fine. But I have other code that depend on this bean in my project, so I need it.

Also if I make the same code a rest endpoint and run it manually it always works.

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
    return new HibernateTransactionManager(emf.unwrap(SessionFactory.class));
}
@EventListener(ApplicationReadyEvent.class)
public void initDateRanges(){
    // Check if date ranges already present
    if (!jsonBucketRepo.findById(DateRangeDto.ID).isPresent()) {
        List<DateRangeDto> dateRangeDtoList = new ArrayList<>(5);
        dateRangeDtoList.add(new DateRangeDto("TODAY", "moment().startOf('day').format(dateFormat)", "moment().endOf('day').format(dateFormat)"));
        dateRangeDtoList.add(new DateRangeDto("YESTERDAY", "moment().subtract(1, 'days').startOf('day').format(dateFormat)", "moment().subtract(1, 'days').endOf('day').format(dateFormat)"));
        dateRangeDtoList.add(new DateRangeDto("THIS_WEEK", "moment().startOf('isoweek').format(dateFormat)", "moment().endOf('isoweek').format(dateFormat)"));
        dateRangeDtoList.add(new DateRangeDto("THIS_MONTH", "moment().startOf('month').format(dateFormat)", "moment().endOf('month').format(dateFormat)"));
        dateRangeDtoList.add(new DateRangeDto("LAST_MONTH", "moment().subtract(1, 'months').startOf('month').format(dateFormat)", "moment().subtract(1, 'months').endOf('month').format(dateFormat)"));
        JsonBucket rangeJson = DateRangeDto.dtoList2NewJsonBucket(dateRangeDtoList);
        JsonBucket bucket = jsonBucketRepo.save(rangeJson);
    }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonPropertyOrder({"nameOfRange", "fromMomentSyntax", "toMomentSyntax"})
public class DateRangeDto {

    public static final String ID = "daterange";
    public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().findAndRegisterModules();

    private String nameOfRange;
    private String fromMomentSyntax;
    private String toMomentSyntax;

    public static List<DateRangeDto> jsonBucket2DtoList(JsonBucket result) throws IOException {
        if(!result.id.equals(DateRangeDto.ID)){
            throw new IllegalArgumentException(String.format("JsonBucket has to have ID '%s'", DateRangeDto.ID));
        }
        ObjectReader reader = DateRangeDto.OBJECT_MAPPER.readerFor(new TypeReference<List<DateRangeDto>>() {});
        List<DateRangeDto> list = reader.readValue(result.getJsonNode());
        return list;
    }

    public static JsonBucket dtoList2NewJsonBucket(List<DateRangeDto> rangeDtoList) {
        JsonNode jsonNode = DateRangeDto.OBJECT_MAPPER.valueToTree(rangeDtoList);
        JsonBucket jsonBucket = new JsonBucket(DateRangeDto.ID);
        jsonBucket.setJsonNode(jsonNode);
        return jsonBucket;
    }

    public static JsonNode dtoList2JsonNode(List<DateRangeDto> rangeDtoList) {
        return DateRangeDto.OBJECT_MAPPER.valueToTree(rangeDtoList);
    }
}
@Entity
@Table(name = "tt_json_bucket")
@Data
@NoArgsConstructor
@TypeDef(
        name = "json-node",
        typeClass = JsonNodeStringType.class
)
public class JsonBucket {

    @Id
    String id;

    @Version
    Integer version;

    @Type(type = "json-node")
    @Column(columnDefinition = "VARCHAR(2000)")
    JsonNode jsonNode;

    public JsonBucket(String id) {
        this.id = id;
    }
}
@Repository
public interface JsonBucketRepository extends CrudRepository<JsonBucket, String> {

}
olahell
  • 1,931
  • 3
  • 19
  • 35
  • can you share complete jpa config code? – Mukhtiar Ahmed Mar 14 '20 at 07:05
  • sure I'll update the question, I have now added entities etc. There are no additional JPA config except for `SQLServer2012Dialect`-setting – olahell Mar 16 '20 at 13:44
  • You are using JPA why do you even have a `HibernateTransactionManager` the default `JpaTransactionManager` should be all you need – M. Deinum Mar 17 '20 at 08:18
  • I also have hibernate code in other places like `sessionFactory.getCurrentSession();`. Here it would not work without the Hibernate transaction manager. I did not get it to work with both... – olahell Mar 17 '20 at 08:25
  • Yes main culprit HibernateTransactionManager. You can get hibernate session using `Session session = entityManager.unwrap( Session.class ); ` and use JpaTransactionManager instead of HibernateTransactionManager – Mukhtiar Ahmed Mar 17 '20 at 14:24

0 Answers0