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;
    }
}
                Spring @Value annotation is used to assign default values to variables and method arguments. We can read spring environment variables as well as system variables using @Value annotation. Spring @Value annotation also supports SpEL. Let's look at some of the examples of using @Value annotation.
no :) you can use annotations to annotate classes, fields, methods and their arguments. but not in methods, since there is no way, to get method- local variables using reflection in order to process these annotations. Use @Value in your field, and read the value from your method.
The @Qualifier annotation can be used on any class annotated with @Component or on methods annotated with @Bean . This annotation can also be applied on constructor arguments or method parameters. Injecting Bike bean in VehicleService using @Autowired with @Qualifier annotation.
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
Or
@PostConstruct. This method will be executed after the injection process.@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;
    }
}
                        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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With