Sir Montes
Sir Montes

Reputation: 952

Spring Boot - @Value annotation doesn't work

I try to create mail service using SmtpAuthenticator. The component is started correctly but null values are in username and password fields. Why is it?

@Component
public class SmtpAuthenticator extends Authenticator {

    private static final Logger LOG = 
    LogManager.getLogger(SmtpAuthenticator.class.getSimpleName());

    @Value("${spring.mail.username}")
    private String username;
    @Value("${spring.mail.password}")
    private String password;

    public SmtpAuthenticator() {
        LOG.info(SmtpAuthenticator.class.getSimpleName() + " started...");
        LOG.debug("username=" + username);
    }

    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)) {
            LOG.debug("Username and password are correct...");
            return new PasswordAuthentication(username, password);
        }
    LOG.error("Not correct mail login data!");
    return null;
    }
}

Upvotes: 12

Views: 23133

Answers (2)

Jaykishan
Jaykishan

Reputation: 1499

Moved no argument constructor code to PostConstruct has done the trick for me. As it'll keep default bean loading workflow intact.

Try this solution. https://stackoverflow.com/a/72547797/2002804

Upvotes: 2

so-random-dude
so-random-dude

Reputation: 16465

You guessed it right, the values will get injected only after the objects gets instantiated; because the spring container cannot set a property of something which doesn't exist yet. So while in constructer, those fields will still be null. One solution is, either

  1. Switch to constructer Injection instead of setter Injection (YMMV, havnt tested your usecase)

Or

  1. Replace the constructor with a method annotated with @PostConstruct. This method will be executed after the injection process.

for example

@Component
public class SmtpAuthenticator extends Authenticator {
    private static final Logger LOG = 
    LogManager.getLogger(SmtpAuthenticator.class.getSimpleName());

    @Value("${spring.mail.username}")
    private String username;
    @Value("${spring.mail.password}")
    private String password;

    @PostConstruct
    public void init() {
        LOG.info(SmtpAuthenticator.class.getSimpleName() + " started...");
        LOG.debug("username=" + username);
    }

    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)) {
            LOG.debug("Username and password are correct...");
            return new PasswordAuthentication(username, password);
        }
    LOG.error("Not correct mail login data!");
    return null;
    }
}

Upvotes: 19

Related Questions