EclipseMavenプラグインを使用してJava EE 7プロジェクトを作成しています。アプリケーションを実行すると、SerlvetContextListenerを実装するクラスが呼び出されません。この問題の原因は何ですか?
@WebListener
public class ApplicationContextListener implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent sce)
{
Request request = new HttpRequest(sce);
new Thread (request).start();
HibernateUtil.getSessionFactory();
}
@Override
public void contextDestroyed(ServletContextEvent sce)
{
}
}
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<listener>com.kyrogaming.AppServletContextListener</listener>
<!-- Jersey Mapping -->
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>com.Sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.Sun.jersey.config.property.packages</param-name>
<param-value>com.kyrogaming.webservices</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
<!-- end Jersey Mapping -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
Web.xmlでは、<listener-class>
も指定する必要があります。
<listener>
<listener-class>
com.kyrogaming.AppServletContextListener
</listener-class>
</listener>
JNLとテッドゴダードの答えを要約すると:
ServletContextListener(またはServletContextAttributeListenerやServletRequestAttributeListenerなどの他のリスナー)をサーブレットコンテナによってロードするには、コンテナにそのことを通知する必要があります。 APIドキュメントで説明 のように、これを行うには3つの方法があります。
1)デプロイメント記述子(web.xml)で宣言します。
_<listener>
<listener-class>
com.kyrogaming.AppServletContextListener
</listener-class>
</listener>
_
2)またはクラスに _@WebListener
_ で注釈を付けます(以下の「注釈に関する注記」を参照)
3)またはaddListener() などのServletContextのメソッドを介して、プログラムで登録します。
注釈に関する注意
方法1)と3)は常に機能します。方法2)(注釈)が機能するには、クラスパス内のクラスをスキャンして注釈付きリスナークラスを見つけるようにサーブレットコンテナを構成する必要があります。
Webアプリ自体のクラス(_WEB-INF/classes
_の下)は常にスキャンされるため、注釈付きのクラスが常に検出されます。ただし、web.xmlに属性_WEB-INF/lib
_(属性のデフォルトはfalse
)が含まれている場合、ライブラリ(_metadata-complete="true"
_の下のJAR)はスキャンされません。 Javaサーブレット仕様バージョン3. 、第8章「アノテーションとプラグ可能性」を参照してください。
したがって、コンテナがJAR内の注釈付きクラスを検索できるようにするには、web.xmlが_metadata-complete="false"
_を設定するか、まったく設定しないようにします。
これを設定すると、アプリケーションの起動が遅れる可能性があることに注意してください。たとえば、 metadata-complete = "true"(Tomcat 7の起動が遅いことを解決した)を設定した後、注釈をどうするか? を参照してください。
残念ながら、それでも問題のServletContextListenerがロードされない理由は説明されていません。問題のweb.xmlは_metadata-complete
_ではないことに注意してください。つまり、デフォルトでfalse
になっているため、クラスパススキャンが有効になっています。おそらく他の問題があります。このチェックリストは、うまくいけばそれを見つけるのに役立ちます。
Web.xmlでmetadata-complete = "false"を使用すると、この問題が修正されました。
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="false">
記録のために、ServletContextListener
が呼び出されないというさらに別の考えられる(そしてかなり悪質な)原因を追加します。
これは、Java.lang.LinkageError
がある場合、つまり<scope>provided</scope>
をjavax.servlet-api
依存関係に追加するのを忘れた場合に発生する可能性があります。このような場合、リスナーインスタンスは作成されますが、静的部分のみが実行され、contextInitialized
メソッドとcontextDestroyed
メソッドは実行されません。
リスナーのインスタンス化中にリンケージエラーが発生しないため、サーブレットを呼び出したときにのみ検出されます。