Tomcat をバージョン 7.0.34 からバージョン 8.0.33 にアップグレードしましたが、それ以来、Web アプリケーション コンテキストと Junit コンテキストを共有する際の問題に直面しています。
Web アプリケーションに関する統計データを収集するシングルトン クラスを持つ Web アプリケーションがあります。組み込みの tomcat で Web アプリケーションを実行する Junit もあります。Junit は Web アプリケーションにクエリを実行し、統計データをチェックします。
簡単な例を作成しようとしています:
シングルトン:
public class Counter {
private static Counter instance;
private AtomicLong counter;
private Counter(){}
public static Counter getInstance(){
if(instance == null){
synchronized (Counter.class) {
if(instance == null){
instance = new Counter();
}
}
}
return instance;
}
public long incrementAndGet(){
return counter.incrementAndGet();
}
public long getValue(){
return counter.get();
}
}
サーブレット:
@WebServlet(name="servlet",loadOnStartup=1, urlPatterns="/servletTest")
public class Servlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("Hi, you are the #" + Counter.getInstance().incrementAndGet() + " visitor");
}
}
コンテキストリスナー:
public class MyContextListener implements ServletContextListener{
@Override
public void contextDestroyed(ServletContextEvent arg0) {}
@Override
public void contextInitialized(ServletContextEvent arg0) {
Counter.getInstance().incrementAndGet();
}
}
テストユニット:
public void mainTest() throws ServletException, LifecycleException{
Tomcat tomcat = new Tomcat();
tomcat.setPort(50000);
StandardContext ctx = (StandardContext) tomcat.addWebapp("/fe", System.getProperty("FEBaseDir")); //The FEBaseDir property is supposed to be taken from Maven build using 'test' profile
tomcat.start();
Counter.getInstance().getValue();
}
Tomcat 7 を使用したときは、すべて正常に動作しました。しかし、TomcatをTomcat 8.0.33にアップグレードして以来、機能していません。静的データを持つシングルトン クラスは 2 回読み込まれます。最初に tomcat によって、次に Junit 自体によって。
tomcat にクラスローダーを渡そうとしましたが、うまくいきません。
public void mainTest() throws ServletException, LifecycleException{
Tomcat tomcat = new Tomcat();
tomcat.setPort(50000);
StandardContext ctx = (StandardContext) tomcat.addWebapp("/fe", System.getProperty("FEBaseDir")); //The FEBaseDir property is supposed to be taken from Maven build using 'test' profile
ctx.setCrossContext(true);
ctx.setLoader((Loader) new WebappLoader(Thread.currentThread().getContextClassLoader()));
ctx.setParentClassLoader(Thread.currentThread().getContextClassLoader());
tomcat.getEngine().setParentClassLoader(Thread.currentThread().getContextClassLoader());
tomcat.getHost().setParentClassLoader(Thread.currentThread().getContextClassLoader());
tomcat.getService().setParentClassLoader(Thread.currentThread().getContextClassLoader());
tomcat.getServer().setParentClassLoader(Thread.currentThread().getContextClassLoader());
tomcat.start();
Counter.getInstance().getValue();
}
私は何を間違っていますか?