Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Spring Beans inside AttributeConverter class

Tags:

I'm developing a Spring Data JPA application, and I've created an AttributeConverter class in order to save an ArrayList of objects as JSON in a database column. Inside this class I need to make use of a class I have defined as a Spring Bean.

As the AttributeConverter class is managed by Hibernate, it seems to be instantiated before any Spring beans are created, and therefore DI does not seem to work (the Spring Bean in the AttributeConverter class is null, and I'm getting a NullPointer exception thrown). So at the moment I'm creating another instance of the said bean to be able to use it in the AttributeConverter class (which defeats the purpose of DI).

I've also tried creating a Util class (annotated with @Component) which implements ApplicationContextAware, which provides a method giving the SpringBean (cxt.getBean(BeanClass.class)). But this also is instantiated after the AttributeConverter.

Is there any idea of how this can be solved?

Thank you.

like image 435
Effie Makri Avatar asked Nov 10 '17 09:11

Effie Makri


2 Answers

With JPA 2.2, Spring 5.1( SPR-16305) and Hibernate 5.3.0 (HHH-12135) you no longer need to use the mutable static property hack and can use dependency injection just like you would on a regular spring managed bean (note that annotations are no longer necessary):

public class MyAttributeConverter implements AttributeConverter<X,Y> {      private final MySpringBean bean;      public MyAttributeConverter(MySpringBean bean) {         this.bean = bean;     }      public Y convertToDatabaseColumn(X attribute) {       ...     }      public X convertToEntityAttribute(Y dbData) {       ...     } } 
like image 126
Lovro Pandžić Avatar answered Sep 20 '22 12:09

Lovro Pandžić


You can inject a bean(@Component, @Service, @Repository) inside an AttributeConverter using static properties

Setps:

  1. Set in your AttributeConverter with the following annotations: @Component, @Converter and @Configurable
  2. Define the field that you want to autowired with the static modifier access
  3. Create an init method in order to autowired the repository
  4. Implement the methods defined in the interface AttributeConverter

Basically, the code should look like this...

//Step 1 @Component @Converter @Configurable public class MyAttributeConverter implements AttributeConverter<X,Y> {     //Where: X = the type of the entity attribute and Y = the type of the database column      //Step 2     private static MyRepository myRepository;      //Step 3     @Autowired     public void initMyRepository(MyRepository myRepository){         MyAttributeConverter.myRepository = myRepository;     }      //Step 4     Y convertToDatabaseColumn(X attribute){//TODO implement method}     X convertToEntityAttribute(Y dbData){//TODO implement method} } 

I hope it can help!!!

like image 42
Gustavo Ponce Avatar answered Sep 16 '22 12:09

Gustavo Ponce