GradleでServlet APIを除外設定する
Javaの小ネタが続く渡辺です。
つまり、そんな案件が続いているってことになります(笑)
Servlet API
Servlet APIはJava EEの基盤となるAPIですが、歴史は非常に古く、Version1が公開されたのは1997年です。 もうすぐ20年になる非常に古くからある仕様であり、現在はJavaEE 7に組み込まれている 3.1.0 が最新バージョンとなっています。
通常、Servlet APIはTomcat や Galssfishといったアプリケーションサーバ(Java EEアプリケーションサーバでなくてもOK)でバンドルされています。 したがって、WARファイルを作成する場合にはServlet APIのJARファイルを含めません。 これは、含めてしまうと、バージョンの異なるServlet APIが混在する可能性があり、予期せぬ挙動を引き起こす可能性があるからです。
Gradleでライブラリの依存関係の解決
Gradleでは、ライブラリ(JAR)の依存関係を解決します。
あるライブラリが遡ってServlet APIを利用しているならば、自動的にServlet APIを依存ライブラリとして認識します。 通常はこの動きは妥当なのですが、Servlet APIのように、成果物(WAR)に含めたくないライブラリ(JAR)も存在します。 この時、ライブラリの設定ファイルで適切な設定が行われていれば、特別な設定をしなくとも、Servlet APIが成果物(WAR)に含まれません。 しかし、往々にして何らかのライブラリが依存関係の処理が甘い結果、Servlet APIがWARに紛れ込んでしまい、予期せぬ挙動をするものです。
明示的にexclude設定を行う
したがって、明示的にServlet APIを依存関係の自動適用から除外します。
次の設定は、build.gradleの一部です。
configurations { all*.exclude group: 'javax.servlet-api', module: 'servlet-api' }
これで解決・・・するならば、こんなエントリーは不要ですね(´・ω・`)
このように設定したのに何故かServlet APIがWARに含まれました。 しかも3.1.0を指定しているのに、2系が・・・。
Servlet APIのGroupID
答えは、ライブラリのGroupIDにありました。
実は、Servlet APIのGroupIDは、2.X系まではjavax.servletであり、3.0以降はjavax.servlet-apiに変更されています。 Maven リポジトリでは、GroupID, ArtifactID, Versionでライブラリを一意に識別します。 javax.servlet-api:servlet-api:3.Xは、javax.servlet:servlet-api:2.Xの上位バージョンとして認識されません(怒)。 おまけに除外設定からすり抜けてきます(トホホ)
もれなく、Servlet APIを除外するには次のように記述しなければなりません。
configurations { // javax.servlet-api:servlet-api:3.X // javax.servlet:servlet-api:2.X all*.exclude group: 'javax.servlet-api', module: 'servlet-api' all*.exclude group: 'javax.servlet', module: 'servlet-api' }
または、module(artifactID)のみを指定し、次のようにします。
configurations { // javax.servlet-api:servlet-api:3.X // javax.servlet:servlet-api:2.X all*.exclude module: 'servlet-api' }
どうして、変更したし・・・(´・ω・`)