JBoss ASで、Infinispanを使うための下準備ってことで。まあ、すぐには手をつけないかもしれませんが。
sbtのMANIFEST設定の勉強にも、ちょいとなりましたね。
コミュニティ版のJBoss ASは、7.1.1で止まっているので、サブシステムとして含まれているInfinispanが5.1.2.FINALとなっていて、わりと古い状態です。
なお、デプロイするアプリケーションから組み込み済みのInfinispanを参照するためには、META-INF/MANIFESTに
Manifest-Version: 1.0 Class-Path: org.infinispan services
と書くか、以下のようなXMLファイルをWARに含めます。
src/main/webapp/WEB-INF/jboss-deployment-structure.xml
<?xml version="1.0" encoding="UTF-8"?> <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1"> <deployment> <dependencies> <module name="org.infinispan" /> </dependencies> </deployment> </jboss-deployment-structure>
これで、JBoss ASにモジュールとして組み込まれているInfinispanを参照することができます。
sbtで設定すると、依存関係はこんな感じでOKとなります。
"org.infinispan" % "infinispan-core" % "5.1.2.FINAL" % "provided", "net.jcip" % "jcip-annotations" % "1.0" % "provided"
組み込み済みなので、「provided」ですね。
「jcip-annotations」が入っているのは、ScalaとInfinsipanの組み合わせだからです…。
Javaで使う場合は、不要です。
MANIFESTを定義する方法は、こんな感じでした。
*xsbt-war-pluginを適用しています
packageOptions in (Compile, packageWar) += Package.ManifestAttributes(new java.util.jar.Attributes.Name("Dependencies") -> "org.infinispan services")
そんな感じの設定を含んだアプリケーションをJBoss ASにデプロイして、DefaultCacheManagerを初期化した時のInfinispanの起動ログは、こんな感じ。
00:09:23,433 INFO [org.infinispan.factories.GlobalComponentRegistry] (http--127.0.0.1-8080-1) ISPN000128: Infinispan version: Infinispan 'Brahma' 5.1.2.FINAL
が、これだとちょっと古いので、Infinispanの差し替えを行います。
Infinispanのオフィシャルサイトから、「AS7 Modules」と記載されたディストリビューションをダウンロードします。
Infinispanダウンロードページ
http://infinispan.org/download/
ここで、JBoss AS 7のインストールディレクトリを「$JBOSS_HOME」とすると、以下のディレクトリに移動して
$ $JBOSS_HOME/modules
ここにダウンロードしたZIPファイルをコピーして展開します。ちょっと乱暴ですが。
$ unzip infinispan-as-modules-5.3.0.Final.zip Archive: infinispan-as-modules-5.3.0.Final.zip creating: org/jgroups/3.2/ creating: org/infinispan/tree/ creating: org/infinispan/tree/5.3/ creating: org/infinispan/cachestore/jdbc/5.3/ creating: org/infinispan/cachestore/remote/5.3/ creating: org/infinispan/5.3/ extracting: org/jgroups/3.2/jgroups-3.3.1.Final.jar inflating: org/jgroups/3.2/module.xml inflating: org/infinispan/tree/5.3/module.xml extracting: org/infinispan/tree/5.3/infinispan-tree.jar inflating: org/infinispan/cachestore/jdbc/5.3/module.xml extracting: org/infinispan/cachestore/jdbc/5.3/infinispan-cachestore-jdbc.jar inflating: org/infinispan/cachestore/remote/5.3/module.xml extracting: org/infinispan/cachestore/remote/5.3/infinispan-cachestore-remote.jar inflating: org/infinispan/5.3/module.xml extracting: org/infinispan/5.3/infinispan-core.jar
infinispan-coreは、JBoss LoggingとJBoss Marshallingにも依存していて、なおかつJBoss AS 7に含まれているモジュールは5.3.0の依存関係から見るとほんの少し古いのですが、まあいいかなぁと…。
ZIPファイルは、要らないので削除。
$ rm infinispan-as-modules-5.3.0.Final.zip
もちろん、別の場所で展開してmodulesディレクトリに入れる、でもいいと思います。
あ、JBoss AS 7は、再起動した方がよいかと。
さて、展開したInfinispan 5.3.0.Finalに含まれるmodule.xmlは、こんな感じです。
*コメントは端折っています
org/infinispan/5.3/module.xml
<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.1" name="org.infinispan" slot="5.3"> <resources> <resource-root path="infinispan-core.jar"/> <!-- Insert resources here --> </resources> <dependencies> <module name="javax.api"/> <module name="javax.transaction.api"/> <module name="javax.xml.bind.api"/> <module name="net.jcip"/> <module name="org.apache.xerces" services="import"/> <module name="org.jboss.jandex"/> <module name="org.jboss.logging"/> <module name="org.jboss.marshalling"/> <module name="org.jboss.marshalling.river" services="import"/> <module name="org.jboss.staxmapper" /> <module name="org.jgroups" slot="3.2"/> <module name="sun.jdk"/> </dependencies> </module>
で、これを先ほどの依存関係やMANIFESTとかに反映します。
依存関係の定義は、こんな感じ。
"org.infinispan" % "infinispan-core" % "5.3.0.Final" % "provided", "net.jcip" % "jcip-annotations" % "1.0" % "provided"
MANIFESTは、こうします。
packageOptions in (Compile, packageWar) += Package.ManifestAttributes(new java.util.jar.Attributes.Name("Dependencies") -> "org.infinispan:5.3 services")
生成されたMANIFESTファイル。
Manifest-Version: 1.0 Dependencies: org.infinispan:5.3 services
もしくは、jboss-deployment-structure.xmlにこんな感じで定義します。
src/main/webapp/WEB-INF/jboss-deployment-structure.xml
<?xml version="1.0" encoding="UTF-8"?> <jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.1"> <deployment> <dependencies> <module name="org.infinispan" slot="5.3" /> </dependencies> </deployment> </jboss-deployment-structure>
slot付きです。
これで、デプロイしたアプリケーションが使うInfinispanの起動ログに、「5.3.0.Final」と出るようになりました。
00:33:54,772 INFO [org.infinispan.factories.GlobalComponentRegistry] (http--127.0.0.1-8080-1) ISPN000128: Infinispan version: Infinispan 'Tactical Nuclear Penguin' 5.3.0.Final
なお、jboss-deployment-structure.xml以外のsbtの設定や動作確認に使ったファイルやコードはこちらになります。
build.sbt
name := "infinispan-in-jboss" version := "0.0.1-SNAPSHOT" scalaVersion := "2.10.3" organization := "littlewings" seq(webSettings: _*) artifactName := { (version: ScalaVersion, module: ModuleID, artifact: Artifact) => artifact.name + "." + artifact.extension } resolvers += "Public JBoss Group" at "http://repository.jboss.org/nexus/content/groups/public-jboss" libraryDependencies ++= Seq( "org.eclipse.jetty" % "jetty-webapp" % "9.0.6.v20130930" % "container", "javax" % "javaee-web-api" % "6.0" % "provided", "org.infinispan" % "infinispan-core" % "5.3.0.Final" % "provided", "net.jcip" % "jcip-annotations" % "1.0" % "provided" ) packageOptions in (Compile, packageWar) += Package.ManifestAttributes(new java.util.jar.Attributes.Name("Dependencies") -> "org.infinispan:5.3 services")
project/plugins.sbt
addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "0.4.2")
src/main/scala/example/SampleServlet.scala
package example import java.io.IOException import javax.servlet.ServletException import javax.servlet.annotation.WebServlet import javax.servlet.http.{HttpServlet, HttpServletRequest, HttpServletResponse} import org.infinispan.Cache import org.infinispan.manager.{DefaultCacheManager, EmbeddedCacheManager} @WebServlet(Array("/*")) class SampleServlet extends HttpServlet { lazy val manager: EmbeddedCacheManager = new DefaultCacheManager lazy val cache: Cache[String, Int] = manager.getCache() @throws(classOf[IOException]) @throws(classOf[ServletException]) override protected def doGet(req: HttpServletRequest, res: HttpServletResponse): Unit = { if (cache.containsKey("counter")) { cache.put("counter", cache.get("counter") + 1) } else { cache.put("counter", 1) } res.getWriter.print(<html><h1>Counter = {cache.get("counter")}</h1></html>.toString) } override def destroy(): Unit = { try { cache.stop() } finally { manager.stop() } } }