jpg4.us

 

PebbleをApache経由で使う。 - るいもの戯れ言
PR: 転職    葬式    マンスリーマンション 神戸    北海道    環境    FX    不動産担保融資    桐ヶ谷斎場    海外旅行    専門学校   

PebbleをApache経由で使う。

8080は、メンテ用にローカルからしかアクセスできないポートとして残し、Apacheから、8009経由でTomcatにアクセスする。しかし、Apache経由でアクセスした場合に、Pebbleが出力する、baseタグが、なぜかhttp://192.168.0.250:8080のようになってしまい、ページ中のリンクが、8080経由にされてしまう。

HttpServletRequest.getServerPort()の結果は80だった。どこで、8080なんて値を仕入れているんだろう。

あった、BlogLookupFilterでやっている模様。

    String url = pebbleContext.getConfiguration().getUrl();
    if (pebbleContext != null && (url == null || url.length() == 0)) {
      String scheme = httpRequest.getScheme();
      url = scheme + "://" + httpRequest.getServerName() + ":" + httpRequest.getServerPort() + httpRequest.getContextPath();
      log.info("Setting Pebble URL to " + url);
      PebbleContext.getInstance().getConfiguration().setUrl(url);
    }

ん〜、そもそもスレッドセーフとか考えていないような... というか、これシングルトンだから、先に来たやつを覚えて、ずっと使い回しちゃうじゃん。

さて、どうするか... まずは以下の戦略を試してみる。

PebbleContextをスレッドローカルに持たせ、シングルトンはやめてリクエストごとにUrlを設定させる。

まずは、PebbleContextをちょっといじって、

    //  private static final PebbleContext instance = new PebbleContext();

  static final ThreadLocal<PebbleContext> instance = new ThreadLocal<PebbleContext>() {
      @Override protected PebbleContext initialValue() {
          return new PebbleContext();
      }
  };

  public static PebbleContext getInstance() {
//    return instance;
      return instance.get();
  }

BlogLookupFilterを修正。

    PebbleContext pebbleContext = PebbleContext.getInstance();
    AbstractBlog blog;

    String url = pebbleContext.getConfiguration().getUrl();
//    if (pebbleContext != null && (url == null || url.length() == 0)) {
      String scheme = httpRequest.getScheme();
      url = scheme + "://" + httpRequest.getServerName() + ":" + httpRequest.getServerPort() + httpRequest.getContextPath();
      log.info("Setting Pebble URL to " + url);
      PebbleContext.getInstance().getConfiguration().setUrl(url);
//    }

pebbleContextがnullになるわけないから、if文自体を削除。そして、ぬるぽ。

12:54:37,310 ERROR [[jsp]] サーブレット jsp のServlet.service()が例外を投げました java.lang.NullPointerException at net.sourceforge.pebble.web.filter.BlogLookupFilter.doFilter(BlogLookupFilter.java:91) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)

以下の行で発生している模様。

    String url = pebbleContext.getConfiguration().getUrl();

pebbleContextがnullになるわけないんだから、getConfiguration()がnullなんでしょう。これを、設定しているのは、、、PebbleContextListenerみたい。

    Configuration config = (Configuration)applicationContext.getBean("pebbleConfiguration");
    DAOFactory.setConfiguredFactory(config.getDaoFactory());
    PebbleContext ctx = PebbleContext.getInstance();
    ctx.setConfiguration(config);

これが呼ばれていないんかなぁ。あ、そうか、このConfigurationは全スレッドに見えないといけないのに、これじゃ、たまたま実行したスレッドにしか設定されないじゃん。とりあえず、ServletContextListenerとして、アプリケーション起動時に一度呼ばれるだけみたいなんで、PebbleContextを以下のように応急処置。

//  private Configuration configuration;
  static volatile Configuration configuration;
...
//  private String webApplicationRoot;
  static volatile String webApplicationRoot;
...
  public void setConfiguration(Configuration conf) {
//    this.configuration = configuration;
    configuration = conf;
  }
...
  public void setWebApplicationRoot(String root) {
//    this.webApplicationRoot = webApplicationRoot;
    webApplicationRoot = root;
  }

動いた!。ちゃんとポート80経由で行った場合も8080経由で行った場合もうまく行くようになった。そろそろ本番サーバも切り替えて大丈夫そうかな。



このサイトの掲載内容は私自身の見解であり、必ずしもIBMの立場、戦略、意見を代表するものではありません。
日本アイ・ビー・エム 花井 志生 Since 1997.6.8


jpg4.us