K4750.NET

Jerseyで@Pathとurl-patternの設定でハマった

拡張子の付いたファイルのURL(例えば「http://example.com/api.json」)へのレスポンスをJerseyで受け付けようとして、設定でハマったのでメモしておく。


1.リクエストURLとweb.xmlのurl-patternと@Pathの対応について

リクエストが受け付けられる場合はOK、404 Not FoundとなるものはNGとする。

リクエストURL                         url-pattern  @Path                   OK/NG
------------------------------------+------------+-----------------------+-----
http://example.com/api/lookup        /api/*       @Path("/lookup")        OK
http://example.com/api/lookup.json   /api/*       @Path("/lookup.json")   OK
http://example.com/lookup.json       *.json       @Path("/lookup.json")   NG
http://example.com/lookup.json       *.json       @Path("/")              OK
http://example.com/lookup.json/hoge  *.json       @Path("/hoge")          NG

url-patternが「/api/*」といった前方一致の記述方法の場合は納得できるのだが、「*.json」といった拡張子の記述方法の場合は妙な対応付けになってしまう(特に3行目がNGというのが、直観に反していていただけない)。ということで、Jerseyへマッピングする際は、url-patternに拡張子マッチングの記述方法は使用しないことにする。


2.Jerseyのデバッグについて

web.xmlを以下のようにすると、レスポンスヘッダーに「X-Jersey-Tracing-XXX」の形式でトレースログが出力されるようになる。上記のようにマッピング回りで悩んだ場合は設定して動作検証を行う。

<servlet>
  <servlet-name>jersey-api</servlet-name>
  <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
  <init-param>
    <param-name>jersey.config.server.provider.packages</param-name>
    <param-value>net.k4750.app.nendoroid.api</param-value>
  </init-param> 

  <init-param>
    <param-name>jersey.config.server.tracing.type</param-name>
    <param-value>ALL</param-value>
  </init-param>
  <init-param>
    <param-name>jersey.config.server.tracing.threshold</param-name>
    <param-value>VERBOSE</param-value>
  </init-param>

  <load-on-startup>1</load-on-startup>
</servlet>

3.その他のURL変換機構

蛇足。

先日書いた「ルートURLへのリクエストをJerseyで受け付ける」では、「http://example.com/」へのアクセスがwelcome-fileの設定によりhttp://example.com/index.doへのリクエストへ変換され、url-pattern「*.do」、@Path「@Path(“/”)」に一致する流れを書いた。このように、URLの変換は様々な箇所で行われている。

例えば、今扱っているサイトで使っている、Apache2とTomcat7との連携用モジュールmod_proxy_ajpもURLを変換する設定が記述できるし、Apache2のURL書き換えモジュールmod_rewriteでも変換が行える。さらに言えば、企業のWEBサイトなどではhttpサーバの前段に配置されるBIG-IP等負荷分散装置にてURLの書き換えが行われる場合もある。他にもまだあるかもしれないが、、とにかくブラウザで指定されたURLが実際のプログラムへマッピングされるまでの間には何回もURL変換がされているということだ。。

ルートURLへのリクエストをJerseyで受け付ける

アプリケーションのルートURL(例えば「http://app.k4750.net/nendoroid/」)へのリクエストをJAX-RSの実装であるJerseyで受け付けようとして手間取ったのでメモを残しておく。


1.使用しているアプリケーションコンテナ、ライブラリ等

  • Tomcat 7.0.52
  • Jersey 2.12
  • Thymeleaf 2.1.3 (今回の話題には無関係)

2.web.xml

以下のweb.xmlを持つWebアプリケーションを「http://app.k4750.net/nendoroid/」へデプロイする。

  <servlet>
    <servlet-name>jersey</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>jersey.config.server.provider.packages</param-name>
      <param-value>net.k4750.app.nendoroid</param-value>
    </init-param> 
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>jersey</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.do</welcome-file>
  </welcome-file-list>

welcome-fileの設定により「http://app.k4750.net/nendoroid/」へのアクセスは「http://app.k4750.net/nendoroid/index.do」へのアクセスとみなされ、url-patternの「*.do」に一致し、JerseyのServletContainerが実行される。因みに、url-patternを「/*」にしてしまうという乱暴なやり方もできなくはないが、Webアプリケーションに含まれる画像(*.jpg等)やJavaScript(*.js)等へのアクセスもすべてServletContainer呼び出しになってしまうため、現実的ではない。


3.アプリケーション

リクエストを受け付けるアプリケーションは以下のとおり。

package net.k4750.app.nendoroid;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

@Path("/")
public class Index {
  @GET
  @Produces("text/html")
  public String exec() {
    return "..."; // HTMLをStringで返す。
  }
}

@PathにリクエストがあったURLの相対パスを記述するのだが、直観に反して(?)@Path("/index.do")ではない。web.xmlのwelcome-fileの設定が適用される前のパス@Path("/")を記述しなければならない。Webアプリケーションの仕様や挙動を熟知していれば当然のことなのかもしれないが、、なんともしっくり来ない動作だと感じる。もっとスマートなやり方はないのだろうかと思う。

ねんどろいどの部屋

nndrid

ねんどろいどの部屋」というサイトを作ってみた。Amazonの「フィギュア・コレクタードール」の検索結果を表示するだけのサイトだが、ねんどろいど画像が“みっしり”表示されるのが特徴。ゼヒ一度ご覧あれ。


1.作った経緯

  • ねんどろいどフィギュアをウィンドウ一面にぎっしり・みっしり並べて俯瞰(フカン)してみたい。
  • Javaの今どき(?)のライブラリで色々遊んでみたかった(Jersey、Thymelief、Bootstrap、jQuery、etc.)。・・・書いてみて思うに、あまり今どきではないな!
  • JavaでAmazonのProduct Advertising APIを使ってみたかった。

2.妥協色々

まだまだ雑な作りで改良の余地は色々ある。

  • Chromeなら100%みっしりが実現できるのだが、FirefoxとIEでは、画像サイズ調整がうまくいかず、各行の横幅が一定しない。回避策として左右に余白を数ドット入れたが、、美しくない!悔しい!なんとかしたい!
  • 静的なサイトなので、見ていて飽きる。少し動きのある要素がほしい(表示内容は1日程度で書き換わるようにはなっている)。
  • 一部、画像の拡大による劣化が見られる。劣化は極小化したい。
  • 画像へのマウスオーバー時のアクションを色々追加したい。商品情報をもっと活用したい。
  • 当初は「可変グリッドレイアウトといえばMasonry」と思い実装したが上手く機能させられず。独自に実装してみたものの、コードが見れたものではない。
  • Bootstrapが使えてない。ヘッダー&フッターに活用する予定。

3.試した環境

  • Windows8.1(64bit):Google Chrome 37、Firefox 32、Internet Explorer 11
  • Android4.4.4:Google Chrome 37