【问题标题】:@Inject properties returns null on Tomcat@Inject 属性在 Tomcat 上返回 null
【发布时间】:2017-09-09 05:59:00
【问题描述】:

我创建了一个类来管理发送电子邮件,我想通过属性文件注入 smtp 配置。但是我的字段属性一直为空。 这是我的代码:

public class EmailUtils { 
    @Inject
    @PropertiesFromFile("smtp.properties")
    Properties properties;

    public void sendEmail(String destinator, String subject, String body) {
        final String username = properties.getProperty("smtp.email");
        final String password = properties.getProperty("smtp.password");

        Session session = Session.getInstance(properties,
          new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
          });

        try {

            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress(properties.getProperty("smtp.from")));
            message.setRecipients(Message.RecipientType.TO,
                InternetAddress.parse(destinator));
            message.setSubject(subject);
            message.setText(body);

            Transport.send(message);

            System.out.println("Done");

        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
   }
}

public class PropertyReader {

    @Produces
    @PropertiesFromFile
    public Properties provideServerProperties(InjectionPoint ip) {
    //get filename from annotation
    String filename = ip.getAnnotated().getAnnotation(PropertiesFromFile.class).value();
    return readProperties(filename);
}

    private Properties readProperties(String fileInClasspath) {
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileInClasspath);

        try {
            Properties properties = new Properties();
            properties.load(is);
            return properties;
       } catch (IOException e) {
           System.err.println("Could not read properties from file " + fileInClasspath + " in classpath. " + e);
       } catch (Exception e) {
           System.err.println("Exception catched:"+ e.getMessage());
       } 

       return null;
   }
}

@Qualifier
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface PropertiesFromFile {
    @Nonbinding
    String value() default "application.properties";
}

我用一个简单的 Main 测试了代码,但它不起作用。 我用tomcat对其进行了测试,但仍然在Properties对象上得到了NPE。 我错过了什么? 请帮忙:)

【问题讨论】:

  • 你的两个类都是托管 bean 吗?注入和生产者仅在托管上下文中工作。
  • 嗨 Dimpre,我应该注释它们吗?我阅读的教程没有注释。
  • Tomcat 有 EE 技术的官方发行版,TomEE,很少有版本存在。非常好,与“经典”Tomcat 兼容

标签: tomcat jakarta-ee cdi


【解决方案1】:

请考虑采用这种 Java EE 方式:

  1. 如果使用 Tomcat,请确保您已按照 How to install and use CDI on Tomcat?Application servers and environments supported by Weld 中的说明使用 CDI 实现对其进行设置。

  2. 将 JavaMail 实现 jar 从应用程序的 WEB-INF/lib 移动到 Tomcat lib 目录。

  3. 通过将以下内容添加到它的 config/Context.xml 文件中,在 Tomcat 中配置您的电子邮件会话:

    <Context>
        ...
        <Resource name="mail/Session" auth="Container"
          type="javax.mail.Session"
          mail.smtp.host="your mail host here"
          mail.smtp.user="your user name here"
          password="your password"
          mail.from="noreply@yourdomain.com" />
        ...
    </Context>   
    

    还有其他地方可以放置此配置,但这里解释起来最简单。有关详细信息,请参阅Tomcat JNDI documentation

  4. 简化您的代码:

        @Resource(name="mail/Session")
        private Session session;
    
        public void sendEmail(String destinator, String subject, String body) {
            try {
    
                Message message = new MimeMessage(session);
                message.setRecipients(Message.RecipientType.TO,
                        InternetAddress.parse(destinator));
                message.setSubject(subject);
                message.setText(body);
    
                Transport.send(message);
    
                System.out.println("Done");
    
            } catch (MessagingException e) {
                throw new RuntimeException(e);
            }
        }
    

    您的服务器(在本例中为 Tomcat)负责为您配置邮件会话和身份验证。

类似的机制适用于设置 JDBC DataSource 对象 FWIW。

【讨论】:

  • 谢谢史蒂夫,我使用maven3来管理依赖关系,有没有其他方法可以解决问题?
  • 至少你需要让 CDI 在 Tomcat 中工作。第 1 步为您提供了指导。如果您使用 Tomee、WildFly 或 Payara 服务器,您的生活会更轻松。然后您可以忽略第 1 步。
【解决方案2】:

使用 @Named@ApplicationScoped 注释您的 PropertyReader 类,使其为 CDI 容器所知,以便对其进行管理。在您的课程路径中有一个空白的beans.xml

【讨论】:

    猜你喜欢
    • 2020-05-24
    • 1970-01-01
    • 2012-04-29
    • 1970-01-01
    • 1970-01-01
    • 2015-07-09
    • 2013-05-10
    • 2019-07-17
    • 2018-11-07
    相关资源
    最近更新 更多