2

EDITED: This application starts fine and runs fine before adding the latest AttributeConverter code. I suspect it is due to the autowiring order. because If I remove the the autowired bean from the attribute converter the application starts fine.

Edited: code of cipherCreator, SecretKey

I am trying to use encryption when persisting values to a database. I implemented an Attribute converter class and and another class for initializing the cipher as well as injecting a config value for the key.

When I decorate my entity class with the AttributeConverter for encryption, the framework does not finish starting.

It stops after ===> Triggering deferred initialization of Spring Data repositories. It does not throw any exceptions to stop. just sits there. If I remove the Autowired annotation from the Cipher creator it starts.

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.0.RELEASE)

2020-08-22 17:10:50.808  INFO 23468 --- [           main] c.c.b.data.xyzApplication   : The following profiles are active: secret,default
2020-08-22 17:10:53.811  INFO 23468 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFERRED mode.
2020-08-22 17:10:54.165  INFO 23468 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 340ms. Found 7 JPA repository interfaces.
2020-08-22 17:10:54.812  INFO 23468 --- [           main] o.s.cloud.context.scope.GenericScope     : BeanFactory id=65cd15a6-6963-3882-983e-554bc1ab6bc0
2020-08-22 17:10:55.187  INFO 23468 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'com.xyz' of type [org.springframework.cloud.openfeign.FeignClientFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-08-22 17:10:55.189  INFO 23468 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'com.xyz' of type [org.springframework.cloud.openfeign.FeignClientFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-08-22 17:10:55.190  INFO 23468 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'com.xyz' of type [org.springframework.cloud.openfeign.FeignClientFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-08-22 17:10:55.192  INFO 23468 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'com.xyz' of type [org.springframework.cloud.openfeign.FeignClientFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-08-22 17:10:55.194  INFO 23468 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'com.xyz' of type [org.springframework.cloud.openfeign.FeignClientFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-08-22 17:10:55.346  INFO 23468 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$a2393a66] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-08-22 17:10:56.480  INFO 23468 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-08-22 17:10:56.502  INFO 23468 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-08-22 17:10:56.502  INFO 23468 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.35]
2020-08-22 17:10:56.709  INFO 23468 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-08-22 17:10:56.709  INFO 23468 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 5867 ms
2020-08-22 17:10:57.755  INFO 23468 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-08-22 17:10:57.840  INFO 23468 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2020-08-22 17:11:00.487  INFO 23468 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2020-08-22 17:11:00.747  INFO 23468 --- [         task-1] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-08-22 17:11:00.879  INFO 23468 --- [         task-1] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.15.Final
2020-08-22 17:11:01.165  WARN 23468 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2020-08-22 17:11:01.307  INFO 23468 --- [         task-1] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-08-22 17:11:01.467  INFO 23468 --- [           main] DeferredRepositoryInitializationListener : Triggering deferred initialization of Spring Data repositories�
2020-08-22 17:11:01.951  INFO 23468 --- [         task-1] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect
2020-08-22 17:11:02.470  WARN 23468 --- [         task-1] org.hibernate.cfg.AnnotationBinder       : 

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.Base64;

@Component
@Converter
public class CustomerEncryptor implements AttributeConverter<String, String>{

    @Autowired
    CipherCreator cipherCreator;

    @Override
    public String convertToDatabaseColumn(String attribute) {
        if(StringUtils.isEmpty(attribute))
            return attribute;
        try {
            return do something...
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String convertToEntityAttribute(String dbData) {
        if(StringUtils.isEmpty(dbData))
            return dbData;
        try {
            do something...
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

I have noticed that if I do not use the

    [@]Autowired
    CipherCreator cipherCreator;

the application starts.

any ideas are appreciated

import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

@Setter
@Getter
@Component
public class CipherCreator {
    private static String ALGORITHM = "AES";
    private Key key;
    private Cipher cipherEnc;
    private Cipher cipherDec;

    @Autowired
    public CipherCreator(SecretKeyProperty keyProperty) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
        key = new SecretKeySpec(keyProperty.getSECRETKEY().getBytes(), ALGORITHM);

        cipherEnc = Cipher.getInstance(ALGORITHM);
        cipherEnc.init(Cipher.ENCRYPT_MODE, key);
        cipherDec = Cipher.getInstance(ALGORITHM);
        cipherDec.init(Cipher.DECRYPT_MODE, key);
    }
}
@Component
public class SecretKeyProperty {

    public String SECRETKEY;


    @Autowired
    public SecretKeyProperty(@Value("${encryption.key}") final String key)  {
        this.SECRETKEY = key;
    }

    public String getSECRETKEY() {
        return SECRETKEY;
    }

    public void setSECRETKEY(String sECRETKEY) {
        SECRETKEY = sECRETKEY;
    }

}
iamomie
  • 21
  • 3
  • 2
    Do you have a circular dependency somewhere? Where is the code that creates the `CipherCreator`. I would also say that your implementation is flawed, you are returning `null` when converting and an exception occurs, this way you could loose data (you should be throwing an exception I suspect). Try adding `spring.data.jpa.repositoriesbootstrap-mode=DEFAULT` to your config, this might trigger some early init of other code. – M. Deinum Aug 24 '20 at 13:51
  • yes, but I tried creating a new very simple entity with no circular dependencies and decorating it, same result – iamomie Aug 24 '20 at 16:37
  • also I tried removing all the circular dependencies to test and it still would not start. – iamomie Aug 24 '20 at 16:56
  • It isn't about entities it is about your converter. You might want to run with debug logging to see what happens and where exactly it stops. I would also suggest to upgrade to Spring Boot 2.3.3 (as you are already are on the 2.3 range). – M. Deinum Aug 24 '20 at 17:23
  • @iamomie I had the exact same problem recently, going from spring `2.3.x` to `2.2.9` solved the problem for me – Pphoenix Oct 30 '20 at 12:35

3 Answers3

3

This is due to the result of a change to the boostrap mode in JPA. To quote the change:

Change the general default to deferred – it parallelizes the bootstrap of the EntityManagerFactory and delays repository initialization to the end of the ApplicationContext initialization

To fix your issue, use bootstrap mode default (spring.data.jpa.repositories.bootstrap-mode=default).

(Props to Stéphane Nicoll at VMware for his help with this, see this discussion at spring github)

Pphoenix
  • 1,423
  • 1
  • 15
  • 37
1

Try adding the @Component annotation to your AttributeConverter, but not the @Converter annotation.

I guess the issue is due to some kind of interlocking between Spring creating its beans, and JPA creating its beans, and both being aware of the other, thanks to both communities’ efforts to make AttributeConverter compatible with Spring beans. In my project, just using @Component works: I suppose Spring then creates all beans, including the AttributeConverter bean, which is borrowed by JPA afterwards… instead of Spring and JPA competing to create beans, using each others’ dependencies, which supposedly results in an interlocking.

Yves
  • 21
  • 1
  • 4
-1

Spring boot embedded tomcat starts either with the spring-boot-starter or with the spring-boot-starter-web(flux). Make sure you have those dependencies in the pom

  • This application starts fine if I remove the attributeConverter annotation from entities I am trying to convert. – iamomie Aug 24 '20 at 13:42
  • That won't help nor is the solution. If you read the question it does startup fine without the converter and with the converter hangs during startup. – M. Deinum Aug 24 '20 at 13:50