javaspringspring-bootencryptionjasypt

Loading decrypted Password with Jasypt in Spring Boot


I'm trying to setup the Jasypt workflow with Spring Boot. As described in this Tutorial, I added the required dependency:

<dependency>
        <groupId>com.github.ulisesbocchio</groupId>
        <artifactId>jasypt-spring-boot-starter</artifactId>
        <version>3.0.4</version>
</dependency>

Encrypted the password with:

mvn jasypt:encrypt-value -Djasypt.encryptor.password=javatechie -Djasypt.plugin.value=Password

Created an encrypted.properties and put the encrypted password inside:

secret.property=ENC(nrmZtkF7T0kjG/VodDvBw93Ct8EgjCAaskygdq8PHapYFnlX6WsTwZZOxWInq+i)

Annotated my Main Class:

@SpringBootApplication
@EnableEncryptableProperties
@PropertySource(name = "EncryptedProperties", value = "classpath:encrypted.properties")
public class Main {
    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }
}

In another class I try to load the decrypted value:

@Component
public class MyOtherClass {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyOtherClass.class);

    @Value("${secret.property}")
    String secret;

    public MyOtherClass() {
        LOGGER.info("PW: " + secret);
    }
}

But I just get:

PW: null

When I change the value into something nonexistent:

@Value("${abc.def}")
String secret;

I get the expected error:

java.lang.IllegalArgumentException: Could not resolve placeholder 'abc.def' in value "${abc.def}"

So it seems to find my actual value secret.property, but why it's null?


Solution

  • You are accessing the injected property in the constructor. This does not work because here Spring will instantiate the bean, and then inject the property. So, if you access the property in the constructor you will get the default value before the injection which is null. If you want to access the property in the constructor, then you can use constructor injection like so:

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    @Component
    public class MyOtherClass {
        private static final Logger LOGGER = 
                          LoggerFactory.getLogger(MyOtherClass.class);
    
        String secret;
    
        @Autowired
        public MyOtherClass(@Value("${secret.property}") String secret) {
            LOGGER.info("PW: " + secret);
            this.secret = secret;
        }
    }