我想使用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文件中时,它可以正常工作。
答案 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”发挥作用......