[Database] ODPI-C 2.0.0-beta.4 released: More & Better-er

原文はこちら。
https://blogs.oracle.com/opal/odpi-c-200-beta4-released

ODPI-C 2.0.0-beta.4がリリースされました。GitHubからご利用いただけます。
ODPI-C version 2.0.0-beta.4
https://github.com/oracle/odpi
ODPI-CはOracle Call Interface (OCI) の抽象化レイヤーです。
Oracle Call Interface OCI
http://www.oracle.com/technetwork/database/features/oci/index-090945.html
このリリースでは、ユーザーからのフィードバックに基づき、継続的なテストの結果として段階的な改善が行われています。ベストプラクティスの数字の取り扱いや、DB接続を使わずにODPI-Cの可変構造を使用する方法について議論がありました。その結果、少々調整が必要になりました。すべての変更を知りたい方は、リリースノートを参照してください。
Release notes - Version 2.0.0-beta.4 (May 24, 2017)
https://oracle.github.io/odpi/doc/releasenotes.html#version-2-0-0-beta-4-may-24-2017
このリリースのハイライトは次のとおりです。
  • LOB、BINARY_FLOAT、BINARY_DOUBLE、NCHARおよびNVARCHAR2型の値を含むコレクション内のオブジェクトまたは要素値の属性の取得/設定がサポートされました。
  • ディスクI/Oを回避するために一時LOBキャッシングを有効にしました。
  • 列のメタデータが値が64ビット整数に収まることを示す場合、デフォルトのネイティブ・タイプをDPI_ORACLE_TYPE_INT64に変更しました。
  • 関数dpiStmt_defineValue()が追加されました。この関数は、アプリケーションが変数を作成せずにフェッチに使用するデータ型を指定することができます。
さらに、コンパイル中に新しいマクロDPI_DEBUG_LEVELを有効にして、ロギングおよびトレース情報を表示することができます。個人的には、この初期ベータ段階でDPI_DEBUG_LEVEL_FREESに対して設定して、リソース処理に間違いがないかどうかを確認しました。

ベータフェーズを速やかに終えたいと思っているので、引き続きODPI-Cについてフィードバックをお寄せください。

より大きなプロジェクトでのODPI-Cの利用を確認したい場合には、このODPI-Cの新リリースを使うようになったPython cx_Oracle 6.0b2をチェックしてください。
Python cx_Oracle 6.0b2
https://github.com/oracle/python-cx_Oracle/releases/tag/6.0b2

[Database] Python cx_Oracle 6.0b2 is available

原文はこちら。
https://blogs.oracle.com/opal/python-cx_oracle-60b2-is-available

Python cx_Oracle 6.0b2がリリースされました。GitHubおよびPyPlからご利用いただけます。
Oracle Database Programming Interface for Drivers and Applications
https://github.com/oracle/odpicx_Oracle 6.0b2 - Python interface to Oracle
https://pypi.python.org/pypi/cx_Oracle/6.0b2
Anthony Tuiningaがいくつかの改良と修正を含むPython cx_Oracle 6.0b2をリリースしました。
PyPIからインストールするには、以下をコマンドを使用します。
python -m pip install cx_Oracle --pre
"--pre" オプションを使わない場合、代わりに現在のProductionバージョン(cx_Oracle 5.3)を取得します。
以前のcx_Oracleをアップグレードする場合は以下のコマンドを実行します。
python -m pip install cx_Oracle --upgrade --pre
リリースノートにはこのリリースでの詳細が全て列挙されています。
Release notes
6.x releases
Version 6.0 beta 2 (May 2017)
http://cx-oracle.readthedocs.io/en/latest/releasenotes.html#version-6-0-beta-2-may-2017
あまり明確ではありませんが、cx_Oracleは基礎となるODPI-C抽象化レイヤーに対する改善のメリットを享受しています。具体的には、cx_Oracle 6.0b2では、一時的なLOBに対してキャッシングが有効になっていたり、LOB、BINARY_FLOAT、BINARY_DOUBLE、NCHAR、NVARCHAR2の値を持つコレクションのオブジェクトの属性や要素値のgetter/setterをサポートします。
ODPI-C's 2.0.0-beta.4 documentation
Release Notes Version 2.0.0-beta.4 (May 24, 2017)
https://oracle.github.io/odpi/doc/releasenotes.html#version-2-0-0-beta-4-may-24-2017
AnthonyはまもなくRelease Candidateフェーズに進むものと思われますので、是非引き続きフィードバックをお願いします。
Issue Tracker
https://github.com/oracle/python-cx_Oracle/issues
cx_Oracle 6では、インストール時にOracle Clientは不要(実行時のみ必要)ということをお忘れ無く。

[Coherence, Docker] Coherence Clusters on Docker Swarm

原文はこちら。
https://blogs.oracle.com/developers/coherence-clusters-on-docker-swarm

Javaのインメモリ・データグリッドは、通常数多くのJVMでクラスタを構成し、データをクラスタ間に分散させるという共通の機能を有しています。JVMが起動時のクラスタ探索にあたっては、マルチキャストを使いますが、これはDockerコンテナ内では機能しません。そのため、インメモリ・データグリッド製品は別の探索機構にフォールバックする必要があります。通常、これはクラスタメンバー・アドレスのリストを手作業で注入したり、別の探索機構を参照したりします。

Oracle CoherenceはDocker Storeからご利用いただけます。
Oracle Coherence
http://store.docker.com/images/oracle-coherence-12c
Docker SwarmでOracle Coherenceクラスタを実行する場合、以前よりもずっとクラスタの探索が簡単になっています。起動時にアドレスリストを挿入する必要がありますが、これはクラスタの開始前にクラスタメンバーのコンテナのIPアドレスのすべてまたは一部を知っている、という点に頼っています。Dockerでは、実行時にコンテナの固定IPアドレスを指定できるため実現できます。とはいえ、アドレス割り当てを気にする必要がないとより柔軟なのは明らかです。

クラスタメンバーが起動すると、クラスタメンバー内のアドレスを検索する必要がありますが、これはクラスタIPアドレスを保持する外部データソースに頼っています。これを実現するDockerサービスの検出に利用可能なアプリケーションがありますが、インフラストラクチャに追加するもう1つの可動要素です。シンプルなアプリケーション・インフラストラクチャであるほど、変なことにならなくなって、より簡単になります。

以前のOracle Coherence on Dockerのブログエントリでは、Coherenceメンバーが複数のDockerホストでクラスタを構成できるようにするために、ホスト・ネットワーキングまたはオーバーレイ・ネットワークを使用する必要がある、と記載しました。
Oracle Coherence on Docker
http://thegridman.com/coherence/oracle-coherence-on-docker/
マルチキャストが可能なホスト・ネットワーキングは最も簡単な解決策ですが、常に利用できるとは限りません。確かに現代のクラウド環境では使えないことがあります。これにより、オーバーレイネットワークを使うことになるわけですが、それに伴い、サービス発見の問題が発生します。しかし、DockerのSwarm Modeが導入されたことで、Oracle Coherenceを使用するコンテナのクラスタ構成がずっと簡単になりました。
Swarm mode overview
https://docs.docker.com/engine/swarm/

Coherence Cluster Discovery

既に触れたように、CoherenceはJVMが起動時にクラスタメンバを探索するための複数の方法を有しています。最も簡単な方法は、マルチキャストですが、これは常に利用可能というわけではなく、確かにDockerコンテナ内では利用できません。もう一つの方法は、well-know-addressingです。これは1個以上のIPアドレスのリストをJVMに渡すというもので、コンテナ内部ではこの方法を使う必要があります。

Well known addressは2方法で提供できます。Coherenceの操作構成ファイル(通常はオーバーライドファイルと呼ばれます)を使って管理します。
<?xml version='1.0'?>
<coherence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://xmlns.oracle.com/coherence/coherence-operational-config"
          xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-operational-config coherence-operational-config.xsd">
 
    <cluster-config>
        <unicast-listener>
            <well-known-addresses>
              … wka configuration …
            </well-known-addresses>
        </unicast-listener>
    </cluster-config>
</coherence>
well-known-addresses要素の内容は、アドレスの提供方法によって異なり、2種類の方法があります。
一つは、カスタムアドレスプロバイダという、com.tangosol.net.AddressProviderを実装したもので、通常は3rdパーティソースからアドレスリストを取得し、必要に応じてそれらを返すカスタムクラスを使います。例えば、私が関わっていたプロジェクトでは、コンテナ管理にMarathon/Mesosを使用しており、このプロジェクトでは、Coherenceクラスタ内のコンテナのIPアドレスを取得するためにMarathon APIに照会するカスタムアドレスプロバイダを使用しています。このアドレスプロバイダの構成例は以下の通りです。
<cluster-config>
        <unicast-listener>
            <well-known-addresses>
                <address-provider>
                    <!-- Specify AddressProvider class name -->
                    <class-name>com.oracle.coherence.clustering.MarathonAddressProvider</class-name>
                </address-provider>
            </well-known-addresses>
        </unicast-listener>
    </cluster-config>
もう一つの方法は、アドレスを直接overridesファイルに書き込むことです。
<cluster-config>
        <unicast-listener>
            <well-known-addresses>
                <!-- Specify one or more IP addresses or host names where the cluster members are running -->
                <address>foo.oracle.com</address>
                <address>bar.oracle.com</address>
            </well-known-addresses>
        </unicast-listener>
    </cluster-config>
実際、Oracle CoherenceのWKA構成では、単一のアドレスがSystemプロパティを介して渡されるように設定されています。 以下はその設定例です。
<cluster-config>
        <unicast-listener>
            <well-known-addresses>
                <address system-property="coherence.wka"></address>
            </well-known-addresses>
        </unicast-listener>
    </cluster-config>
これはつまり単一のWKAの値を実行時に設定でき、この値を使ってクラスタメンバを特定するため、最初のクラスタメンバを当該サーバで起動する必要があります。具体的には以下のような感じです。
$ java -cp ${COHERENCE_HOME}/lib/coherence.jar \
  -Dcoherence.wka=foo.oracle.com \
  com.tangosol.net.DefaultCacheServer
この場合、各Coherenceメンバはfoo.oracle.com上のメンバを探し、このメンバを使って残るクラスタメンバを探します。
これはつまり、Coherenceに設定を追加せずに、すぐにクラスタを起動でき、一つのアドレスを渡すことができ、このアドレスを持つサーバ上のCoherenceメンバは、新しいJVMクラスタメンバが他のメンバを探し始める際に連絡をうけとる、ということです。当該サーバーに問題がある場合を除いて、これでOKです。例えば、クラッシュした場合にはWKAリストが無効なIPアドレスを指しているため、新しいクラスタメンバを開始できません。これを回避するには、通常、構成ファイルに複数のWKAアドレスを指定します。

Coherence Clusters on Docker Swarm

DockerにSwarm Modeとサービスが導入されたことで、結果としてコンテナ内からDNSを使用してサービスのメンバを検索できるようになりました。Oracle CoherenceがWKA名を使用する方法の1つは、これらの名前がDNSを介して複数のアドレスに解決された場合、CoherenceはそれらのすべてのアドレスをWKAリスト用に使用します。したがって、デフォルトのCoherence構成で単一のホスト名しか指定できない上記の場合、DNSを使用してそのホスト名を複数のサーバーに解決できるのであれば、これは制限とはなり得ません。これこそが、Docker Swarm Modeを使ってサービスを構成するコンテナのためにできることです。DockerでサービスとしてCoherenceクラスタを起動すると、特別なホスト名を使用して、そのサービスを構成するコンテナのIPアドレスをすべて検索できます。Dockerのドキュメントには、Swarm Mode Networkingの仕組みの説明があります。
Attach services to an overlay network
https://docs.docker.com/engine/swarm/networking/
上記URLから、Oracle Coherenceにとって重要なことは、全てのサービスはDNS名を有しており、この名前を使ってIPアドレスの検索に利用できる、ということです。Dockerのドキュメントのサンプルをおさらいすると、どれほど簡単かがわかります。

まず、サービスが利用するオーバーレイ・ネットワークを作成します。
$ docker network create \
  --driver overlay \
  --subnet 10.0.9.0/24 \
  my-network
基本的なコンテナを持つシンプルなサービスを起動します。
$ docker service create \
  --name my-busybox \
  --network my-network \
  busybox \
  sleep 3000
サービスをリストアップすると、my-busyboxサービスが実行中であることがわかるはずです。
$ docker service ls
ID            NAME        MODE        REPLICAS  IMAGE
tpsqpgwh423c  my-busybox  replicated  1/1       busy box
サービスを3個のコンテナにスケールアップすることができます。
$ docker service scale my-busybox=3
my-busybox scaled to 3
実行中のコンテナをリストアップすると、my-busyboxサービスを構成するコンテナが確認できるはずです。
$ docker ps --format "{{.ID}}: {{.Names}}"
443d3ea90e62: my-busybox.2.mx5nq93n8w7z80ndfkqd1zmhj
81893dfcdaf8: my-busybox.3.nd4lp1z7iliys8wsplusxkq0a
19d4fdded3dd: my-busybox.1.xewffdq29h7pomx8jhw9xib14
では、nslookupをコンテナ内で使ってtasks.my-busyboxのアドレスを検索します(訳注:nslookupでよいのかどうかはさておき…)
$ docker exec my-busybox.1.xewffdq29h7pomx8jhw9xib14 nslookup tasks.my-busybox
Server:    127.0.0.11
Address 1: 127.0.0.11
 
Name:      tasks.my-busybox
Address 1: 10.0.9.4 my-busybox.2.mx5nq93n8w7z80ndfkqd1zmhj.my-network
Address 2: 10.0.9.5 my-busybox.3.nd4lp1z7iliys8wsplusxkq0a.my-network
Address 3: 10.0.9.3 19d4fdded3dd
各コンテナに1つずつ、3個のアドレスが返っていることがわかります。Docker Storeから利用可能なCoherence Dockerイメージをそのまま使用し、まったく同じコンセプトでOracle Coherenceクラスタを作成できます。ところで、このイメージはOracle LinuxとオフィシャルなOracle Server JREイメージの上に構築されています。
Put Your Containers on a Diet with Oracle Linux
https://blogs.oracle.com/developers/put-your-containers-on-a-diet-with-oracle-linux
Oracle Java 8 SE (Server JRE)
https://store.docker.com/images/oracle-serverjre-8
コンテナエントリポイントとして実行されるイメージ内のシェルスクリプトは、デフォルトでストレージが有効化されたcom.tangosol.net.DefaultCacheServerインスタンスを開始します。シェルスクリプトを使うと、環境変数を設定することで種々のパラメータを渡すこともできます。その1つが、well-known-addressの値を設定するCOH_WKAです。
$ docker pull store/oracle/coherence:12.2.1.2
$ docker service create  --name coh-cluster \
  --network my-network \  
  -e COH_WKA=tasks.coh-cluster \
  store/oracle/coherence:12.2.1.2
サービス起動時にサイズを指定していなかったので、coh-clusterサービスは1個のメンバだけで動作しています。docker psコマンドを実行すると、コンテナを1個のみ表示します。
$ docker ps --format "{{.ID}}: {{.Names}}"
c4917b7c9b9b: coh-cluster.1.tpz4kby4nwpxi0n89herpfsyp
コンテナのログを見ると、1個のメンバを持つ新たなクラスタがあることがわかります。
$ docker logs coh-cluster.1.tpz4kby4nwpxi0n89herpfsyp
ログは以下のような感じで出力されます。
WellKnownAddressList(
  10.0.9.3
  )
MasterMemberSet(
  ThisMember=Member(Id=1, Timestamp=2017-04-14 11:12:04.36, Address=10.0.9.3:36273, MachineId=1586, 
    Location=machine:c4917b7c9b9b,process:1, Role=CoherenceServer)
  OldestMember=Member(Id=1, Timestamp=2017-04-14 11:12:04.36, Address=10.0.9.3:36273, MachineId=1586, 
    Location=machine:c4917b7c9b9b,process:1, Role=CoherenceServer)
  ActualMemberSet=MemberSet(Size=1
    Member(Id=1, Timestamp=2017-04-14 11:12:04.36, Address=10.0.9.3:36273, MachineId=1586, 
      Location=machine:c4917b7c9b9b,process:1, Role=CoherenceServer)
    )
  MemberId|ServiceJoined|MemberState|Version
    1|2017-04-14 11:12:04.36|JOINED|12.2.1.1.0
  RecycleMillis=1200000
  RecycleSet=MemberSet(Size=0
    )
  )
ホスト名 task.coh-service という1個のメンバを持つWKAリストによって単一のコンテナを名前解決したことがわかります。

では、サービスをスケールし、複数のクラスタメンバを持つようにしましょう。
$ docker service scale coh-cluster=3
coh-cluster scaled to 3
この場合、3個のコンテナがあるはずです。
$ docker ps --format "{{.ID}}: {{.Names}}"
50db2c5b76ed: coh-cluster.2.r79i1q03q0umup2b8geovc6m0
8f4159035dd1: coh-cluster.3.i8wdao099zbwa5tdeslx9y2bz
c4917b7c9b9b: coh-cluster.1.tpz4kby4nwpxi0n89herpfsyp
3個目のコンテナのログを見てみると…
$ docker logs coh-cluster.3.i8wdao099zbwa5tdeslx9y2bz
3個のメンバがクラスタに存在しています。
WellKnownAddressList(
  10.0.9.3
  10.0.9.4
  10.0.9.5
  )
MasterMemberSet(
  ThisMember=Member(Id=2, Timestamp=2017-04-14 11:18:01.087, Address=10.0.9.5:42521, MachineId=686, 
    Location=machine:8f4159035dd1,process:1, Role=CoherenceServer)
  OldestMember=Member(Id=1, Timestamp=2017-04-14 11:12:04.36, Address=10.0.9.3:36273, MachineId=1586, 
    Location=machine:c4917b7c9b9b,process:1, Role=CoherenceServer)
  ActualMemberSet=MemberSet(Size=2
    Member(Id=1, Timestamp=2017-04-14 11:12:04.36, Address=10.0.9.3:36273, MachineId=1586, 
      Location=machine:c4917b7c9b9b,process:1, Role=CoherenceServer)
    Member(Id=2, Timestamp=2017-04-14 11:18:00.072, Address=10.0.9.4:39874, MachineId=231, 
      Location=machine:df36591c7ab6,process:1, Role=CoherenceServer)
    Member(Id=3, Timestamp=2017-04-14 11:18:01.087, Address=10.0.9.5:42521, MachineId=686, 
      Location=machine:8f4159035dd1,process:1, Role=CoherenceServer)
  )
  MemberId|ServiceJoined|MemberState|Version
    1|2017-04-14 11:12:04.36|JOINED|12.2.1.1.0,
    2|2017-04-14 11:18:00.072|JOINED|12.2.1.1.0,
    3|2017-04-14 11:18:01.087|JOINED|12.2.1.1.0
  RecycleMillis=1200000
  RecycleSet=MemberSet(Size=0
    )
  )
WKAリストに3つのアドレスがすべて含まれていることがわかります。そんなわけで、Swamを使ってCoherenceクラスタを拡張・縮小することができ、Swamの組み込みDNSのおかげで、CoherenceのWKAはうまく機能します。Docker Storeにあるセットアップ手順には、種々の設定やオプションを使い、Oracle CoherenceのDockerイメージを実行することに関する詳細記述があります。

Container Cloud Serviceを使って、Oracle Cloud PlatformでDockerやCoherenceを試すことができます。
Oracle Container Cloud Service
https://cloud.oracle.com/ja_JP/container
以下のURLにアクセスしてアカウントを取得し、300ドルの無料クレジットを取得してください(訳注:日本はこのエントリ執筆時点では無料クレジットの対象外です)。
トライアルページ
https://cloud.oracle.com/ja_JP/tryit

[Java] Java SE support for Docker CPU and memory limits

原文はこちら。
https://blogs.oracle.com/java-platform-group/java-se-support-for-docker-cpu-and-memory-limits

複数のOpenJDKプロジェクトにコントリビュートしてくれているCharlie Huntがこのようなすばらしいエントリを書いてくれました。とても感謝しています。
Charlie Hunt
http://openjdk.java.net/census#huntch 
Alpine LinuxにJDKのポートを提供するプロジェクトであるOpenJDK Project Portolaを発表したブログのフォローアップとして、Java SEの機能強化がなされました。
Official Docker Image for Oracle Java and the OpenJDK Roadmap for Containers
https://blogs.oracle.com/developers/official-docker-image-for-oracle-java-and-the-openjdk-roadmap-for-containers
[Docker, Java] Official Docker Image for Oracle Java and the OpenJDK Roadmap for Containers
https://orablogs-jp.blogspot.jp/2017/05/official-docker-image-for-oracle-java.html
Portola Project
http://openjdk.java.net/projects/portola/
OpenJDK
http://openjdk.java.net/
Alpine Linux
https://alpinelinux.org/
これはDockerとAlpine Linuxのスローガン「Small、Simple、Secure」にも合致します。今回言及するのは以下の2個です。
  • Docker CPUとメモリ制限のサポート
  • Project Jigsawのjlink。このツールを使って、アプリケーションが利用もしくは必要とするモジュールベースの最小限のJREを作成することができます(jlinkについては今後このエントリで紹介予定です)。
    Project Jigsaw
    http://openjdk.java.net/projects/jigsaw/
    JEP 282: jlink: The Java Linker
    http://openjdk.java.net/jeps/282
Oracle Server JREのDockerイメージはDocker Storeから利用いただけます。
Oracle Java 8 SE (Server JRE)
https://store.docker.com/images/oracle-serverjre-8

Java SE support for Docker CPU and memory limits

JavaアプリケーションでDockerのCPUとメモリの制限を使用してきた人にとって、いくつかの課題がありました。特にCPUの制限は、JVMがGCスレッド数とJITコンパイラスレッド数を内部で透過的に設定するため、課題となっていましたが、これらの値をコマンドラインオプションの-XX:ParallelGCThreads-XX:CICompilerCountで明示的に設定することができます。メモリ制限については、JVMコマンド行オプション-Xmxを使用して、最大Javaヒープ・サイズを明示的に設定することもできます。しかしながら、前述のJVMコマンドラインオプションを指定せず、Java SE 8u121以前のバージョンを使うJavaアプリケーションがDockerコンテナ上で動作する場合、GCスレッド数やJITコンパイラスレッド数、使用する最大Javaヒープサイズを透過的に決定する際に、JVMはDockerが動作するホストのCPUやメモリの構成を使います。

Java SE 8u131およびJDK 9以降、DockerのCPU制限に関してJVMは透過的にDockerを認識しています。つまり、-XX:ParalllelGCThreadsまたは-XX:CICompilerCountがコマンドラインオプションとして指定されていない場合、JVMはDocker CPU制限を、JVMがシステム上で認識するCPUの数として適用します。そしてJVMは、DockerのCPU制限として設定されてる個数のCPUが載っているベアメタルシステム上で動作しているかのように、GCスレッド数とJITコンパイラスレッド数を調整します。-XX:ParallelGCThreadsまたは-XX:CICompilerCountがJVMコマンドラインオプションで指定されていて、DockerのCPU制限が指定されている場合、JVMは-XX:ParallelGCThreadsおよび-XX:CICompilerCountの値を使用します。

Dockerのメモリ制限について、最大Javaヒープの透過的な設定に対する作業がもうすこし必要です。-Xmxを使って最大Javaヒープサイズを設定していない場合に、JVMに対しDockerのメモリ制限を認知するよう指示するには、次の2個のコマンドラインオプションが必要です。
-XX:+UnlockExperimentalVMOptions
-XX:+UseCGroupMemoryLimitForHeap
将来のリリースでDockerメモリ制限の透過的な認知を目標としているため、-XX:+UnlockExperimentalVMOptions が必要です。これら2個のJVMコマンドラインオプションを使い、 -Xmx を指定しない場合には、JVMはLinux cgroupの設定(Dockerコンテナがメモリ制限の設定のために利用)を見て、透過的に最大Javaヒープサイズを設定します。参考までに、DockerコンテナもまたCPU制限のためにcgroupsの設定を使います。

Java SE 8u131およびJDK 9でのこれらの2個の変更で、DockerでのJavaの実行体験の改善が期待されます。
8u131 Update Release Notes
http://www.oracle.com/technetwork/java/javase/8u131-relnotes-3565278.html
JDK 9
http://openjdk.java.net/projects/jdk9/

これらの機能強化の作業は両方ともOpenJDKでトラッキングされています。

[Java, Cloud] JOnsen, Java Day Tokyo, Oracle Code, and JJUG CCC

皆様いかがお過ごしでしょうか。先週はJava Weekでしたね。
先週(厳密には12日から20日まで)はタイトルに記載した4イベントに参加(そのうち3イベントに登壇)することができ、非常に刺激を受けました。セッションならびにイベントに参加いただいた皆様には厚く御礼申し上げます。

JOnsen (12-14, May, 2017)

伊豆半島の下田で開催された、第1回JOnsen。
他の方がいろいろコメントされていると思うので、詳細は割愛しますが、面白い取り組みだと思います。日本と海外の違いがわかったり、日本と海外で同じ悩みを持っていたり、といろいろな気付きがあり、興味深いものでした。来年の開催も期待しましょう(もし来年開催するとなれば、なんとなく裏方の仕事をやることになるのでは、という気がしています)。JOnsenについては以下のURLからどうぞ。
Java Unconference at a Japanese Onsen
http://jonsen.jp/

Java Day Tokyo 2017 (17, May, 2017)

トピックはCDI 2.0。既にほぼ仕様は決まっていて、2年前に上妻さんがまとめてらっしゃる内容からの変更はあまりない、という状況でしたが、直前に全EGによって承認されたのでよかったですね(あのJSR 376とは違います)。セッションでは、Java SEサポートとCDIコンテナ起動のAPIを使ったデモをご紹介しましたが、CDIってデモ映えしないので、ちょっとわかりづらかったかもしれません。。。
スライドはイベントのページから公開されますが、こちらにも貼り付けておきます。


Oracle Code Tokyo 2017 (18, May, 2017)

基調講演の1コマになぜか登壇することになりました。ここでちょびっと喋ったことで、社内にも中の人が誰か認知されたという。。。

# 実を言うと、このコマで紹介したAPI Platform Cloud Serviceを含む、iPaaS (Integration PaaS) と呼ばれる類いのサービスが当方の主担当なのです。

API Managementは様々なお歴々が語ってらっしゃるので、当方があの短い10分程度でさらに何かすごい話ができるわけもないのですが、お伝えしたかったのは、
"MicroservicesのAPIの公開"という狭い観点ではなく、"APIの公開"という観点で考えると、すなわち情報公開なので、当該情報の管理だけでなく、情報へのアクセス管理も必要であり、その管理のしくみはプロセス化しておく必要がある
ということでした。なので、基調講演に参加された皆様に上記の内容が伝われば成功かなー、と考えています。特に社外公開する場合には、SaaSプロバイダとして情報を提供することに他ならないわけですから、より一層の管理が必要ですよねぇ。
なお、このコマでお話した内容は、昨年のOpen WorldでのAPI Platformのセッションや、今年の2月のAPI Platform & Identity Managementのイベントでお話した内容と同一です。スライドが公開されるかどうかはわからないのですが、もし公開されるようなら、イベントページからダウンロードできるはずです。

JJUG CCC 2017 Spring (20, May, 2017)

元々20分枠で申し込んだのですが、なぜか45分枠に格上げ(?)されました。しかもGraalという、ニッチかつマニアックな内容だったので、数名の方に聞いてもらえたらいいかなー、と思っていたのですが、大幅に上回る人数の方々に聞いていただきありがとうございました(最前列に鎮座なさっていたきつねさんやじゅくちょーさんからの目が一番厳しかったのは言うまでもありません)。
Graalの話はどこまで詳細に踏み込むべきか思案していたため、今回はあえて難しくならないレベルに抑えました。スライドはこちらからどうぞ。


このセッションの部屋を担当されていたまめぴかさんの落胆のTweetが涙を誘うものでしたので、ここにUpしておきます。



休憩時間中に久保田さんに、懇親会でかずひらさんやうらがみさん、キクタローさんにご挨拶できたのはよかったです。みなさまありがとうございました。当面イベント登壇はないので、しばらく地道にステルス性能を向上させる所存でございます。今後ともどうぞご贔屓に。

[Java] GlassFish 5 Promoted Build 6

原文はこちら。
https://blogs.oracle.com/theaquarium/glassfish-5-promoted-build-6

Java.netの移行が原因で数週間GlassFishのpromotionプロセスを一時停止しなければなりませんでしたが、Nightly Buildsは移行後すぐに利用できるようになっています。
GlassFish 5 nightly builds
http://download.oracle.com/glassfish/5.0/nightly/index.html
(Java.net移行に伴い)以下の新しいホームに変わったことにご注意ください。
GlassFish - The Open Source Java EE Reference Implementation
https://javaee.github.io/glassfish/
GlassFishのソースコードは以下にあります。
GlassFish Server
https://github.com/javaee/glassfish
最新のGlassFish 5.0-b06 promoted buildは以下からご利用頂けます。
GlassFish 5 promoted builds
http://download.oracle.com/glassfish/5.0/promoted/index.html
このビルドの詳細は以下の通りです。

Component Update:

  • Grizzly 2.4.0-beta2

Bug Fixes:

Issue ID
 Summary
20684
 Visual issue in the Batch Admin UI
21693
 Rename install directory to 'glassfish5'
21702
 Update Java EE version in master pom.xml to EE8
21714
 Warning related core.jar bundle not started in time of startup

ちょっとしたことですが重要な変更として、インストールディレクトリがglassfish4からglassfish5に変わっています。ご自身のスクリプトをアップデートしてこの変更を反映するようにしてください。

是非お試しいただいて、何か問題があればGitHubのissue trackerにレポートしてください。
glassfish issue tracker
https://github.com/javaee/glassfish/issues

[Java, Cloud] Introducing Application Cache Client Java SDK for Oracle Cloud

原文はこちら。
https://blogs.oracle.com/developers/introducing-application-cache-client-java-sdk-for-oracle-cloud

Oracle Application Container Cloud (ACCS) のApplication Cacheは(名前が示す通り)アプリケーションのキャッシュ機能を提供します。
Application Container Cloud Service
https://cloud.oracle.com/ja_JP/acc
Mike LehmannによるCaching with Oracle Application Container Cloudと題したエントリで説明した通り、Cacheに使いたいメモリのサイズと基本的な開発・検証環境用非HAキャッシュもしくは本番環境用の信頼性の高いキャッシュを指定するだけで、適切なインフラストラクチャを自動的にプロビジョニングします。
Caching with Oracle Application Container Cloud
https://blogs.oracle.com/developers/caching-with-oracle-application-container-cloud

Under the Hood

ACCS Application Cacheは高パフォーマンスかつスケーラブルなOracle Coherenceインメモリデータグリッド上に構築されています。Oracle Coherenceはトレーディングやその他メモリやレイテンシの要求に厳しいアプリケーションを長年支えているコンポーネントです。
Oracle Coherence
http://www.oracle.com/technetwork/jp/middleware/coherence/overview/index.html
ACCS Application CacheではCoherence実装は公開されていませんが、インメモリ・データグリッドクラウドサービスを必要とする場合には、心配する必要はありません。Oracleがまさにそれをやっています。この間、Coherenceチームは継続して革新を続けています。例えば、以下の動画はOracle CodeでのBrian Oliverによる分散ストリームに関するセッションです。


この動画では背後にあるすばらしいエンジンについて説明していますが、メイントピックに戻ることにしましょう。

Java Caching

Application Cacheは、最初は言語に依存しないREST APIでリリースされましたが、Javaアプリケーションが容易にキャッシュを利用できるよう、新たにネイティブJavaクライアントライブラリが作成されました。Javaからのキャッシュ使用を簡素化するのに加え、キャッシュとクライアント間の効率的なデータ転送を実現するためのgRPCのオプションもライブラリに追加されています。
gRPC
http://www.grpc.io/
クライアントライブラリはオープンソースフレームワークで、GitHubでホストされており、バイナリは、Maven Centralから直接ダウンロードすることも利用することもできます。
Application Container Cloud Service Application Cache Java API
https://github.com/oracle/accs-caching-java-sdk
Javaクライアントライブラリを紹介するため、簡単な例で使用方法の基礎を説明し、そのサンプルコードをApplication Container Cloudにデプロイする方法を紹介します。

Background

読者の皆さんが、Application Cacheの機能をご存知であることを前提として、今回はJavaクライアントライブラリに焦点を当てています。ACCS Application Cacheをご存知ない場合は、以下のリソースで詳細を説明しています。

Cache API Basics

数ステップの簡単な手順でJavaクライアントライブラリを使ってキャッシュにアクセスすることができます。
  1. 名前(MyCacheなど)と目的のトランスポートプロトコルをサポートするポート(gRPCの場合は1444、RESTの場合は8080)をURLとして指定し、以前に作成したApplication Cache用のSessionProviderを作成します。RESTを使用する場合、キャッシュのホスト名の後に "/ ccs" が続きます。
    SessionProvider sessionProvider = new RemoteSessionProvider("http://MyCache:1444");
  2. 指定したポートで利用可能なトランスポートを指定し、SessionProviderからSessionを取得します。
    Session cacheSession = sessionProvider.createSession(Transport.grpc());
  3. SessionからCacheオブジェクトを取得します。キャッシュがない場合には作成されます。
    Cache<Users> users = cacheSession.getCache("users");

Using A Cache

キャッシュは(Key-Valueペアの)アイテムのget、put、replace、removeをサポートします。 各操作はJava Sparkフレームワークを使う非常にシンプルなUser管理RESTサービスを提供するサンプルに含まれています。
Spark Framework: A tiny Java web framework
http://sparkjava.com/
サンプルのバックエンドでは、 UserService がUserの create/update/delete 操作を提供しており、この操作はApplication Cache Javaクライアントライブラリを使って実装されています。例えば、UserオブジェクトをそのIDを使ってusersキャッシュに入れるコードは以下のようです。
users.put(user.getId(),user);
キャッシュからの削除は users.remove(id) だけで、とても簡単ですが、キャッシュはローカルにないので、remove APIはパフォーマンス最適化オプションを提供しています。JDKの java.util.Map インターフェースは(もしあれば)削除されたオブジェクトとしてremove()メソッドの戻り値を定義していますが、キャッシュを扱う場合、単にオブジェクトを削除したいだけで、キャッシュから削除されたオブジェクトをクライアントに返すコストをかけたくないかもしれません。そんなわけで、Javaクライアントライブラリの Cache.remove() メソッドでは、削除されたオブジェクトを返すかどうかを指定します。デフォルトでは、削除されたオブジェクトを返さず、メソッドはNullを返します。以下は削除されたオブジェクトを必要とするためにReturn.OLD_VALUEオプションを指定しています。
User user = users.remove(id, Return.OLD_VALUE);
Cache.replace() でユーザーを更新する場合のように、remove()メソッドはネットワーク越しに通信するデータ量を制御する機能を提供しています。今回の場合、置換対照のオブジェクトの詳細に興味がないので、デフォルトの挙動のまま、指定したキーに対する以前のオブジェクトを転送しないようにしているので、nullが返ります。
users.replace(id, user);

この図はApplication Container Cloudにデプロイした際のサンプルの構造を図示したものです。クライアントはUserアプリケーションにRESTでアクセスすると、ACCSロードバランサーによってルーティングされます。この図で、アプリケーションを2インスタンスにスケールアウトしています。'MyCache' Application Cache もまた3インスタンスにスケールアウトして、高可用性構成を提供し、全データがメモリ上で安全であることを保証します。任意の1個のキャッシュインスタンスがなくなった場合でも、データの消失はありません。Userアプリケーションはステートレスであり、Javaクライアントライブラリを使って、ACCS内部オーバーレイ・ネットワーク上のキャッシュと対話します。様々なワークロードを処理するためにUserアプリケーションインスタンスの個数がスケールアップしたりスケールダウンしたりしても、データは引き続き安全にキャッシュに格納されます。

Deploying the Example

ではこれらを踏まえて、サンプルをデプロイし、試すことにしましょう。
  1. 1GBのストレージを持つ、MyCacheというApplication CacheをBasicタイプで作成します。この構成では、キャッシュデータのメモリの安全性を保証しませんが、サンプルのためにはこれでOKです。以下のチュートリアルの "Creating a Cache" の手順に従って作成します。
    Oracle® Cloud Using Caches in Oracle Application Container Cloud Service
    Creating a Cache Service
    http://docs.oracle.com/en/cloud/paas/app-container-cloud/cache/creating-cache-service.html
  2. このサンプルのGitリポジトリをローカルに複製します。
  3. サンプルをビルドして、デプロイ可能なアプリケーション・アーカイブを生成します。複製したGitリポジトリのcache-client-examples/appcache-example フォルダ内で、mvn clean packageを実行します。このコマンドを実行すると、”fat”なJarファイルが生成されます。このファイルにはアプリケーションコードと、Javaクライアントライブラリを含む、アプリケーションが依存している全てのライブラリが含まれています。Mavenビルドによって、ACCSアプリケーションアーカイブファイルも生成されます。このファイルにはfat Jarファイルがmanifest.jsonファイルと共にパッケージされています。
  4. ACCSサービスコンソールに移動し、”Create Application”をクリックして、Java SEをランタイムとして選択します。
  5. アプリケーション名を付けて、”Upload”を選択し、Mavenが生成したtargetフォルダから appcache-example-1.0-dist.zip アプリケーションアーカイブを選択します。
  6. MyCache を関連付けられたApplication Cacheとして選択します。Application Cacheが未作成もしくは現在プロビジョニング中である場合には、キャッシュの選択ドロップダウンリストが現れないことにご注意ください。deployement.jsonファイルでサービスバインディングを使うことでApplication Cacheとアプリケーションの関連付けをすることもできます。
    Oracle® Cloud Using Caches in Oracle Application Container Cloud Service
    Creating Metadata Files
    http://docs.oracle.com/en/cloud/paas/app-container-cloud/dvcjv/creating-meta-data-files.html
  7. 'Create' をクリックして、アプリケーションアーカイブをアップロードし、サンプルのインスタンスをデプロイします。これでおしまいです。
Webコンソールではなく、コマンドラインで操作したい場合には、ACCS REST APIをcURLで使って、アプリケーションのライフサイクルを完全に管理することもできます。
REST API for Managing Applications
http://docs.oracle.com/en/cloud/paas/app-container-cloud/apcsr/index.html 

Using the Example

アプリケーションを実行したら、そのURLをApplicationsリストならびにアプリケーションの詳細ページで把握できます。デプロイされたアプリケーションを試すために、このURLが必要です。

Creating a User

単純化するため、cURLを使ってデプロイ済みのサンプルと対話することにします。Userを作成するためには、POSTを実行する必要があります。UserControllerクラスのPOSTエンドポイントは以下のようです。
post("/users", (req, res) -> userService.createUser(
        req.queryParams("name"),
        req.queryParams("email")
), json());
これから、nameemailという2個のクエリパラメータを渡す必要があることがわかります。ターミナルから、ご自身のアプリケーションのURLを使って、以下のように実行してください。
$ curl -i -X POST https://CacheDemo-paas104.apaas.us2.oraclecloud.com/users?name=mark\&email=twain@riverboat.org
実行すると、作成され、キャッシュに配置されたUserオブジェクトがJSONデータを伴い200で返ってきます。
HTTP/1.1 200 OK
Server: Jetty(9.3.z-SNAPSHOT)
Date: Mon, 01 May 2017 20:18:15 GMT
Content-type: application/json Via: 1.1 net-apaasotd
Proxy-agent: Oracle-Traffic-Director/11.1.1.9
Transfer-encoding: chunked
{
  "id":"92e7d5f0-6919-4f72-9f85-e8b01dedc770",
  "name":"mark",
  "email":"twain@riverboat.org"
}
作成の成功を確認するため、POSTの結果返ってきたidを使ってユーザーに対するGETを実行することができます。
$ curl -i -X GET https://CacheDemo-paas104.apaas.us2.oraclecloud.com/users/92e7d5f0-6919-4f72-9f85-e8b01dedc770

HTTP/1.1 200 OK
Server: Jetty(9.3.z-SNAPSHOT)
Date: Mon, 01 May 2017 20:18:50 GMT
Content-type: application/json
Via: 1.1 net-apaasotd
Proxy-agent: Oracle-Traffic-Director/11.1.1.9
Transfer-encoding: chunked
{
  "id":"92e7d5f0-6919-4f72-9f85-e8b01dedc770",
  "name":"mark",
  "email":"twain@riverboat.org"
}
いい感じですね。ユーザーがキャッシュにあります。

Updating a User

作成したユーザーの名前と電子メールを更新するには、以下のように(作成したユーザーのIDに置き換えて)実行してください(これは簡単な例ですので、あまり洗練されていません)。
$ curl -i -X PUT https://CacheDemo-paas104.apaas.us2.oraclecloud.com/users/92e7d5f0-6919-4f72-9f85-e8b01dedc770?name=luke\&email=luke@rebellion.org
200が返ってきて、更新されたユーザーが表示されます。
HTTP/1.1 200 OK
Server: Jetty(9.3.z-SNAPSHOT)
Date: Mon, 01 May 2017 20:21:04 GMT
Content-type: application/json
Via: 1.1 net-apaasotd
Proxy-agent: Oracle-Traffic-Director/11.1.1.9
Transfer-encoding: chunked

{
  "id":"92e7d5f0-6919-4f72-9f85-e8b01dedc770",
  "name":"luke",
  "email":"luke@rebellion.org"
}

Deleting a User

キャッシュからユーザーをDELETE しましょう(削除されたUserオブジェクトが返ります)。
$ curl -i -X DELETE https://CacheDemo-paas104.apaas.us2.oraclecloud.com/users/92e7d5f0-6919-4f72-9f85-e8b01dedc770

HTTP/1.1 200 OK
Server: Jetty(9.3.z-SNAPSHOT)
Date: Mon, 01 May 2017 20:23:07 GMT
Content-type: application/json
Via: 1.1 net-apaasotd
Proxy-agent: Oracle-Traffic-Director/11.1.1.9
Transfer-encoding: chunked

{
  "id":"92e7d5f0-6919-4f72-9f85-e8b01dedc770",
  "name":"luke",
  "email":"luke@rebellion.org"
}
削除を確認するため、UserをGETしましょう。
$ curl -i -X GET https://CacheDemo-paas104.apaas.us2.oraclecloud.com/users/92e7d5f0-6919-4f72-9f85-e8b01dedc770
404が返ってくるので、キャッシュにはもう存在しないことがわかります。
HTTP/1.1 404 Not Found
Server: Jetty(9.3.z-SNAPSHOT)
Date: Mon, 01 May 2017 20:23:12 GMT
Content-type: application/json
Via: 1.1 net-apaasotd
Proxy-agent: Oracle-Traffic-Director/11.1.1.9
Transfer-encoding: chunked

{
  "message":"No user with id \u002792e7d5f0-6919-4f72-9f85-e8b01dedc770\u0027 found"
}

Developing Locally

Application Cacheを使うアプリケーションの開発、テスト、デバッグを容易にするため、JavaキャッシュクライアントライブラリはLocalSessionをサポートしています。ACCSにデプロイする際に利用するRemoteSessionと全く同じAPIを提供していますが、インプロセスで実行します。LocalSessionを使うLocalUserServiceクラスの例をご覧ください。LocalMainクラスを実行すると、リモートの共有キャッシュではなく、ローカルのインプロセスキャッシュでサンプルアプリケーションを開始できます。お手軽ですね。

Obtaining the Application Cache Java Client Library

Javaキャッシュクライアントライブラリを入手する方法は複数ありますので、お好きな方法でどうぞ。
  1. 一つ目は、Maven Centralを使う方法です。依存性を解決するため、pom.xmlに以下を追加します。
    <dependency>
        <groupId>com.oracle.cloud.caching</groupId>
        <artifactId>cache-client-api</artifactId>
        <version>1.0.0</version>
    </dependency>
  2. 2番目は、Oracle Technology NetworkのCloud Downloadページから入手する方法です。
    Oracle Cloud Downloads
    http://www.oracle.com/technetwork/topics/cloud/downloads/index.html
    Jarファイル、javadoc、ソースが入ったZipファイルをダウンロードできます。
    Application Container Cloud Service Downloads
    http://www.oracle.com/technetwork/topics/cloud/downloads/app-cloud-service-3707850.html
  3. 最後に、クライアントライブラリのソースが格納されているGitHubからソースを入手することができます。
    Application Container Cloud Service Application Cache Java API
    https://github.com/oracle/accs-caching-java-sdk

Acknowledgements

今回のサンプルは、Michael ScharhagがJava Sparkフレームワークを紹介したブログ記事のコードに基づいています。元のコードはApache 2.0ライセンスに基づいており、今回かなりの変更を加えています。
mscharhag/blog-examples is licensed under the Apache License 2.0
https://github.com/mscharhag/blog-examples/blob/master/LICENSE
特に、元のインメモリUser HashMapをACCS Application Cacheに置き換えました。Michaelのブログエントリにオリジナルのエントリとそれに関連するコードが掲載されています。
Building a simple RESTful API with Spark
http://www.mscharhag.com/java/building-rest-api-with-spark