Ошибка автоподключения JavaMailSenderImpl, если spring.mail.host отсутствует в application.properties

У меня небольшая «проблема» с использованием JavaMailSenderImpl для отправки электронных писем в моем весеннем загрузочном приложении.

Я пытаюсь установить все свойства динамически (в будущем я хочу, чтобы они читались из БД), но по неизвестным мне причинам автоподключение JavaMailSenderImpl работает только в том случае, если в моем приложении присутствует «spring.mail.host». .

Неважно, какое значение я установил (оно может быть пустым, это не имеет значения, потому что правильное я установил позже), но свойство должно быть там, иначе автосвязывание не удастся.

Это мой контроллер:

import java.util.Properties;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller
public class MailController {

    @Autowired
    private JavaMailSenderImpl ms;


    @RequestMapping("/mail")
    public String send(Model model){

        SimpleMailMessage message;
        String fromEmail="[email protected]";
        String toEmail ="xxxxxxx";

        Properties mailProperties = new Properties();
        mailProperties.put("mail.smtp.starttls.enable", true);
        mailProperties.put("mail.smtp.ssl.trust", "smtp.gmail.com");

        ms.setHost("smtp.gmail.com");
        ms.setPort(587);
        ms.setUsername("xxxx");
        ms.setPassword("yyyyy");
        ms.setJavaMailProperties(mailProperties);

        message = new SimpleMailMessage();
        message.setSubject("Test email");
        message.setFrom(fromEmail);
        message.setTo(toEmail);
        message.setText("Something something");

        try{
            ms.send(message);
        }
        catch(MailException ex){
            System.err.println(ex.getMessage());
        }
        return "OK";
    }

}

Будет работать нормально (отправляет электронное письмо) с этим application.properties:

#springboot-starter-mail properties
spring.mail.host=

Но выдаст это исключение, если я удалю эту строку:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.mail.javamail.JavaMailSenderImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
    ... 19 common frames omitted

Я мог бы оставить там пустую собственность, но мне кажется, что это неправильно.

Есть идеи, в чем может быть причина?


person Kepa M.    schedule 24.05.2016    source источник
comment
Триггером для создания JavaMailSenderImpl является наличие свойства spring.mail.host. Не быть там — это нечто иное, как быть пустым. Кроме того, то, что вы делаете, это то, что вы не должны делать в первую очередь. Если вам нужна ваша конфигурация из базы данных, сделайте это, но не перенастраивайте bean-компоненты во время выполнения. Загрузите все свойства при запуске (создайте реализацию PropertySource на основе Jdbc) и позвольте Spring сделать инъекцию за вас. Кроме того, почему база данных? Почему бы не настроить Spring Cloud или что-то еще.   -  person M. Deinum    schedule 24.05.2016
comment
@ M.Deinum Большое спасибо за объяснение, я не знал, что это триггер. Это приложение, которое позволит пользователям отправлять письма, используя свои учетные записи электронной почты. Эта информация будет сохранена в базе данных для каждого пользователя, поэтому я устанавливаю свойства на лету. Я не знаю, есть ли лучшее решение для этого случая, я не эксперт, поэтому любые предложения приветствуются.   -  person Kepa M.    schedule 24.05.2016


Ответы (2)


Autowire интерфейс JavaMailSender вместо реализации.

@Autowired
private JavaMailSender mailSender;
person epdittmer    schedule 24.05.2016
comment
И как мне динамически установить хост, порт, имя пользователя и т. д. с помощью JavaMailSender? - person Kepa M.; 26.05.2016

Не выполняйте автоподключение JavaMailSenderImpl. Вместо этого создайте метод, который создает экземпляр JavaMailSenderImpl и возвращает его со всеми необходимыми параметрами. А затем позвоните отправителю почты, где вам это нужно. Если вы автоматически подключаете отправителя почты, он внедряет экземпляр, которому уже нужен параметр spring.mail.host.

person John Smith    schedule 25.05.2016