事前準備
CPUがハードウェア仮想化をサポートしているか検査。 以下のコマンドを実行した結果、1以上が表示されればOK。
$ egrep -c '(vmx|svm)' /proc/cpuinfo
KVM
$ sudo apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils
virt-manager
$ sudo apt-get install virt-manager
CPUがハードウェア仮想化をサポートしているか検査。 以下のコマンドを実行した結果、1以上が表示されればOK。
$ egrep -c '(vmx|svm)' /proc/cpuinfo
$ sudo apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils
$ sudo apt-get install virt-manager
ほとんどのJava EEのアプリケーションサーバは、Javaで実装した独自のWebサーバを持っている。 通常はそのWebサーバを利用すればよいのだが、運用の都合などにより、時々前段にApacheを配置することがある。 その時のために、mod_jkを利用してAJPでApacheと各種アプリケーションサーバを連携させる設定方法をメモしておく。
ただ、前段にApacheを配置する場合でも、通常はmod_proxy_httpを利用してHTTPで繋げればよいのだが。。。
OSはUbuntu 16.04 LTSを利用。
$ uname -srvm
Linux 4.4.0-47-generic #68-Ubuntu SMP Wed Oct 26 19:39:52 UTC 2016 x86_64
Javaは導入済みであることを前提とする。
ここでは、お手軽なのでapt-getでインストール。
$ sudo apt-get install apache2 libapache2-mod-jk
次にmod_jkの設定を行うために、jk.confを編集。 念のためバックアップをとった後に編集する。
$ cd /etc/apache2/mods-available
$ sudo cp jk.conf jk.conf.org
$ sudo vi jk.conf
デフォルトのjk.confではまともに動作しないので、余分な項目を削って、以下の内容にしておく。
<IfModule jk_module>
JkWorkersFile /etc/libapache2-mod-jk/workers.properties
JkLogFile /var/log/apache2/mod_jk.log
JkLogLevel info
</IfModule>
/etc/apache2/mods-enabledにシンボリックリンクを作成してmod_jkを有効化。
$ cd /etc/apache2/mods-enabled
$ sudo ln -s ../mods-available/jk.load jk.load
$ sudo ln -s ../mods-available/jk.conf jk.conf
現在有効なサイト(デフォルトでは/etc/apache2/sites-enabled/000-default.conf)に、AJPの転送元と転送先のマッピング(JkMount)を追加。
<VirtualHost *:80>
# (略)
JkMount /* ajp13_worker
</VirtualHost>
最後に、Apacheを再起動。
$ sudo systemctl restart apache2
デフォルトでAJPのポート(8009)がオープンされているので、特段の設定は不要でTomcatを起動するだけ。
$ cd /path/to/tomcat
$ bin/catalina.sh start
参考: Apache Tomcat 8 Configuration Reference - The AJP Connector
GlassFish 4のディレクトリに移動後、管理コマンドを利用してドメインの起動とAJPリスナを作成。
$ cd /path/to/glassfish4
$ bin/asadmin start-domain domain1
$ bin/asadmin create-network-listener --protocol http-listener-1 --listenerport 8009 --jkenabled true jk-connector
参考: GlassFish 4.0 Administration Guide
WildFly 10のディレクトリに移動後、WildFlyをバックグラウンドで起動し、そして管理コマンドを利用してAJPリスナを作成。
$ cd /path/to/wildfly10
$ bin/standalone.sh &
$ bin/jboss-cli.sh --connect
[standalone@localhost:9990 /] /subsystem=undertow/server=default-server/ajp-listener=myListener:add(socket-binding=ajp, scheme=http, enabled=true)
参考: WildFly Admin Guide - AJP listeners
Jetty 9はAJPには未対応。 Jetty 8まではAJPに対応していたらしい。
参考: Jetty - Howto - Configure AJP13
http://localhostとhttp://localhost:8080にアクセスして、それぞれ同じ画面(各アプリケーションサーバのトップ画面)が表示されればOK。 ブラウザのキャッシュに引っかからないように、強制リフレッシュ(Google ChromeだとCTRL + F5)したほうがよい。
Vagrant + libvirtでprivate_networkの設定を行うと、ゲスト側のNICが増えるのが気になったが、そういうものらしい。
That's not how private_network works. It will always create an extra interface. Vagrant needs the first interface that comes up to sit on the management_network so that it can connect to it and manage the VM.
Vagrantの設計思想とのこと。
No, because it is entirely against the design philosophy. The management network is there to allow Vagrant access to the VM and by not using DHCP we cannot know the IP address of the booted VM because we cannot alther the box VM network configuration until after it booted.
https://github.com/vagrant-libvirt/vagrant-libvirt/issues/613
Ubuntu 16.04 LTS
$ uname -srvm
Linux 4.4.0-45-generic #66-Ubuntu SMP Wed Oct 19 14:12:37 UTC 2016 x86_64
$ dpkg -l | grep libvirt0
ii libvirt0:amd64 1.3.1-1ubuntu amd64 library for interfacing with different
ネットワークの設定の編集コマンドを実行。
$ virsh net-edit default
以下のようなXMLがエディタでオープンされるので、それを編集。
<network> <name>default</name> <uuid>d5e58ece-d152-4a87-a768-4339b82940d5</uuid> <forward mode='nat'/> <bridge name='virbr0' stp='on' delay='0'/> <mac address='52:54:00:3b:67:93'/> <ip address='192.168.122.1' netmask='255.255.255.0'> <dhcp> <range start='192.168.122.2' end='192.168.122.254'/> </dhcp> </ip> </network>
DHCPのIPアドレスの範囲を変更したいので、<range>を以下のように修正。
<range start='192.168.122.128' end='192.168.122.254'/>
編集完了後、ネットワークの再起動。
$ virsh net-destroy default ネットワーク default は強制停止されました $ virsh net-start default ネットワーク default が起動されました
ネットワークの状態の確認。
$ virsh net-list 名前 状態 自動起動 永続 ---------------------------------------------------------- default 動作中 はい (yes) はい (yes)
<range>の変更が反映されているかの確認。
$ virsh net-dumpxml default <network connections='2'> <name>default</name> <uuid>d5e58ece-d152-4a87-a768-4339b82940d5</uuid> <forward mode='nat'> <nat> <port start='1024' end='65535'/> </nat> </forward> <bridge name='virbr0' stp='on' delay='0'/> <mac address='52:54:00:3b:67:93'/> <ip address='192.168.122.1' netmask='255.255.255.0'> <dhcp> <range start='192.168.122.128' end='192.168.122.254'/> ← 反映されている </dhcp> </ip> </network>
Ubuntuの場合、/etc/libvirt/qemu/networks/default.xmlにネットワークdefaultの設定があるが、コメント欄を読むと「直接編集するな、virsh使え」と書いてある。
<!-- WARNING: THIS IS AN AUTO-GENERATED FILE. CHANGES TO IT ARE LIKELY TO BE OVERWRITTEN AND LOST. Changes to this xml configuration should be made using: virsh net-edit default or other application using the libvirt API. --> <network> <name>default</name> <uuid>d5e58ece-d152-4a87-a768-4339b82940d5</uuid> <forward mode='nat'/> <bridge name='virbr0' stp='on' delay='0'/> <mac address='52:54:00:3b:67:93'/> <ip address='192.168.122.1' netmask='255.255.255.0'> <dhcp> <range start='192.168.122.2' end='192.168.122.254'/> </dhcp> </ip> </network>
CDIを利用したJAX-RS 2.0のアプリを作成し、Tomcat 8で実行するサンプル。 web.xmlレスの情報が少ないので、まとめておく。 ビルドにはJDK 8とMaven 3を利用。 また、JAX-RS 2.0の実装としてJerseyを、CDIの実装としてWeldを利用。 実行にはServlet 3.0に対応したTomcat 7以降(ここで試したのはTomcat 8)が必要。
. |-- pom.xml `-- src `-- main |-- java | `-- redj | `-- hello | `-- cdi | `-- jersey | |-- ApplicationConfig.java | |-- Greeting.java | `-- GreetingResource.java `-- resources `-- META-INF `-- beans.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>redj</groupId> <artifactId>hello-cdi-jersey</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <failOnMissingWebXml>false</failOnMissingWebXml> </properties> <dependencies> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> <version>2.22.1</version> </dependency> <dependency> <groupId>org.glassfish.jersey.ext.cdi</groupId> <artifactId>jersey-cdi1x</artifactId> <version>2.22.1</version> </dependency> <dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet-core</artifactId> <version>2.3.2.Final</version> </dependency> </dependencies> </project>
weld-servlet-coreには、WebコンテナでCDIを実現するServletが含まれている。 jersey-cdi1xは、Jersey内のCDIの実装をHK2からCDIに切り替える。
package redj.hello.cdi.jersey; import javax.enterprise.context.RequestScoped; @RequestScoped public class Greeting { public String sayHello(String name) { return "hello," + name + "!"; } }
package redj.hello.cdi.jersey; import javax.inject.Inject; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @Path("greeting/{name}") public class GreetingResource { @Inject private Greeting greeting; @GET @Produces("text/plain") public String sayHello(@PathParam("name") String name) { return greeting.sayHello(name); } }
package redj.hello.cdi.jersey; import java.util.HashSet; import java.util.Set; import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; @ApplicationPath("hello-cdi-jersey") public class ApplicationConfig extends Application { @Override public Set<Class<?>> getClasses() { Set<Class<?>> classes = new HashSet<>(); classes.add(GreetingResource.class); return classes; } }
<?xml version="1.0" encoding="UTF-8"?> <beans/>
weld-servlet-coreでCDIを有効化している場合、Managed Beanを全てアノテーションで定義していたとしても空のbeans.xmlが必要になる。
https://docs.jboss.org/weld/reference/latest/en-US/html/environments.html
In general, an implicit bean archive does not have to contain a beans.xml descriptor. However, such a bean archive is not supported by Weld Servlet, i.e. it’s excluded from discovery.
$ mvn clean install
$ cp target/hello-cdi-jersey-1.0-SNAPSHOT.war $CATALINA_HOME/webapps/
$ curl http://localhost:8080/hello-cdi-jersey-1.0-SNAPSHOT/hello-cdi-jersey/greeting/world hello,world!
JAX-RS 2.0のアプリを作成し、Tomcat 8で実行するサンプル。 web.xmlレスの情報が少ないので、まとめておく。 ビルドにはJDK 8とMaven 3を利用。 また、JAX-RS 2.0の実装としてJerseyを利用。 実行にはServlet 3.0に対応したTomcat 7以降(ここで試したのはTomcat 8)が必要。
. |-- pom.xml `-- src `-- main `-- java `-- redj `-- hello `-- jersey |-- ApplicationConfig.java `-- GreetingResource.java
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>redj</groupId> <artifactId>hello-jersey</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <failOnMissingWebXml>false</failOnMissingWebXml> </properties> <dependencies> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> <version>2.22.1</version> </dependency> </dependencies> </project>
package redj.hello.jersey; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @Path("greeting/{name}") public class GreetingResource { @GET @Produces("text/plain") public String sayHello(@PathParam("name") String name) { return "hello," + name + "!"; } }
package redj.hello.jersey; import java.util.HashSet; import java.util.Set; import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; @ApplicationPath("hello-jersey") public class ApplicationConfig extends Application { @Override public Set<Class<?>> getClasses() { Set<Class<?>> classes = new HashSet<>(); classes.add(GreetingResource.class); return classes; } }
$ mvn clean install
$ cp target/hello-jersey-1.0-SNAPSHOT.war $CATALINA_HOME/webapps/
$ curl http://localhost:8080/hello-jersey-1.0-SNAPSHOT/hello-jersey/greeting/world hello,world!