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