4

我想使用 Tomcat 6.0 提供的标准资源工厂,它为我创建 javax.mail.Sessions 实例。如JNDI 资源 HOW-TO 教程中所述。

我的 META-INF/context.xml 看起来像:

<?xml version="1.0" encoding="UTF-8"?>
<Context reloadable="true">
    <Resource name="mail/Session" 
          auth="Container" 
          type="javax.mail.Session" 
          mail.smtp.host="smtp.gmail.com"
          mail.smtp.port="587"
          mail.smtp.auth="true"
          mail.smtp.user="someone@gmail.com"
          mail.smtp.password="secretpassword" 
          mail.smtp.starttls.enable="true"/>    
</Context>

我的 WEB-INF/web.xml 中有下一个资源引用,就在 </webapps> 之前。Web.xml 验证。我使用McDowell 的方式进行了验证。

<resource-ref>
    <description>Resource reference to a factory for javax.mail.Session instances that may be used for sending electronic mail messages, preconfigured
    to connect to the appropiate SMTP server.
    </description>
    <res-ref-name>mail/Session</res-ref-name>
    <res-type>javax.mail.Session</res-type>
    <res-auth>Container</res-auth>
    </resource-ref>

我正在使用下一个代码片段访问我的 javax.mail.Session 对象。

Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
Session session = (Session)envCtx.lookup("mail/Session");
System.out.println("HERE smtp.user: " + session.getProperty("mail.smtp.user"));

我在一个示例应用程序中对其进行了测试,它工作正常。不幸的是,当我将相同的代码移动到一个 struts 应用程序时,我在上面的打印语句中得到了 NULL。我在名为 mailer 的单例类中查找上下文(在我的 WEB-INF/classes 文件夹中定义),但是如果我在 Struts 动作类中查找上下文,我会遇到同样的问题。

我一直在想有什么不同的地方才能找到问题。我的 struts 应用程序 web.xml 比简单应用程序的 web.xml 更复杂。它具有安全约束、过滤器和 Struts Servlet 配置。我将 resource-ref 定位在 servlet 定义之前。似乎资源引用被忽略了。

我还有一个问题。如果我在 myapp/WEB-INF/lib 文件夹中有 javax.mail.Session 所需的 mailapi.jar,我会得到:

java.lang.NoClassDefFoundError: javax/mail/Authenticator

如果我把它放在 $CATALINA_HOME/lib 中就找到了。

有任何想法吗?我使用struts和hibernate。也许与此有关。

调试

我试图调试它,将调试属性放在上下文中

<Context reloadable="true" debug="99" ...  

但我没有看到任何有趣的东西。

01-feb-2009 17:39:09 org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()
01-feb-2009 17:39:09 org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextInitialized()
01-feb-2009 17:39:09 org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()
01-feb-2009 17:39:09 org.apache.catalina.core.ApplicationContext log
INFO: SessionListener: contextInitialized()
01-feb-2009 17:39:09 org.apache.catalina.core.ApplicationContext log
INFO: ContextListener: contextInitialized()
01-feb-2009 17:39:09 org.apache.catalina.core.ApplicationContext log

我试过:

Session session = (Session) initCtx.lookup("java:comp/env/mail/Session");

代替:

Context envCtx = (Context) initCtx.lookup("java:comp/env");
Session session = (Session)envCtx.lookup("mail/Session");

但我仍然得到一个 NULL Session 对象。

部分解决方案

当我将 Resource 元素放在 $CATALINA_HOME/conf/context.xml 文件中时,它可以工作。

4

4 回答 4

6

JNDI 查找代码怪癖

我已经看到了多个找不到 JNDI 资源的问题。在 Websphere 上(我知道,你不使用它,但很高兴知道......)你会遇到问题

上下文 envCtx = (Context) initCtx.lookup("java:comp/env");
会话会话 = (会话)envCtx.lookup("邮件/会话");

有效的(在 Websphere 上)是

会话会话 = (Session) initCtx.lookup("java:comp/env/mail/Session");

从您在另一个答案中所写的内容中,我了解到这不是您的问题-我将其留在这里,以供以后在不同情况下遇到相同问题的人们使用。

从自生线程中查找 JNDI 资源

此外,对 JNDI 资源的访问可能取决于查找资源的线程。据我记得,在 servlet api(或 Java EE 或相关领域)中没有很好地定义线程。它甚至可能是自愿和明确地未定义的。因此,服务器在线程中提供 JNDI 资源并不是强制性的你已经产生了自己(Websphere 再次咬我,我没有在这方面测试过 Tomcat6,早期版本用于为所有线程提供 JNDI 资源)

您已经写过您正在从单例中查找 JNDI 资源。如果您在查找资源时检查堆栈跟踪(在您的 IDE 中,通过抛出异常或弄乱Thread.currentThread().getStacktrace()):堆栈跟踪中是否有任何 Tomcat 连接器或者是您自己的 Thread 的 run() 方法之一堆栈跟踪的如果您从 Action 类进行查找,这将回答 Jacks question 背后的问题。(见杰克的回答)

线程和调用环境第二部分

创建一个新的 Struts Action 并从那里调用您的 JNDI 查找代码,看看它是否在靠近 struts 并在 http 请求的处理中工作。如果在这里有效,请继续执行上述步骤。

web.xml 的有效性

此外,您可能希望查看 web.xml 的架构定义,以确保您的资源引用正确定位。servlet 规范 2.4 可在jcp.org上获得,并且应该足以检查,即使 tomcat 实现 2.5。

毕竟,我相信 tomcat6 会验证 web.xml,因此您可能已经将它放在正确的位置。(不记得了,因为我的 IDE 编辑器在我出错时会抱怨,我是否需要编写 web.xml)

Tomcat 调试选项

许多 context.xml 条目尊重属性“调试”。虽然我相信低一位数的值就足够了,但我已经养成了将 'debug="99"' 添加到 'Context' 或其他元素等元素的习惯。您可能想看看这是否会产生一些有用的日志条目。

确保它不是类路径

由于您似乎从根本上改变了环境,请确保您拥有所有必需的库 - 邮件 api 由几个 jars 组成。下载新副本并将所有库解压到 $CATALINA_HOME/lib。一旦它与那里的所有库一起使用,您可能会带走未使用的东西。

关于您的类路径问题

放入 $CATALINA_HOME/lib 时找到类的原因是,连接是由服务器完成的(请记住 - 您已经在 context.xml 中定义了它,服务器会读取它以启动应用程序),因此jar 必须在服务器类路径上 - 不仅仅是在应用程序上(有关更多信息,请参阅tomcat 类加载器 HOWTO )

编辑:

关于您的部分解决方案

$CATALINA_HOME/conf/context.xml 包含全局“默认”上下文元素。这不是您希望应用程序特定配置的位置。

tomcat 的标准位置要么在 webapps META-INF/context.xml 中,要么在 $CATALINA_HOME/conf/Catalina/localhost/ 中的 xml 文件(随意命名,以 .xml 结尾)中。就 META-INF/context.xml 而言,后一种解决方案实际上更受欢迎,因为这样配置独立于应用程序,并且在部署新应用程序时不会被覆盖。

此上下文通常包含附加属性,例如 docBase 和路径:

<Context docBase="/location/where/you/deployed/your/application" path="/app">
  ...
</Context>

这样您的应用程序就可以在http://servername:8080/app. 如果部署到 $CATALINA_HOME/webapps 目录,则 docBase 值可以相对于 webapp。但请注意竞争条件:Tomcat 将在 $CATALINA_HOME/webapps 中自动部署应用程序,并可能创建上下文文件。此外,删除 webapp 以部署新的可能会导致 tomcat 删除 xml 配置文件。

因此-无论您的问题是什么:尝试放置在 $CATALINA_HOME/conf/Catalina/localhost/app.xml 中时您的上下文定义/应用程序是否工作。我觉得这是一件非常简单的事情,只有最后一点信息丢失才能看到真正的问题。

于 2009-02-01T16:08:04.260 回答
1

我相信您应该在 META-INF/context.xml 中定义您的上下文,而不是 META-INF/web.xml(尽管这可能只是您原始帖子中的错字)。

当您说您将代码移至 Struts 应用程序时,您能更具体一点吗?您的意思是您现在正在 Action 类中查找上下文吗?

此外,您可能已经知道这一点,但是在您的 Web 应用程序 META-INF/context.xml 中定义您的上下文(JNDI 条目等)在开发人员的环境中是可以接受的,我强烈反对在任何形式的共享环境中使用它,当然不在生产环境中。

于 2009-02-01T17:21:12.413 回答
1

你有什么建议?

在 JNDI 中定义它,但在您的 Web 应用程序/WAR 之外。在 Tomcat 中,您可以通过将其放在 ${CATALINA_BASE}/conf/context.xml 文件中来执行此操作。这允许在您的 Web 应用程序之外定义外部资源(邮件、数据库等)配置,从而避免在数据库配置更改时重新打包 WAR,或者例如使用不同的数据库移动到不同的环境。

我在称为邮件程序的单例类中查找上下文。

这个邮件类,是在 WEB-INF/classes 中,还是在 WEB-INF/lib 中的 JAR?或者它是否在您的类路径中的其他地方定义?如果是后者,您可能需要考虑将其移至您的应用程序中。


编辑:根据您的最新发现,您的网络应用程序的 META-INF/context.xml 似乎没有生效。Tomcat 中有几种情况会导致这种情况。我不知道这些细节,但这里有一些我能找到的信息:

每 - http://tomcat.apache.org/tomcat-5.5-doc/config/host.html

如果您的 Host 元素中的“deployXML”属性设置为 false(我相信 server.xml)。

deployXML - 如果要禁用解析嵌入在应用程序中的 context.xml 文件(位于 /META-INF/context.xml),则设置为 false。具有安全意识的环境应将其设置为 false 以防止应用程序与容器的配置进行交互。然后管理员将负责提供一个外部上下文配置文件,并将其放在 $CATALINA_HOME/conf/[enginename]/[hostname]/ 中。该标志的值默认为 true。

每 - http://tomcat.apache.org/tomcat-5.5-doc/config/context.html

如果您定义了 $CATALINA_HOME/conf/[enginename]/[hostname]/[context-path].xml 文件。

我敢肯定还有其他的,这些只是我能够快速找到的。

于 2009-02-03T05:40:01.063 回答
0

由于与上述解决方案相比,这是一个完全不同的场景,我选择添加另一个答案而不是编辑前一个答案:

以防万一:确保您的上下文定义中没有错别字将其与 $CATALINA_HOME/conf/context.xml 中的工作版本进行仔细比较

我们不希望“邮件/Sessoin”有所作为……

于 2009-02-08T10:20:13.163 回答