mail / Session Resource Factory не работает в приложении Struts - PullRequest
4 голосов
/ 30 января 2009

Я хочу использовать стандартную фабрику ресурсов, предоставляемую Tomcat 6.0, которая создает для меня экземпляр javax.mail.Sessions. Как описано в учебном руководстве по ресурсам JNDI .

Мой 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, прямо перед . 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>

Я использую следующий фрагмент кода доступа к моему объекту 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. Я позиционирую resource-ref как раз перед определениями сервлета. Кажется, что ресурс-ссылка игнорируется.

У меня есть другая проблема. Если у меня есть mailapi.jar, необходимый для javax.mail.Session, в папке myapp / WEB-INF / lib я получаю:

java.lang.NoClassDefFoundError: javax / mail / Authenticator

Если я положу его в $ CATALINA_HOME / найден lib.

Есть идеи? Я использую распорки и спящий режим. Может быть, это как-то связано с этим.

Debug

Я попытался отладить его, поместив атрибут debug в контекст

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

6 голосов
/ 01 февраля 2009

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 может зависеть от потока, ищущего ресурсы. Насколько я помню, потоки не очень хорошо определены в API сервлетов (или Java EE или связанных областях. Это может быть даже добровольно и явно не определено). Поэтому сервер не обязательно должен предоставлять ресурсы JNDI в потоках, которые вы создали сами (опять же, Websphere меня укусил, я не тестировал Tomcat6 в этом отношении, более ранние версии использовались для предоставления ресурсов JNDI всем потокам)

Вы написали, что ищете ресурсы JNDI из одного экземпляра. Если вы , в момент поиска ресурсов, изучите трассировку стека (либо в вашей IDE, сгенерировав исключение, либо связавшись с Thread.currentThread().getStacktrace()): есть ли Соединитель Tomcat в трассировке стека или один из методов собственного потока Thread () в корне трассировки стека ? Это ответит на вопрос, стоящий за вопросом Джека, если вы делаете поиск из класса Action. (см. ответ Джека)

Threads и call-environment часть вторая

Создайте новое действие Struts и вызовите оттуда свой код поиска JNDI, посмотрите, работает ли оно, если оно расположено как можно ближе к стойкам и в рамках обработки http-запроса. Если это работает здесь, продолжайте с шагами выше.

срок действия web.xml

Также, возможно, вы захотите взглянуть на определение схемы для web.xml, чтобы убедиться, что ваш resource-ref расположен правильно. Спецификация сервлета 2.4 доступна на jcp.org и должна быть достаточной для проверки, даже если tomcat реализует 2.5.

В конце концов, я считаю, что tomcat6 проверяет web.xml, так что вы, вероятно, уже нашли его в правильном положении. (Не могу вспомнить, так как мой редактор IDE жалуется, когда я ошибаюсь, мне нужно написать web.xml)

Параметры отладки Tomcat

Многие записи context.xml имеют атрибут debug. Хотя я считаю, что достаточно низких однозначных значений, я принял привычку добавлять 'debug = "99" к таким элементам, как "Context" или другим. Возможно, вы захотите узнать, приводит ли это к некоторым полезным записям в журнале.

Убедитесь, что это не путь к классу

Поскольку вы, похоже, коренным образом изменили среду, убедитесь, что у вас есть все необходимые библиотеки на борту - почтовый API состоит из нескольких jar-файлов. Загрузите новую копию и распакуйте все библиотеки в каталог $ CATALINA_HOME / lib. Вы можете убрать неиспользованный, когда он будет работать со всеми библиотеками там.

Относительно вашего вопроса о пути к классам :

Причина нахождения класса при помещении в $ CATALINA_HOME / lib заключается в том, что соединение выполняется сервером (помните - вы определили его в context.xml, который читается сервером для запуска приложения ), таким образом, jar должен быть на серверах classpath, а не только на приложениях (см. загрузчик классов tomcat HOWTO для получения дополнительной информации)

EDIT:

Относительно вашего частичного решения :

$ CATALINA_HOME / conf / context.xml содержит глобальные контекстные элементы «по умолчанию». Это не то место, где вы хотите, чтобы конфигурация вашего приложения была.

Стандартная позиция для tomcat находится либо в веб-приложении META-INF / context.xml, либо в файле xml (назван как вам угодно, заканчивающийся .xml) в $ CATALINA_HOME / conf / Catalina / localhost /. Более позднее решение на самом деле предпочтительнее в отношении 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 может быть относительно веб-приложения. Будьте осторожны в отношении условий гонки: Tomcat автоматически развернет приложения в $ CATALINA_HOME / webapps и может создать файл контекста. Кроме того, удаление веб-приложения для развертывания нового может привести к тому, что tomcat удалит файл конфигурации xml.

Для этого - какой бы ни была ваша проблема: попробуйте, если ваше определение контекста / приложение работает, когда помещено в $ CATALINA_HOME / conf / Catalina / localhost / app.xml. У меня такое ощущение, что это что-то очень простое, где не хватает только последней информации, чтобы увидеть реальную проблему.

1 голос
/ 03 февраля 2009

А что порекомендуете?

Определите его в JNDI, но за пределами вашего веб-приложения / WAR. В Tomcat вы можете сделать это, поместив его в файл $ {CATALINA_BASE} /conf/context.xml. Это позволяет определять конфигурацию внешнего ресурса (почта, база данных и т. Д.) За пределами вашего веб-приложения, избегая необходимости переупаковывать WAR-файл при изменении конфигурации базы данных или при переходе в другую среду с другой базой данных, например.

Я проверяю контекст в синглтон-классе под названием mailer.

Этот почтовый класс, в WEB-INF / classes или в JAR в WEB-INF / lib? Или это определено в другом месте в вашем classpath? Если последнее, вы можете рассмотреть возможность его переноса в ваше приложение.


Редактировать: Судя по вашим последним результатам, META-INF / context.xml вашего веб-приложения не действует. В Tomcat есть несколько сценариев, которые приведут к этому. Я не знаю их подробно, но вот некоторую информацию, которую мне удалось найти:

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

Если атрибут "deployXML" установлен в false в вашем элементе Host (я верю в server.xml).

deployXML - установите в false, если хотите отключить разбор context.xml файл, встроенный в приложение (находится по адресу /META-INF/context.xml). Безопасная среда должна установите это в ложь, чтобы предотвратить приложения от взаимодействия с конфигурация контейнера. Администратор будет нести ответственность для обеспечения внешнего контекста файл конфигурации, и поместите его в $ CATALINA_HOME / CONF / [enginename] / [имя хоста] /. Значение флага по умолчанию равно true.

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

Если у вас есть файл $ CATALINA_HOME / conf / [enginename] / [имя хоста] / [context-path] .xml.

Я уверен, что есть и другие, это те, которых я смог быстро найти.

1 голос
/ 01 февраля 2009

Полагаю, вы должны определить свой контекст в META-INF / context.xml, а не в META-INF / web.xml (хотя это может быть просто опечатка в исходном сообщении).

Когда вы сказали, что перенесли свой код в приложение Struts, можете ли вы быть более конкретным? Ты имеешь в виду, что сейчас ты делаешь свой контекстный поиск в классе Action?

Кроме того, вы, возможно, уже знаете это, но хотя определение вашего контекста (записей JNDI и т. Д.) В ваших веб-приложениях, META-INF / context.xml приемлемо в среде разработчика, я настоятельно не рекомендую использовать его в любой форме общих сред и, конечно, не в производственной среде.

0 голосов
/ 08 февраля 2009

Поскольку это совершенно другой сценарий по сравнению с вышеупомянутым решением, я решил добавить другой ответ, а не редактировать предыдущий:

На всякий случай: сделайте extra-extra- extra - убедитесь, что в вашем определении контекста нет опечаток. Тщательно сравните его с рабочей версией в $ CATALINA_HOME / conf / context.xml

Мы бы не хотели, чтобы "почта / Сессойн" имела значение ...

...