邮件/会话资源工厂在Struts应用程序中不起作用

时间:2009-01-30 09:46:22

标签: tomcat email jndi

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

中所述

我的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中有下一个resource-ref,就在&lt; / webapps&gt;之前。 Web.xml验证。我使用McDowell's way验证了。

<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>

我正在使用下一个代码snipett访问我的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应用程序时,我在上面的print语句中得到NULL。我在单例类中查找上下文,称为邮件程序(在我的WEB-INF / classes文件夹中定义),但如果我在Struts操作类中查找上下文,我会遇到同样的问题。

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

我有另一个问题。如果我有javax.mail.Session所需的mailapi.jar,请在myapp / WEB-INF / lib文件夹中获取:

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 个答案:

答案 0 :(得分:6)

JNDI查找代码怪癖

我发现没有找到JNDI资源的多个问题。在Websphere上(我知道,你不使用它,但知道很好......)你会遇到问题

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

什么有效(在Websphere上)

Session session = (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类进行查找。 (见杰克的答案)

主题和调用环境第二部分

创建一个新的Struts Action并从那里调用你的JNDI查找代码,看看这是否有效,如果放置在struts附近和http请求的处理范围内。如果它在此处有效,请继续执行上述步骤。

web.xml的有效性

此外,您可能希望查看web.xml的架构定义,以确保正确定位resource-ref。 servlet规范2.4在jcp.org处可用,即使tomcat实现了2.5,也应足以检查。

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

Tomcat调试选项

许多context.xml条目都支持属性“debug”。虽然我认为低一位数值就足够了,但我习惯于在'Context'或其他元素中添加'debug =“99”'。您可能希望查看是否会产生一些有用的日志条目。

确保它不是类路径

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

关于您的类路径问题

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

编辑:

关于您的部分解决方案

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

tomcat的标准位置是在webapps META-INF / context.xml中,或者在$ CATALINA_HOME / conf / Catalina / localhost /中的xml文件(以您喜欢的名字命名,结尾.xml)中。后面的解决方案实际上是关于META-INF / context.xml的,因为这种方式配置独立于应用程序,并且在部署新应用程序时不会被覆盖。

此上下文通常包含其他属性,如docBase和path:

<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以部署新的webapp可能会导致tomcat删除xml配置文件。

因此 - 无论您遇到什么问题:尝试将您的上下文定义/应用程序置于$ CATALINA_HOME / conf / Catalina / localhost / app.xml中。我觉得这很简单,只有最后一点信息缺失才能看到真正的问题。

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

  

你推荐什么?

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

  

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

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


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

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

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

  

deployXML - 如果需要,设置为false   禁用解析context.xml   嵌入在应用程序中的文件   (位于/META-INF/context.xml)。   安全的环境应该是   将此设置为false以防止   与...交互的应用程序   容器的配置。该   管理员将负责   用于提供外部环境   配置文件,并将其放入   $ CATALINA_HOME / conf目录/ [引擎] / [主机名] /。   标志的值默认为true。

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

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

我确信还有其他人,这些只是我能够快速找到的。

答案 3 :(得分:0)

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

以防万一:额外 - 额外 - 确保您的上下文定义中没有拼写错误。将它与$ CATALINA_HOME / conf / context.xml

中的工作版本进行额外的比较

我们不希望“邮件/ Sessoin”发挥作用......