2016年7月28日

[Java] Kurian Outlines Java EE Next Steps

原文はこちら。
https://blogs.oracle.com/TheOracleBlog/kurian-clarifies-oracle%E2%80%99s-java-ee-commitment

Oracleが来るJava Enterprise Editionへの「非常に明確な計画を持っている」ことをJavaコミュニティのために再確認し、基礎となるアプリケーション開発プラットフォームに対する数多くの今後の改善点をThomas Kurian(Oracleの製品開発President)が説明しました。
「顧客がクラウドにシフトし、マイクロサービスアプリケーションアーキテクチャを採用しているため、クラウドコンピューティングという『新しい世界で存続可能である』ために、Javaプラットフォームをモダナイズしなければならない」と、先週のInfoWorldでのインタビューでKurianは述べています。
Exclusive: Oracle to reboot Java EE for the cloud
http://www.infoworld.com/article/3098007/java/oracle-to-reboot-java-ee-for-the-cloud.html
Kurianは、Java EE 8のリリースに関する計画を発表しました。この計画には以下の点の改善が含まれます。
  • マルチテナント・クラウド・デプロイメントのサポート
  • マイクロサービス・アーキテクチャのサポート
  • Dockerやその他のコンテナテクノロジーのサポート
  • NoSQLを利用するしくみ
  • 新しい認証認可モデルのサポート
Kurianはインタビューで以下のように述べました。「最後に、開発者コミュニティのために正しいことをやっているのであれば、開発者のコ​​ミュニティのみなさんが結集してくれる、と信じている」

JavaOne 2016に参加登録し、グローバルのJavaコミュニティの一員になってください。
Register for JavaOne 2016
https://www.oracle.com/javaone/register/index.html 
 (訳注)
 新しい方針はJavaOne 2016で発表される予定です。

2016年7月27日

[Database, Docker] Creating and Oracle Database Docker image

原文はこちら。
https://blogs.oracle.com/developer/entry/creating_and_oracle_database_docker

Oracle Database用のDockerビルドファイルがGitHubにリリースされています。
Oracle Database on Docker
https://github.com/oracle/docker-images/tree/master/OracleDatabase
これらのビルドファイルを使うと、Oracle Databaseの自身のDockerイメージを作成できます。Dockerをご存知ない方は、以下のリンクをどうぞ。
Docker
https://www.docker.com/
Linuxコンテナテクノロジーをベースとした、アプリケーションなどをコンテナ化することができる非常にクールなテクノロジーです。データベースのコンテナ化までに要する時間はそれほどかからず、特に開発、検証環境のためには有用です。Oracleが提供しているビルドファイルを使ってOracle Databaseをコンテナ化する方法を見ていきましょう。

What you need

Environment

テストに使った環境は以下の通りです。
  • Oracle Linux 7.2 (4.1.12-32.2.1.el7uek.x86_64)
  • Docker 1.10.3 (docker-engine.x86_64 1.10.3-1.0.3.el7)
  • Oracle Database 12.1.0.2 Enterprise Edition

Docker setup

まず、Dockerをセットアップしますが、幸運にもDockerがPublic Yumパッケージとして提供されているので、これは非常に簡単です。作業はdocker-engineパッケージをrootユーザとしてインストールするだけでOKです。
[root@localhost ~]# yum install docker-engine
Loaded plugins: langpacks, ulninfo
Resolving Dependencies
--> Running transaction check
---> Package docker-engine.x86_64 0:1.10.3-1.0.3.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

=====================================================================================================================================
 Package                           Arch                      Version                               Repository                     Size
=====================================================================================================================================
Installing:
 docker-engine                     x86_64                    1.10.3-1.0.3.el7                      ol7_addons                    9.6 M

Transaction Summary
=====================================================================================================================================
Install  1 Package

Total download size: 9.6 M
Installed size: 41 M
Is this ok [y/d/N]: y
Downloading packages:
docker-engine-1.10.3-1.0.3.el7.x86_64.rpm                                                                     | 9.6 MB  00:00:03
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
   Installing :  docker-engine-1.10.3-1.0.3.el7.x86_64                                                                              1/1
  Verifying  :  docker-engine-1.10.3-1.0.3.el7.x86_64                                                                              1/1

Installed:
  docker-engine.x86_64 0:1.10.3-1.0.3.el7

Complete!
[root@localhost ~]#
これでDockerのインストールは終了です。Dockerを開始してイメージビルドを実行する前に、デフォルト設定を微調整して、Oracle Database用に十分なディスクサイズを提供することを確認する必要があります。Dockerはデフォルトのコンテナサイズの最大値が10GBです。このサイズは、通常Dockerコンテナ内で実行するアプリケーションにとっては十分なサイズではありますが、Oracle Database Enterprise Edition実行のためには上限を拡大する必要があります。この例では、15GBまで拡張し、コンテナ内でOracle Databaseとデータをホストできるようにします。もちろん、要件に合わせて上限をもっと大きな値にすることもできます。このデフォルト値を増加するためには、 storage-opt dm.basesize というストレージオプションを所望の15GBに設定する必要があります。このオプションを/etc/sysconfig/docker-storageというファイルに追記することで上限を拡大することができます。
[root@localhost ~]# cat /etc/sysconfig/docker-storage
# This file may be automatically generated by an installation program.

# By default, Docker uses a loopback-mounted sparse file in
# /var/lib/docker.  The loopback makes it slower, and there are some
# restrictive defaults, such as 100GB max storage.

# If your installation did not set a custom storage for Docker, you
# may do it below.

# Example: Use a custom pair of raw logical volumes (one for metadata,
# one for data).
#  DOCKER_STORAGE_OPTIONS = --storage-opt  dm.metadatadev=/dev/mylogvol/my-docker-metadata --storage-opt  dm.datadev=/dev/mylogvol/my-docker-data

DOCKER_STORAGE_OPTIONS=--storage-opt dm.basesize=15G
これで、systemctlを使ってDockerを開始する準備が整いました。
[root@localhost ~]# systemctl start docker
[root@localhost ~]#
先ほど指定したコンテナサイズの上限値の設定が受け入れられたことを、docker infoを使って確認することができます(確認するためにはDockerを起動しておく必要があります)。
[root@localhost ~]# docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 0
Server Version: 1.10.3
Storage Driver: devicemapper
 Pool Name: docker-251:0-203798656-pool
 Pool Blocksize: 65.54 kB
Base Device Size: 16.11 GB
 Backing Filesystem:
 Data file: /dev/loop0
 Metadata file: /dev/loop1
 Data Space Used: 391.4 MB
 Data Space Total: 107.4 GB
 Data Space Available: 48.37 GB
 Metadata Space Used: 774.1 kB
 Metadata Space Total: 2.147 GB
 Metadata Space Available: 2.147 GB
 Udev Sync Supported: true
 Deferred Removal Enabled: false
 Deferred Deletion Enabled: false
 Deferred Deleted Device Count: 0
 Data loop file: /var/lib/docker/devicemapper/devicemapper/data
 WARNING:  Usage of loopback devices is strongly discouraged for production use.  Either use `--storage-opt dm.thinpooldev` or use `--storage-opt  dm.no_warn_on_loop_devices=true` to suppress this warning.
 Metadata loop file: /var/lib/docker/devicemapper/devicemapper/metadata
 Library Version: 1.02.107-RHEL7 (2015-12-01)
Execution Driver: native-0.2
Logging Driver: json-file
Plugins:
 Volume: local
 Network: null host bridge
Kernel Version: 4.1.12-32.2.1.el7uek.x86_64
Operating System: Oracle Linux Server 7.2
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 7.795 GiB
Name: localhost.localdomain
ID: AWF3:DGIQ:YX2P:5BWD:KDQP:G3T3:6UNP:UE2W:POTZ:G4VZ:7IYV:BPIB

Obtaining the required files

Dockerが起動すれば、イメージの作成を始めることができます。上述の通り、まずOracle DatabaseのインストールバイナリとDockerビルドファイルの両方が必要で、どちらも入手は簡単です。Oracle Databaseのインストールバイナリについては、通常ダウンロードされる場所からダウンロードします。おそらくOracle Technology Networkがよく利用される場所でしょう。
Oracle Technology Network
ダウンロードが完了したら、イメージ作成に取りかかることができます。 oracle ユーザーで以下の手順を進めます。
[oracle@localhost ~]$ ls -al
total 2625120
drwx------. 15 oracle oracle       4096 Jul 22 13:21 .
drwxr-xr-x.  3 root   root           19 Mar 25 20:03 ..
-rw-------.  1 oracle oracle        566 Mar 25 20:52 .bash_history
-rw-r--r--.  1 oracle oracle         18 Sep 11  2015 .bash_logout
-rw-r--r--.  1 oracle oracle        193 Sep 11  2015 .bash_profile
-rw-r--r--.  1 oracle oracle        231 Sep 11  2015 .bashrc
drwx------. 10 oracle oracle       4096 Mar 25 19:06 .cache
drwxr-xr-x. 15 oracle oracle       4096 Mar 25 19:06 .config
drwxr-xr-x.  2 oracle oracle          6 Mar 25 19:05 Desktop
drwxr-xr-x.  2 oracle oracle          6 Mar 25 19:05 Documents
drwxr-xr-x.  2 oracle oracle          6 Mar 25 19:05 Downloads
-rw-------.  1 oracle oracle         16 Mar 25 19:05 .esd_auth
-rw-------.  1 oracle oracle       4030 Mar 25 20:48 .ICEauthority
-rw-------.  1 oracle oracle         57 Mar 25 19:55 .lesshst
-rw-r--r--.  1 oracle oracle 1673544724 Jul 22 13:21 linuxamd64_12102_database_1of2.zip
-rw-r--r--.  1 oracle oracle 1014530602 Jul 22 13:22 linuxamd64_12102_database_2of2.zip
drwx------.  3 oracle oracle         18 Mar 25 19:05 .local
drwxr-xr-x.  4 oracle oracle         37 Mar 25 19:40 .mozilla
drwxr-xr-x.  2 oracle oracle          6 Mar 25 19:05 Music
drwxr-xr-x.  2 oracle oracle          6 Mar 25 19:05 Pictures
drwxr-xr-x.  2 oracle oracle          6 Mar 25 19:05 Public
drwx------.  2 oracle oracle          6 Mar 25 19:33 .ssh
drwxr-xr-x.  2 oracle oracle          6 Mar 25 19:05 Templates
drwxr-xr-x.  2 oracle oracle          6 Mar 25 19:05 Videos
続いて、Dockerビルドファイルをダウンロードする必要がありますが、色々な方法があります。Gitリポジトリを直接クローンすることもできますが、簡単のため、かつGitに詳しくない人のことを考慮して、GitHubのダウンロードオプションを使うことにします。メインリポジトリに移動し、[Clone or download]の緑色のボタンを確認し、そのボタンをクリックして、”Download Zip”を選択します。
Official source for Docker configurations, images, and examples of Dockerfiles for Oracle products and projects
https://github.com/oracle/docker-images/
その他、リポジトリを直接静的URLからダウンロードすることもできます。
https://github.com/oracle/docker-images/archive/master.zip
[oracle@localhost ~]$ wget https://github.com/oracle/docker-images/archive/master.zip
--2016-07-22 13:30:14--  https://github.com/oracle/docker-images/archive/master.zip
Resolving github.com (github.com)... 192.30.253.112
Connecting to github.com (github.com)|192.30.253.112|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/oracle/docker-images/zip/master [following]
--2016-07-22 13:30:14--  https://codeload.github.com/oracle/docker-images/zip/master
Resolving codeload.github.com (codeload.github.com)... 192.30.253.120
Connecting to codeload.github.com (codeload.github.com)|192.30.253.120|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 4064219 (3.9M) [application/zip]
Saving to: ‘master.zip’

100%[===========================================================================================>]  4,064,219    393KB/s   in 6.9s

2016-07-22 13:30:21 (577 KB/s) - ‘master.zip’ saved [4064219/4064219]
Zipファイルをダウンロードしたら、ファイルを展開します。
[oracle@localhost ~]$ unzip master.zip
Archive:  master.zip
ce91c58275d24df32b3f5d3b8a68000ade61d562
   creating: docker-images-master/
 extracting: docker-images-master/.gitattributes
  inflating: docker-images-master/.gitignore
  inflating: docker-images-master/.gitmodules
...
...
...
  inflating: docker-images-master/README.md
[oracle@localhost ~]$

Building the Oracle Database Docker image

必要なファイルが全てそろったので、Dockerイメージを作成します。docker-images-master/OracleDatabaseのREADME.mdという個別のファイルがあり、このファイルでビルドプロセスを詳細に説明しています。
README.md - Oracle Database on Docker
https://github.com/oracle/docker-images/blob/master/OracleDatabase/README.md
 docker-images-master/OracleDatabase/dockerfiles にある buildDockerImage.sh というシェルスクリプトファイルは、ビルドにおける細々複雑な作業をします。ビルドの際には、正しいバージョンのディレクトリにインストールファイルをコピーすることが必要です。Oracle Database 12.1.0.2 EEイメージを作成する予定なので、ファイルを  docker-images-master/OracleDatabase/dockerfiles/12.1.0.2 にコピーする必要があります。
[oracle@localhost ~]$ cd docker-images-master/OracleDatabase/dockerfiles/12.1.0.2/
[oracle@localhost 12.1.0.2]$ cp ~/linuxamd64_12102_database_* .
[oracle@localhost 12.1.0.2]$ ls -al
total 2625144
drwxrwxr-x. 2 oracle oracle       4096 Jul 22 13:50 .
drwxrwxr-x. 4 oracle oracle         62 Jul 21 14:07 ..
-rw-rw-r--. 1 oracle oracle        515 Jul 21 14:07 Checksum.ee
-rw-rw-r--. 1 oracle oracle        523 Jul 21 14:07 Checksum.se2
-rw-rw-r--. 1 oracle oracle      12738 Jul 21 14:07 dbca.rsp
-rw-rw-r--. 1 oracle oracle       9118 Jul 21 14:07 db_inst.rsp
-rw-rw-r--. 1 oracle oracle       5491 Jul 21 14:07 Dockerfile.ee
-rw-rw-r--. 1 oracle oracle       5508 Jul 21 14:07 Dockerfile.se2
-rwxr-xr-x. 1 oracle oracle        773 Jul 21 14:07 installPerl.sh
-rw-r--r--. 1 oracle oracle 1673544724 Jul 22 13:50 linuxamd64_12102_database_1of2.zip
-rw-r--r--. 1 oracle oracle 1014530602 Jul 22 13:50 linuxamd64_12102_database_2of2.zip
-rwxr-xr-x. 1 oracle oracle        120 Jul 21 14:07 runOracle.sh
buildDockerImage.sh シェルスクリプトファイルを呼び出す準備ができました。このスクリプトは複数のパラメータを取ります。-v でバージョンを指定、-e でEnterprise Editionを作成することを指示、 -p でDBAアカウントのパスワードを指定します。Dockerは root で動作するため、Dockerデーモンと通信するためにroot権限が必要です。 oracle ユーザーは既にsudoersに含まれているため、 sudo でroot権限で実行することができます。
[oracle@localhost 12.1.0.2]$ cd ..
[oracle@localhost dockerfiles]$ sudo ./buildDockerImage.sh -v 12.1.0.2 -e -p LetsDocker
[sudo] password for oracle:
Checking if required packages are present and valid...
linuxamd64_12102_database_1of2.zip: OK
linuxamd64_12102_database_2of2.zip: OK
=====================
Building image 'oracle/database:12.1.0.2-ee' ...
Sending build context to Docker daemon 2.688 GB
Step 1 : FROM oraclelinux:latest
latest: Pulling from library/oraclelinux
10ec637c060c: Pull complete
Digest: sha256:583f9e880f9228894555775c720d32eb22bf09cd13009c036d8f19b3257ccb41
Status: Downloaded newer image for oraclelinux:latest
...
...
...
Step 27 : CMD $ORACLE_BASE/runOracle.sh
 ---> Running in f536fc46e81e
 ---> a31ab247296b
Removing intermediate container f536fc46e81e
Successfully built a31ab247296b

  Oracle Database Docker Image for 'ee' version 12.1.0.2 is ready to be extended:

    --> oracle/database:12.1.0.2-ee

  ORACLE PASSWORD (SYS, SYSTEM, PDBADMIN): LetsDocker

  Build completed in 1204 seconds.

[oracle@localhost dockerfiles]$

Starting and connecting to the Oracle Database in a Docker container

ビルドが成功すれば、Oracle DatabaseをDockerコンテナ内で開始、実行できます。 docker run コマンドに適切なパラメータを付けて呼び出すだけでOKです。重要なパラメータの一つに、コンテナ内部のポート番号を外部世界とマッピングする -p  があります。当然ながら、Dockerコンテナの外部からデータベースに接続するため、このパラメータを使う必要があります。別の有用なパラメータには --name があります。これを使うと、指定した名前で新たにDockerコンテナを作成することができます。このパラメータを使うと、自動生成されたIDや名前を使わずに指定した名前でコンテナを参照することができます。
[oracle@localhost dockerfiles]$ sudo docker run -p 1521:1521 --name gvenzl oracle/database:12.1.0.2-ee

LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 25-JUL-2016 17:23:07

Copyright (c) 1991, 2014, Oracle.  All rights reserved.

Starting /opt/oracle/product/12.1.0.2/dbhome_1/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 12.1.0.2.0 - Production
System parameter file is /opt/oracle/product/12.1.0.2/dbhome_1/network/admin/listener.ora
Log messages written to /opt/oracle/diag/tnslsnr/78c750640f31/listener/alert/log.xml
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 12.1.0.2.0 - Production
Start Date                25-JUL-2016 17:23:09
Uptime                    0 days 0 hr. 0 min. 0 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Default Service           ORCLCDB
Listener Parameter File   /opt/oracle/product/12.1.0.2/dbhome_1/network/admin/listener.ora
Listener Log File         /opt/oracle/diag/tnslsnr/78c750640f31/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
The listener supports no services
The command completed successfully

SQL*Plus: Release 12.1.0.2.0 Production on Mon Jul 25 17:23:09 2016

Copyright (c) 1982, 2014, Oracle.  All rights reserved.

Connected to an idle instance.

SQL> ORACLE instance started.

Total System Global Area 1610612736 bytes
Fixed Size            2924928 bytes
Variable Size          520097408 bytes
Database Buffers     1073741824 bytes
Redo Buffers           13848576 bytes
Database mounted.
Database opened.
SQL> Disconnected from Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
Mon Jul 25 17:23:23 2016
===========================================================
Dumping current patch information
===========================================================
No patches have been applied
===========================================================
Starting background process CJQ0
Mon Jul 25 17:23:23 2016
CJQ0 started with pid=29, OS id=194
Completed: ALTER DATABASE OPEN
Mon Jul 25 17:23:24 2016
db_recovery_file_dest_size of 4560 MB is 0.00% used. This is a
user-specified limit on the amount of space that will be used by this
database for recovery-related files, and does not reflect the amount of
space available in the underlying filesystem or ASM diskgroup.
利便性のため、コンテナ開始スクリプトはOracle Databaseを起動するだけでなく、Oracle Databaseのalert.logファイルを tail -f で表示します。これは簡単に潜在的な問題の目星を付けやすくするためです。コンテナが動作し、1521/tcpが外部世界にマッピングされているので、コンテナ内のデータベースに接続することができます。
[oracle@localhost ~]$ sql system/LetsDocker@//localhost:1521/ORCLPDB1

SQLcl: Release 4.2.0.16.175.1027 RC on Mon Jul 25 13:31:03 2016

Copyright (c) 1982, 2016, Oracle.  All rights reserved.

Last Successful login time: Mon Jul 25 2016 13:31:04 -04:00

Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options


SQL> grant connect, resource to gvenzl identified by supersecretpwd;

Grant succeeded.

SQL> conn gvenzl/supersecretpwd@//localhost:1521/ORCLPDB1
Connected.

Stopping the Oracle Database Docker container

Dockerコンテナを停止したい場合は、 docker stop コマンドを使って停止できます。このコマンドにコンテナ名を付けて呼び出すだけです。
[oracle@localhost ~]$ sudo docker stop gvenzl
gvenzl

Summary

これで、Dockerを使ってOracle Databaseをコンテナ化する方法のチュートリアルは終了です。OracleはOracle Databaseの他のEditionのビルドファイルも提供しており、手順は上述のものとほぼ同じですが、ビルドファイルに付属するREADME.mdを常に参照するよう心がけてください。
Oracle Database on Docker
https://github.com/oracle/docker-images/tree/master/OracleDatabase

2016年7月22日

[JavaScript, Database] Node-oracledb 1.10.1 Released to NPM

原文はこちら。
https://blogs.oracle.com/opal/entry/node_oracledb_1_10_1

node-oracledbのパッチリリースをGitHubとNPMでご利用いただけるようになりました。
oracledb - Oracle Database driver by Oracle Corp.
https://www.npmjs.com/package/oracledb
1.10.0に間に合わなかった修正も含まれています。REF CURSORのメモリリークのリグレッションも、予期せぬREF CURSOR障害の場合における、これまでにあったメモリリークと同様に修正されています。

node-oracledb 1.10.1での主要な変更点は以下の通りです。
  • JavaScriptからIN OUTバインドにnull値を渡せないという問題を修正しました。
  • 1.10で導入されたREF CURSORに伴うメモリリークを修正しました。
  • REF CURSORをフェッチする際にエラーが発生する場合、メモリリークしていた不具合を修正しました。
  • テスト・スィート用にMocha構成ファイルを追加
    テスト・スィートのREADMEで、テストの追加方法に関する手順を更新しました。
    Test node-oracledb
    https://github.com/oracle/node-oracledb/blob/master/test/README.md
    副作用として、テストは番号順に実行します。
内部機構の改良は変更履歴に記載があります。
Change Log
https://github.com/oracle/node-oracledb/blob/master/CHANGELOG.md

Resources

node-oracledbに関する問題や質問があれば、GitHubに投稿してください。みなさまからの投稿がadd-onに対する作業のスケジューリングの助けになります。よろしくお願いします。
node-oracledb : Issues
https://github.com/oracle/node-oracledb/issues
node-oracledbのインストール手順
https://github.com/oracle/node-oracledb/blob/master/INSTALL.md
node-oracledbのAPIとユーザードキュメント
https://github.com/oracle/node-oracledb/blob/master/doc/api.md

[JavaScript, Database] Node-oracledb 1.10 has Enhanced Metadata

原文はこちら。
https://blogs.oracle.com/opal/entry/node_oracledb_1_10_has

node-oracledb 1.10がご利用いただけるようになりました。変更点をご紹介します。
oracledb - Oracle Database driver by Oracle Corp
https://www.npmjs.com/package/oracledb
  • Leonardoからのプルリクエストのおかげで、メタデータのクエリが機能強化されました。
    extended metaData #386
    https://github.com/oracle/node-oracledb/pull/386
    Leonardo
    https://github.com/leolmi
    我々が引き継いで実装を微調整することを親切にも許してくれました。
    新しいboolean型の oracledb.extendedMetaData 属性もしくは対応するexecute() オプション属性の extendedMetaData がtrueの場合、クエリのための追加のメタデータとREF CURSOR列がmetaDataオブジェクトで利用可能です。
    extendedMetaData
    https://github.com/oracle/node-oracledb/blob/master/doc/api.md#propdbextendedmetadata
    extendedMetaData(execute() : Options)
    https://github.com/oracle/node-oracledb/blob/master/doc/api.md#propexecextendedmetadata
    例として、DEPARTMENTS表が以下のような場合を考えます。
    SQL> desc departments
     Name                                      Null?    Type
     ----------------------------------------- -------- ----------------------------
     DEPARTMENT_ID                             NOT NULL NUMBER(4)
     DEPARTMENT_NAME                           NOT NULL VARCHAR2(30)
     MANAGER_ID                                         NUMBER(6)
     LOCATION_ID                                        NUMBER(4)
    
    このとき、node-oracledbでのクエリでは以下のような拡張メタデータを返します。
    [ { name: 'DEPARTMENT_ID',
           fetchType: 2002,
           dbType: 2,
           precision: 4,
           scale: 0,
           nullable: false },
         { name: 'DEPARTMENT_NAME',
           fetchType: 2001,
           dbType: 1,
           byteSize: 30,
           nullable: false },
         { name: 'MANAGER_ID',
           fetchType: 2002,
           dbType: 2,
           precision: 6,
           scale: 0,
           nullable: true },
         { name: 'LOCATION_ID',
           fetchType: 2002,
           dbType: 2,
           precision: 4,
           scale: 0,
           nullable: true } ]
    利用可能な属性はデータベース型によって様々であることがわかります。属性の説明はmetaDataのドキュメントにあります。
    metaData
    https://github.com/oracle/node-oracledb/blob/master/doc/api.md#execmetadata
    extendedMetaDataの値にかかわらず、よく使われる列名は常にmetaDataで利用できます。これは以前のバージョンから変わりません。
    メタデータのdbType と fetchType という属性値はそれぞれ、新たなDB_TYPE_*  定数と既存のnode-oracledb型定数で表現されます。
    Oracle Database Type Constants
    https://github.com/oracle/node-oracledb/blob/master/doc/api.md#oracledbconstantsdbtype
    Node-oracledb Type Constants
    https://github.com/oracle/node-oracledb/blob/master/doc/api.md#oracledbconstantsnodbtype
    メタデータのタイプをチェックする際、みなさんのコードでこれらの定数を使っている必要があります。
  • 余分なメタデータをオプションにし、デフォルトでオフにしたり、データ型として文字列ではなく数字を利用したりしている理由は、一般的なユースケース、標準機能としてのエクスペリエンス、パフォーマンス、などについて議論を繰り返した結果です。
  • この機能強化の結果、みなさんのアプリケーションのメンテナンスが容易になり、より強力になると思っています。
  • LOBを伴うクエリ時にLOBデータがストリーミングされない場合に、ガベージコレクタがクリーンアップできない問題を解決しました。
  • 名前付きバインドオブジェクトを位置によるバインド(bind-by-position)コンテキストで使用した場合に、エラー(新しいエラーNJS-044)を返すようになりました。以前は、想定される属性が見つからず、バインド設定がデフォルトで最終的にデフォルトのままだったので、ORA-06502のようなエラーを返していました。引き続き、位置によるバインド(bind-by-position)で無名オブジェクトを使用することもできます。以下はその例です。
  • var sql = "begin myproc(:1, :2, :3); end;";
    var binds = [ id, name, { type: oracledb.STRING, dir: oracledb.BIND_OUT } ];
    
    3番目の配列要素が無名オブジェクトです。
  • 根底にあるResultSetがクローズされる前にQueryStreamインスタンスでエラーイベントが発生した場合の不具合を修正しました。ユーザがエラー・イベントハンドラで接続をクローズしようとした場合、ResultSetが接続クローズを妨げるため、問題が発生する可能性がありました。
  • getRows呼び出し中にエラーが発生した場合、QueryStreamインスタンスの基礎となるResultSetインスタンスでパブリックなcloseメソッドを呼び出したとき不具合を修正しました。QueryStreamインスタンスがtoQueryStreamメソッドを使ってResultSetインスタンスから生成されると、このパブリックなメソッドはエラーを送出します。Cレイヤーのcloseメソッドの呼び出しは直接呼び出されます。
  • Pool._logStats をアップデートし、プールが正しくない場合にコンソールへ表示するのではなく、エラーを送出するようにしました。
  • GitHub Issue and Pull Requestテンプレートを追加しました。
    GitHub Issue and PR templates
    https://github.com/oracle/node-oracledb/tree/master/.github
  • 新しいInstant Client 12.1リリースに対応した、OS Xへのインストール手順を更新しました。
  • AIX、Solaris x64に対応したインストール手順を追加しました。
  • 基礎となるDPIデータアクセス層に対する機能強化を実施しました。
    https://github.com/oracle/node-oracledb/tree/master/src/dpi
    この機能強化はnode-oracledbを使っていないDPIの利用者とともに実施しました。この変更によって、潜在的な、ユーザーに見える、node-oracledbの機能強化のための基礎が築かれます。
    • SYSDBA接続を許可します
    • セッションのタグ付けを許可します
    • 文字セットと各国文字セットをDPI総へのパラメータを使って指定します
    • (既存の均質なプールに加え)異種混在のプールをサポートします
    繰り返しになりますが、これらはnode-oracledbに公開されません。

Resources

node-oracledbに関する問題や質問があれば、GitHubに投稿してください。みなさまからの投稿がadd-onに対する作業のスケジューリングの助けになります。よろしくお願いします。
node-oracledb : Issues
https://github.com/oracle/node-oracledb/issues
node-oracledbのインストール手順
https://github.com/oracle/node-oracledb/blob/master/INSTALL.md
node-oracledbのドキュメント
https://github.com/oracle/node-oracledb/blob/master/doc/api.md

2016年7月20日

[Java] Inside JShell

原文はこちら。
https://blogs.oracle.com/java/jshell

Yoshida Shinya (吉田真也)さん(またの名をきつねさん、@bitter_fox)はJEP 222、JShell、別名project Kullaに関するOpenJDKのコミッタです。JDK 9のJshellを使うと、開発者は、Java 9の学習やテストが簡単になるシェルインターフェースであるread–eval–print loop (REPL)を使うことができるようになります。以下の動画で、吉田さんはJShellを使ってコードをテストする方法、JShell APIを別のツールと一緒に使う方法、彼が作成したJavaFX plug-in for JShellを説明しています。是非デモをご覧ください。

(訳注)
この動画はJava Day Tokyo 2016で収録されたものです。

[Security, Support] July 2016 Critical Patch Update Released

原文はこちら。
https://blogs.oracle.com/security/entry/july_2016_critical_patch_update

2016年7月19日(PDT)に、Oracleは2016年7月度のCritical Patch Updateをリリースしました。
Oracle Critical Patch Update Advisory - July 2016
http://www.oracle.com/technetwork/security-advisory/cpujul2016-2881720.html
このCritical Patch Updateでは、(Oracle Database Server、Oracle E-Business Suite、Oracle Industry Applications、Oracle Fusion Middleware、Oracle Sun Products、Oracle Java SE、Oracle MySQLなどの)幅広い製品群に対する修正を提供します。
OracleはこのCritical Patch Updateをできる限り早期に適用されることを推奨いたします。このCritical Patch Updateのサマリーや分析情報はMy Oracle Supportの以下のサポート文書として公開しています(ご覧いただくためにはサポート契約が必要です)。
July 2016 Critical Patch Update: Executive Summary and Analysis (Doc ID 2161607.1)
https://support.oracle.com/rs?type=doc&id=2161607.1

[Java] JDK 8u101, 8u102, 7u111, and 6u121 Released!

原文はこちら。
https://blogs.oracle.com/thejavatutorials/entry/jdk_8u101_8u102_7u111_and

JDK 8u101、8u102、7u111、6u121がご利用できるようになりました(7u111、6u121はサポート契約されているお客様のみ)。最新のJDKはJava SE Downloadページからダウンロードできます。
Java SE Downloads
http://www.oracle.com/technetwork/java/javase/downloads/index.html
このリリースでの機能強化、変更、修正点は、それぞれのリリースに対応するリリースノートをご覧下さい。
JDK 8u101 Release Notes
http://www.oracle.com/technetwork/java/javase/8u101-relnotes-3021761.html
JDK 8u102 Release Notes
http://www.oracle.com/technetwork/java/javase/8u102-relnotes-3021767.html
JDK 7u111 Release Notes
http://www.oracle.com/technetwork/java/javaseproducts/documentation/javase7supportreleasenotes-1601161.html#R170_111
JDK 6u121 Release Notes
http://www.oracle.com/technetwork/java/javase/overview-156328.html#R160_121
JDK 8u101には、ARM用JDK 8u101も含んでいます。この製品に関する情報は、Java™ Development Kit for ARM Release Notes 8 Update 101のページに記載があります。
Java™ Development Kit for ARM Release Notes 8 Update 101
http://www.oracle.com/technetwork/java/javase/8u101-arm-relnotes-3021773.html 
(訳注)
Critical Patch Updateの一環としてリリースされているため、JREのセキュリティベースラインが変更されています。ご利用のお客様はアップデートされることを推奨します。
  • [8] 1.8.0_101-b13
  • [7] 1.7.0_111-b13
  • [6] 1.6.0_121-b09
このリリースに含まれるセキュリティ修正は以下のページから確認できます。
Oracle Critical Patch Update Advisory - July 2016
Oracle Java SE Executive Summary
http://www.oracle.com/technetwork/security-advisory/cpujul2016-2881720.html#AppendixJAVA

2016年7月19日

[WLS] WebLogic Server 12.2.1.1.0 - Domain to Partition Conversion Tool (DPCT) Updates

原文はこちら。
https://blogs.oracle.com/WebLogicServer/entry/weblogic_server_12_2_1

Domain to Partition Conversion Tool (DPCT) はWebLogic Server(10.3.6、12.1.2、12.1.3、もしくは12.2.1)の既存ドメインをWebLogic Server 12.2.1ドメインのパーティションに移行するためのアシスタントツールです。
このDPCTは、独立した、しかしながら関連する2個の操作から構成されています。
  1. 既存のドメインを検査し、関連する構成やバイナリファイルを取り込んでアーカイブにエクスポートする。
  2. WebLogic Server 12.2.1で利用可能なパーティションへのインポートオプションを使って、エクスポートしたドメインのアーカイブをインポートし、新規パーティションを作成する。このパーティションには移行元からの構成リソースやアプリケーション・デプロイメントが含まれる。
    WebLogic Server 12.2.1.1.0リリースに伴い、DPCTの機能改善に伴うアップデートや変更がありました。アップデートされたドキュメントには、新機能、修正された不具合、既知の制限事項がまとめられています。
    Oracle® Fusion Middleware
    Using Oracle WebLogic Server Multitenant 12c (12.2.1.1.0)
    Migrating a WebLogic Server Domain to a Domain Partition
    https://docs.oracle.com/middleware/12211/wls/WLSMT/config_dpct.htm#WLSMT1695

    Key Updates

    a) WebLogic Server 12.2.1.1.0をインストールするとDPCTも配布されるようになりました
    当初DPCTは、OTNからのみダウンロードできる別のZipファイルとして配布されていましたが、12.2.1.1.0から、DPCTは製品インストールとともに配布されるようになっています。
    $ORACLE_HOME/wlserver/common/dpct/D-PCT-12.2.1.1.0.zip
    
    12.2.1.1.0のインストール環境からこのファイルを移行元ドメインのあるサーバへコピーし、展開して利用することができます。なお、DPCTはOTNからも依然としてダウンロードできます。
    Free Oracle WebLogic Server Installers for Development
    Domain To Partition Conversion Tool
    http://www.oracle.com/technetwork/middleware/weblogic/downloads/wls-for-dev-1703574.html

    b) 利用にあたってパッチ適用は不要です
    以前はDPCTを利用するにあたって、DPCTが生成したアーカイブをインポートするために移行先の12.2.1インストール環境にパッチを適用する必要がありましたが、この制限はなくなりました。

    c) プラットフォームサポートの改善
    Windows環境ではDPCT利用にあたって発生していた不具合は解決済みです。

    d) レポートの改善
    新しくなったレポートファイルは、エクスポートされた各ドメインに対して生成されます。移行元ドメインの詳細だけでなく、エクスポートされたアーカイブに取り込まれた構成リソースやデプロイメントの各々の詳細も列挙しますし、エクスポートできなかったリソースも記載されます。

    e) オーバーライド時に使うJSONファイルのフォーマット変更
    生成されたJSONファイルを使うと、インポート時に指定して移行先環境のカスタマイズを可能とするためのオーバーライド機構を提供します。このファイルの形式が正しく整形され、変更がより簡単、わかりやすくなりました。

    f) JSONオーバーライドファイルへのリソースの追加
    移行先ドメインに対するカスタマイズを支援するため、JDBCシステムリソース、SAFエージェント、メールセッション、JDBCストアといった追加のリソースを、生成されたJSONファイル内に構成可能なオブジェクトとして記述できるようになりました。

    g) 新しいexport-domainスクリプトの包含
    DPCT実行時に使うスクリプトを書き換え、新しいスクリプトとして追加しました。この新しいスクリプトはexport-domain.[cmd|sh]という名前で、ヘルプテキストがよりわかりやすく、スクリプトへの入力値に名前付きパラメータを利用できるようになりました。以前のスクリプトも後方互換のために提供しているので引き続き利用できますが、可能であれば新しいスクリプトを利用されることを推奨します。
    export-domain スクリプトの利用方法
    Usage: export-domain.sh -oh {ORACLE_HOME} -domainDir {WL_DOMAIN_HOME}
           [-keyFile {KEYFILE}] [-toolJarFile {TOOL_JAR}] [-appNames {APP_NAMES}]
            [-includeAppBits {INCLUDE_APP_BITS}] [-wlh {WL_HOME}]
           where:
                 {ORACLE_HOME} : the MW_HOME of where the WebLogic is installed
                 {WL_DOMAIN_HOME} : the source WebLogic domain path
                 {KEYFILE} : an optional user-provided file containing a clear-text passphrase used to encrypt exported attributes written to the archive, default: None;
                 {TOOL_JAR} : file path to the com.oracle.weblogic.management.tools.migration.jar file.
                 Optional if jar is in the same directory location as the export-domain.sh
                 {APP_NAMES} : applicationNames is an optional list of application names to export.
                 {WL_HOME} : an optional parameter giving the path of the weblogic server for version 10.3.6.Used only when the WebLogic Server from 10.3.6 release is installed under a directory other than {ORACLE_HOME}/wlserver_10.3

    Enhanced Cluster Topology and JMS Support

    上記に加え、エクスポート/インポート操作を再構築し、DPCTが数多くのWebLogic Serverの主要な機能をサポートするようになりました。
    移行元ドメインを検査してエクスポート・アーカイブを生成する際に、DPCTはリソースやデプロイメントのターゲットとして、移行先ドメインの適切なサーバやクラスタを指定できるようになりました。移行元ドメインの各サーバやクラスタに対し、対応するリソースグループオブジェクトが生成されたJSONファイルに作成されます。各リソースグループは専用の仮想ターゲットにターゲット指定されており、順に移行先ドメインのサーバやクラスタへターゲット指定できるようになっています。
    移行元のドメインにおける特定のWebLogic Serverインスタンスやクラスタをターゲット指定しているすべてのアプリケーション・デプロイメントとリソースは、移行先ドメインのリソースグループに対応します。
    この変更の結果、適切に新しい環境にマップできるようJSONファイルでターゲットを指定することによって、移行先ドメインが移行元のクラスタやサーバのリソースと異なる名前である状況であってもサポートできるようになりました。
    以前あった、シングルサーバおよびクラスタトポロジーでのJMS構成のエクスポートに関わる数多くの制限が解決済みですので、一般的なJMSのユースケースでDPCTを使った移行がサポートされるようになりました。ドキュメントには既存の既知の制限が列挙されています。

    2016年7月8日

    [Linux] Oracle Linux Kernel Developers at LinuxCon Japan

    原文はこちら。
    https://blogs.oracle.com/linuxkernel/entry/oracle_linux_kernel_developers_at

    Oracle Linuxのカーネル開発者が7月13日から15日にかけて開催されるLinuxCon Japanで講演します。
    LinuxCon Japan
    (英語)http://events.linuxfoundation.org/events/linuxcon-japan
    (日本語)http://events.linuxfoundation.jp/events/linuxcon-japan
    講演タイトルとスピーカーは以下の通りです。
    James Morrisは、他のカーネル開発者とならんで、Kernel Developer Panelにも参加予定です。

    2016年7月7日

    [Java] Putting Hypermedia Back in REST with JAX-RS

    原文はこちら。
    https://community.oracle.com/docs/DOC-998953

    あなたのJavaエンタープライズ・アプリケーションで本格的なハイパーメディアドリブンのREST APIを実装すると、変更に対してより柔軟性と弾力性が増します。よい副作用として、一つ一つのRESTリソースを文書化する必要性もなくなります。

    誰もがRESTにしています。少なくとも誰もがやっていると主張しています。しかし、ハイパーメディアを使わずにビルドされている場合を除き、発見できるほとんどのWeb APIは、「RPCスタイル」と「HTTPセマンティクスを持つ基本的なリソース」の間にあります。

    Real-World "REST" Examples

    多くの実プロジェクトでは、任意のHTTP APIのことを間違ってRESTfulと呼んでいます。Listing 1の例を見てみましょう。
    POST /doSomeAction
    <someActionRequest>
        <param>12345</param>
    </someActionRequest>
    
    200 OK
    <someActionResponse>
        <value>2345</value>
    </someActionResponse>
    
    Listing 1. RPC HTTP example (request and response)
    これらのHTTP呼び出しは、実際にはHTTPを使ってメソッドを呼び出しています。doSomeActionというURLはメソッド名で、POSTが全ての呼び出しで使われています(データの読み取りにおいてもです)。そしてリクエストおよびレスポンスのボディ部分は入出力パラメータです。
    これはSOAPエンベロープがないSOAP以外の何者でもないと結論付けることができます。

    Resources and HTTP Semantics


    REST APIのURLはアプリケーションのビジネス・エンティティを表しています。つまり、APIデザイン時には動詞ではなくオブジェクトの観点で検討する必要がある、ということです。
    以下はユーザー管理モジュールのために、ユーザーオブジェクトをHTTPで公開します(Listing 2)。
    GET /users
    200 OK

    <users>
        <user>
            <id>12345</id>
            <name>Duke</name>
            <motto>Java rocks!</motto>
        </user>
        <!-- some more users ... -->
    </users>
    
    Listing 2. Resources example (request and response)
    ここでの違いは、URLがビジネスオブジェクト(全ユーザーのリスト)を反映しており、正しいHTTPメソッドを使ってリソースを読み取る、というところです。
    クライアントが全ユーザーを読み取り、各ユーザーのリソースをフォローしたいという場合、URLの構築方法を知る必要があるでしょう。特定ユーザーのURLが/users/12345である場合、クライアントは暗黙のうちに一致するオブジェクトのIDを使って全ユーザーのURLを結合する必要があります。これはクライアントがサーバにのみ存在しているべきロジックと密に結合しています。
    一般的な誤解は、RESTがいささか予測可能なURLであるということです。実際には、読み込み可能なURLがあると便利ですが、より重要なのは、サーバーはURLの制御に留まり、積極的に必要なリソースにクライアントを導く、という事実です。これはどうやって実現できるのでしょうか。
    Listing 3は、リソースとHTTPセマンティクスを使ってユーザーを作成する例です。
    POST /users

    <user>
        <name>Duke</name>
        <motto>JAX-RS rocks!</motto>
    </user>
    
    201 Created
    Location: /users/12345
    Listing 3. Creating resources (request and response)
    サーバはリクエストに対してHTTPステータス201 Createdを返し、Locationヘッダー・フィールドには新規作成されたリソースのURLが含まれています。クライアントはこのURLを利用して特定のユーザーのリソースにアクセスします。これは、もはやURLがクライアント側で作成されないことを意味します。つまりサーバが再びURLを管理下に置いています。

    Enter Hypermedia


    関連するリソースにアクセスする方法はハイパーメディアを使って指示できます。
    リスト4に示すように、再びユーザ・リストの例を考えてみましょう。ただ今回はリソースのリンクを持っています。
    GET /users
    200 OK

    <users>
        <user>
            <name>Duke</name>
            <motto>Java rocks!</motto>
            <link rel="self" href="/users/12345"/>
        </user>
        <!-- some more users ... -->
    </users>
    
    Listing 4. Resources with links example (request and response)
    レスポンスにはもはやビジネスオブジェクトのIDは含まれておらず、対応するリソースへのリンクが含まれています。クライアントはアプリケーションの構造を事前に知らなくても、これらのリンクに従うことができますが、同一性だけを認知しておく必要があります。これはクライアントに対し、リンクそれ自身が、包含するオブジェクト(つまりユーザー)のリソースであることを伝えているのです。
    その結果、関係性だけを知った上で、リンクを使ってクライアントに全ての必要なロケーションへ指示します。あとはサーバー次第です。
    Listing 5は、別の局面でのリソースリンク・アプローチの例です。今回はブックストアの例をJSON形式で表現しています。
    GET /books/12345
    200 OK

    {
        "name": "Java",
        "author": "Duke",
        // + availability, price
        "_links": {
            "self": "/books/12345",
            "add-to-cart": "/shopping_cart"
        }
    }
    
    Listing 5. Resource with several links (request and response)
    リソースには同一性を示すリンクだけでなく、「ショッピングカートに入れる」機能にアクセスできるURLも含まれています。これがハイパーメディアを使用するメリットです。そのリンクは、ユーザーがカートに本を追加することができる場合にのみ含まれます。本を購入できる場所の例として書店を考えてみましょう。いくつかの前提条件に一致する場合にのみ、本をユーザーのショッピングカートに追加することができます。このビジネスロジック(例えば、在庫がある書籍のみを追加する)は、理想的には、冗長なロジックを防止するため、サーバー上にのみ存在します。
    (本の在庫がある場合のみ、ショッピングカートボタンを見せるという)ロジックをクライアントに複製せずに、ロジックが適用される場合にのみレスポンスのボディにサーバはadd-to-cartのリンクを含めます。クライアントはadd-to-cartの関係を知っているので、ファンシーなボタンを表示し、そのボタンがクリックされれば、そのURLにアクセスします。
    しかし、APIユーザーは、どのデータをadd-to-cartのURLに送信する必要がある、ということをどうやって知るのでしょうか。このアクションは、HTTPのGET呼び出しではなく、必要なデータ(例えば書籍ID、追加する書籍の個数、など)を伴ってPOST呼び出しをします。この情報を、文書化(つまり、そのURLにアクセスする方法の説明)、もしくは、より洗練されたハイパーメディア・アプローチを介して、APIに含める必要があります。
    様々なレベルの管理・制御を可能にするいくつかのハイパーメディアを意識したコンテンツ・タイプがあります。  M. AmundsenによるH Factorに関するエントリを参照ください。
    Hypermedia Types > H factor
    http://amundsen.com/hypermedia/hfactor/
    あるハイパーメディアを意識したコンテンツ・タイプにSirenがあります。これを使うと、リンクを定義できるだけでなく、いわゆるアクションも定義できます。シンプルなGET呼び出しを使う以外の方法でリソースへアクセスする方法を示します。
    Siren: a hypermedia specification for representing entities
    https://github.com/kevinswiber/siren
    Listing 6はリンクとアクションを持つ書籍の例です。
    GET /books/12345
    200 OK

    {
        "class": [ "book" ],
        "properties": {
            "isbn": "1-1234-5678",
            "name": "Java",
            "author": "Duke",
            "availability": "IN_STOCK",
            "price": 29.99
        },
        "actions": [
            {
                "name": "add-to-cart",
                "title": "Add Book to cart",
                "method": "POST",
                "href": "http://api.jamazon.example.com/shopping_cart",
                "type": "application/json",
                "fields": [
                    { "name": "isbn", "type": "text" },
                    { "name": "quantity", "type": "number" }
                ]
            }
        ],
        "links": [
            { "rel": [ "self" ], "href": "http://api.jamazon.example.com/books/1234" }
        ]
    }
    
    Listing 6. Siren book resource example (request and response)
    クライアントはadd-to-cart機能を呼び出すためのあらゆる必要な情報、これにはURL、HTTPメソッド、Content-type、あらゆる必要なコンテントデータが含まれますが、これらをJSONプロパティの形式で受け取ります。ISBNと個数のフィールドの情報の出所だけは、知っておく必要があります。これはクライアント上に存在する必要があるビジネス・ロジックであることは明らかです。
    その結果、クライアントは、アプリケーションのドメイン・モデル以外の前提知識を持たなくても、自己探索方式でAPIを使用してナビゲートすることができます。「利用方法」の情報はAPI自身に焼き付けてあるので、多くのドキュメントをここに保存することができます。
    それに加えて、ハイパーメディアを使用した場合には、API変更に対してより高い柔軟性を持たせることができ、クライアントは対応することができます。
    一般的には、APIが大きくなり、利用するクライアントの種類が増えれば増えるほど、REST APIをハイパーメディア駆動にすることはますます理に適います。

    Enter Java EE

    JAX-RSはJava EEでRESTful Webサービスを開発するための標準です。
    Listings 7と8では、(Listing 5で示した)HTTP呼び出しを処理するJAX-RSリソースクラスとアノテーションが付いたPOJOを示しています。
    @Path("books")
    @Produces(MediaType.APPLICATION_JSON)
    public class BooksResource {
    
        @Inject
        BookStore bookStore;
    
        @Context
        UriInfo uriInfo;
    
        @GET
        public List<Book> getBooks() {
            final List<Book> books = bookStore.getBooks();
    
            books.stream().forEach(u -> {
                final URI selfUri = uriInfo.getBaseUriBuilder().path(BooksResource.class).path(BooksResource.class, "getBook").build(u.getId());
                u.getLinks().put("self", selfUri);
            });
    
            return books;
        }
    
        @GET
        @Path("{id}")
        public Book getBook(@PathParam("id") final long id) {
            final Book book = bookStore.getBook(id);
    
            final URI selfUri = uriInfo.getBaseUriBuilder().path(BooksResource.class).path(BooksResource.class, "getBook").build(book.getId());
            book.getLinks().put("self", selfUri);
    
            // check if business logic applies
            if (bookStore.isAddToCartAllowed(book)) {
                final URI addToCartUri = uriInfo.getBaseUriBuilder().path(CartResource.class).build();
                book.getLinks().put("add-to-cart", addToCartUri);
            }
            return book;
        }
    }
    
    Listing 7. JAX-RS resource class
    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Book {
    
        @XmlTransient
        private long id;
        private String name;
        private String author;
    
        @XmlElement(name = "_links")
        private Map<String, URI> links = new HashMap<>();
    
        // getters & setters
    }
    
    Listing 8. Book example POJO
    getBooksリソース・ハンドラは、BookStore ManagedBeanを呼び出して、対応するURIを付加し、クライアントに返す本を取得します。注意いただきたいのは、Content-typeがapplication/jsonであっても、JAXB(Java Architecture for XML Binding)アノテーションを使って、JSON出力にJavaオブジェクトをマッピングできる、ということです。アプリケーションサーバに同梱されている主要なJSONマッピングフレームワークもまた、JAXBアノテーションを考慮します。
    JAX-RSのUriInfo機能を使って、JAX-RSクラスから直接得た情報を使ってURIをプログラムで作成します。pathメソッドは@Pathアノテーションのpathの部分を連結します。getBookメソッドには、書籍の実際のIDで置換する必要があるパス・パラメーターが含まれています。これは、対応する引数を使ってbuildmethodを呼び出すことによって行われます。
    UrlInfoコンポーネントのもう一つの有用な機能は、getBaseUriBuilderというビルダーです。これは与えられたHTTPリクエストに従って、プロトコル、ホスト、ポートを作成します。アプリケーションサーバが例えばApacheやnginxの背後にある場合、元のHTTPリクエストのリクエストプロトコル、ホストやポート、つまりはプロキシサーバのベースURLを使ってURIを作成します。これはJAX-RSの標準機能であり、設定作業とJava EEアプリケーションをITランドスケープとの密結合を最小限にとどめることができます。
    getBookリソースハンドラは、基本的には1個の書籍のためにのみ同じことをします。そしてビジネスロジックが一致した場合、このリソースハンドラはadd-to-cartリンクも含みます。これが、ハイパーメディアを使ってクライアントの挙動を制御する方法の一例です。

    Listing 9および10は、与えられた例における可能性のあるレスポンスです。
    GET /hypermedia-test/resources/books
    200 OK

    [
      {
        "name": "Java",
        "author": "Duke",
        "_links": {
          "self": "http://localhost:8080/hypermedia-test/resources/books/1"
        }
      },
      {
        "name": "Hello",
        "author": "World",
        "_links": {
          "self": "http://localhost:8080/hypermedia-test/resources/books/2"
        }
      }
    ]
    
    Listing 9. Books resource example
    GET /hypermedia-test/resources/books/1
    200 OK

    {
      "name": "Java",
      "author": "Duke",
      "_links": {
        "self": "http://localhost:8080/hypermedia-test/resources/books/1",
        "add-to-cart": "http://localhost:8080/hypermedia-test/resources/shopping_cart"
      }
    }
    
    Listing 10. Book resource example
    Sirenなどのコンテント・タイプを使ったより洗練された例は、レスポンスにより多くの情報を必要とします。Siren4Jのようなライブラリには、所望のハイパーメディア・コンテント・タイプでレスポンスを作成する機能があります。
    Java library for the Siren Hypermedia Type Specification
    https://github.com/eserating/siren4j/
    しかしながら、外部ライブラリを使って依存性を増やさず、できる限り生成されるデプロイメントアーティファクトのサイズを小さくするため、ふつうのJava EE 7の機能を使う方法をご紹介しましょう。これはつまり、コンテント・タイプに応じてフィールドを含む独自のJavaクラスを作成する、もしくはプログラム的なアプローチを使う、ということを意味します。JSON-Pは、最大限JSONの構造をプログラムで作成できる機能を提供します。
    JSR 353: JavaTM API for JSON Processing
    https://jcp.org/en/jsr/detail?id=353
    Listing 11は、bookリソースのレスポンスをJSON-Pを使い、プログラムで作成する例です。
    @GET
    public JsonArray getBooks() {
        return bookStore.getBooks().stream().map(b -> {
            final URI selfUri = uriInfo.getBaseUriBuilder().path(BooksResource.class).path(BooksResource.class, "getBook").build(b.getId());
            final JsonObject linksJson = Json.createObjectBuilder().add("self", selfUri.toString()).build();
            return Json.createObjectBuilder()
                    .add("name", b.getName())
                    .add("author", b.getAuthor())
                    .add("_links", linksJson).build();
        }).collect(Json::createArrayBuilder, JsonArrayBuilder::add, JsonArrayBuilder::add).build();
    }
    
    @GET
    @Path("{id}")
    public JsonObject getBook(@PathParam("id") final long id) {
        final Book book = bookStore.getBook(id);
    
        final URI selfUri = uriInfo.getBaseUriBuilder().path(BooksResource.class).path(BooksResource.class, "getBook").build(book.getId());
        final JsonObjectBuilder linksJson = Json.createObjectBuilder().add("self", selfUri.toString());
    
        if (bookStore.isAddToCartAllowed(book)) {
            final URI addToCartUri = uriInfo.getBaseUriBuilder().path(CartResource.class).build();
            linksJson.add("add-to-cart", addToCartUri.toString());
        }
    
        return Json.createObjectBuilder()
                .add("name", book.getName())
                .add("author", book.getAuthor())
                .add("_links", linksJson).build();
    }
    
    Listing 11. Book resource example using JSONP
    StreamsやLambda式、メソッドハンドルといったJava 8の言語機能を使って、取得されたPOJOのJsonObjectsとJsonArraysをプログラムで作成しています。このアプローチを使うと、開発者はレスポンスの構造や利用するコンテント・タイプを完全に管理することができます。
    実プロジェクトでは、ビジネス・オブジェクトをリンクやアクションを含むハイパーメディア・レスポンスにマッピングするためのこの機能は、Contexts and Dependency Injection (CDI) Managed Beanのような単独のコンポーネントに分割され、プロジェクト内の全てのRESTリソースクラスで再利用されることでしょう。
    完全なサンプルは、以下のリンクからどうぞ。
    Hypermedia with JAX-RS
    https://github.com/sdaschner/jaxrs-hypermedia
    サンプルには、リソースのリンクだけを含むハイパーメディアAPIを作成する方法や、様々なアプローチを使い、アクションを含める方法(Sirenを使って実現しています)が含まれています。

    Conclusion


    Java EE 7アプリケーションでハイパーメディア・ドリブンのREST APIを作成するために必要なものを全てご紹介しました。
    どのレベルのハイパーメディアを適用することが理に適っているのか、どのHTTPコンテント・タイプを使うべきか、レスポンスを作成するにあたって、ふつうのJava EE 7のアプローチに比べて、3rdパーティの依存性(ライブラリ)を利用することは妥当なのかどうか、ということを設計するにあたり選択することが最も重要です。

    See Also

    About the Author


    Sebastian DaschnerはフリーランスのJavaコンサルタント、ソフトウェア開発者、アーキテクトです。プログラミングやJava EEのエンスージアストであり、JCPへ参加し、JSR 370 Expert Group (JSR 370: JavaTM API for RESTful Web Services (JAX-RS 2.1) Specification)のメンバーです。また、GitHubで様々なオープンソースプロジェクトのハッキングをしています。6年以上Javaに関わってきました。Javaのほかに、LinuxやDockerのようなコンテナ技術のヘビーユーザーでもあります。自身のブログTwitterでコンピュータ・サイエンスのプラクティスを啓蒙しています。

    2016年7月3日

    [Java, JavaScript] Java source name pattern checker with a nashorn script

    原文はこちら。
    https://blogs.oracle.com/sundararajan/entry/java_source_name_pattern_checker

    Ken Fogel(@omniprof)が先日以下のようなTweetをしていました。

    IDEによるソリューションはないのですが、以下のNashornスクリプトをカスタマイズして、Javaソースコード中のクラスやメソッド、変数名のパターンをチェックすることができます。このスクリプトはJava Tree APIを使ってJavaソースコードを解析しています。
    Compiler Tree API
    https://docs.oracle.com/javase/8/docs/jdk/api/javac/tree/
    その後、TreeScannerサブクラスをスクリプト内で利用してcheckXYZメソッドを呼び出し、クラスやメソッド、変数名をチェックします。checkXYZNameがfalseを返すと、このスクリプトは標準出力にソースのファイル名、行番号、列番号を表示します。
    おそらくこのスクリプトをカスタマイズして学生のソースを評価するのに使うことができるかもしれません。
    /*
     * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     *   - Redistributions of source code must retain the above copyright
     *     notice, this list of conditions and the following disclaimer.
     *
     *   - Redistributions in binary form must reproduce the above copyright
     *     notice, this list of conditions and the following disclaimer in the
     *     documentation and/or other materials provided with the distribution.
     *
     *   - Neither the name of Oracle nor the names of its
     *     contributors may be used to endorse or promote products derived
     *     from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    // Usage: jjs checknames.js -- <file-or-directory>
    
    if (arguments.length == 0) {
        print("Usage: jjs checknames.js -- <file-or-directory>");
        exit(1);
    }
    
    // Java types used
    var File = Java.type("java.io.File");
    var Files = Java.type("java.nio.file.Files");
    var StringArray = Java.type("java.lang.String[]");
    var ToolProvider = Java.type("javax.tools.ToolProvider");
    var Tree = Java.type("com.sun.source.tree.Tree");
    var Trees = Java.type("com.sun.source.util.Trees");
    var TreeScanner = Java.type("com.sun.source.util.TreeScanner");
    
    // customize these functions with checks that you'd want!
    function checkClassName(name) {
        return name.length < 3;
    }
    
    function checkMethodName(name) {
        return name.length < 3;
    }
    
    function checkVarName(name) {
        return name.length < 3;
    }
    
    function checkNames() {
        // get the system compiler tool
        var compiler = ToolProvider.systemJavaCompiler;
        // get standard file manager
        var fileMgr = compiler.getStandardFileManager(null, null, null);
        // Using Java.to convert script array (arguments) to a Java String[]
        var compUnits = fileMgr.getJavaFileObjects(Java.to(arguments, StringArray));
        // create a new compilation task
        var task = compiler.getTask(null, fileMgr, null, null, null, compUnits);
        var sourcePositions = Trees.instance(task).sourcePositions;
        // subclass SimpleTreeVisitor
        var NameChecker = Java.extend(TreeScanner);
    
        var visitor = new NameChecker() {
            report: function(node) {
                var pos = sourcePositions.getStartPosition(this.compUnit, node);
                var line = this.lineMap.getLineNumber(pos);
                var col = this.lineMap.getColumnNumber(pos);
                print("Too short name: " + node.name + " @ " + this.fileName + ":" + line + ":" + col);
            },
    
            // override to capture information on current compilation unit
            visitCompilationUnit: function(compUnit, p) {
                this.compUnit = compUnit;
                this.lineMap = compUnit.lineMap;
                this.fileName = compUnit.sourceFile.name;
    
                return Java.super(visitor).visitCompilationUnit(compUnit, p);
            },
    
            // override to check class name
            visitClass: function(node, p) {
                if (checkClassName(node.simpleName.toString())) {
                    this.report(node);
                }
    
                return Java.super(visitor).visitClass(node, p);
            },
    
            // override to check method name
            visitMethod: function(node, p) {
                if (checkMethodName(node.name.toString())) {
                    this.report(node);
                }
    
                return Java.super(visitor).visitMethod(node, p);
            },
    
            // override to check variable name
            visitVariable: function(node, p) {
                if (checkVarName(node.name.toString())) {
                    this.report(node);
                }
    
                return Java.super(visitor).visitVariable(node, p);
            }
        }
    
        for each (var cu in task.parse()) {
            cu.accept(visitor, null);
        }
    }
    
    // for each ".java" file in directory (recursively).
    function main(dir) {
        var totalCount = 0;
        Files.walk(dir.toPath()).
          forEach(function(p) {
              var name = p.toFile().absolutePath;
              if (name.endsWith(".java")) {
                  checkNames(p);
              }
          });
    }
    
    main(new File(arguments[0]));
    

    2016年7月1日

    [WLS] Connection Initialization Callback on WLS Datasource

    原文はこちら。
    https://blogs.oracle.com/WebLogicServer/entry/connection_initialization_callback_on_wls

    WebLogic Server 12.2.1.1がダウンロードできるようになりました。一般提供の発表に関するエントリは以下をどうぞ。
    Oracle WebLogic Server 12.2.1.1 is Now Available
    https://blogs.oracle.com/WebLogicServer/entry/oracle_weblogic_server_12_22https://orablogs-jp.blogspot.jp/2016/06/oracle-weblogic-server-12211-is-now.html
    One of the WebLogic Serverデータソースの機能の一つで、接続初期化中に呼び出されるコールバックを定義することができます。ただ、登場して長いにもかかわらずあまり取り上げられませんでした。コールバックの当初の目的は、Application Continuity (AC) 機能と共に使われるメカニズムを提供することでした。これを使うと、接続が予約されていたり、後ほど接続を再生する場合、アプリケーションにとって同じ接続初期化を保証することができる、というものです。後者の場合、元の接続に「リカバリ可能」なエラーがあって閉じられ、その陰で新規接続が予約され、元の接続に対してなされた操作の全てが新規接続で再生されます。コールバックを使うと、アプリケーションが必要とする任意の状態を使って再度接続を初期化することができます。

    アプリケーションソフトウェア内でgetConnection()を呼び出した任意の箇所にこの処理を散乱させずに、コールバックを使って全ての接続を初期化することができるというこのコンセプトは、再生を使わなかったとしても非常に便利です。実際には、コールバックをデータソース記述子で構成することができるので(この方法をお薦めします)、コールバックを記述する以外にアプリケーションへの変更はありません。

    以下でこの機能のサポートの歴史をまとめました。接続の初期化コールバックを設定している前提で、以下をサポートしていました。
    WLS Version Description
    10.3.6 リプレイドライバを使って実行する場合にActiv GridLinkデータソースでのみ呼び出される(リプレイはActive GridLink for RACでのみサポート)
    12.1.1/12.1.2/12.1.3 リプレイドライバと任意のデータソースタイプを使っている場合に呼び出される(リプレイのサポートが汎用データソースにも追加されたため)
    12.2.1 Oracleドライバと任意のデータソースタイプを使って呼び出される
    12.2.1.1 任意のドライバ、任意のデータソースタイプを使って呼び出される。Oracleドライバだけに制限する理由はないですね。
    Javaコード中でデータソースにコールバックを登録することで、アプリケーションにコールバックを構成することができますが、データソース毎にこれを1回だけ実施する必要があります。データソース構成で登録するほうがずっと簡単だと思います。

    以下はコールバックのサンプルです。
    package demo;
    import oracle.ucp.jdbc.ConnectionInitializationCallback;
    
    public class MyConnectionInitializationCallback implements
      ConnectionInitializationCallback { 
      public MyConnectionInitializationCallback()  { 
      }
      public void initialize(java.sql.Connection connection)
        throws java.sql.SQLException {
         // Re-set the state for the connection, if necessary
      }
    }
    
    以下は、できるだけデフォルトのものを使って登録しているコールバックを表示する、シンプルなJythonスクリプトです。
    import sys, socket
    hostname = socket.gethostname()
    connect("weblogic","welcome1","t3://"+hostname+":7001")
    edit()
    dsname='myds'
    jndiName='myds'
    server='myserver'
    cd('Servers/'+server)
    target=cmo
    cd('../..')
    startEdit()
    jdbcSR = create(dsname, 'JDBCSystemResource')
    jdbcResource = jdbcSR.getJDBCResource()
    jdbcResource.setName(dsname)
    dsParams = jdbcResource.getJDBCDataSourceParams()
    dsParams.addJNDIName(jndiName)
    driverParams = jdbcResource.getJDBCDriverParams()
    driverParams.setUrl('jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=dbhost)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=otrade)))')
    driverParams.setDriverName('oracle.jdbc.OracleDriver')
    driverParams.setPassword('tiger')
    driverProperties = driverParams.getProperties()
    userprop = driverProperties.createProperty('user')
    userprop.setValue('scott')
    oracleParams = jdbcResource.getJDBCOracleParams()
    oracleParams.setConnectionInitializationCallback('demo.MyConnectionInitializationCallback')  # register the callback
    jdbcSR.addTarget(target)
    save()
    activate(block='true')
    
    ここではいくつか注目すべき点があります。まず、構成を使用してコールバックを登録するには、クラスがクラスパスになければなりません。とにかく、実行するには、サーバーのクラスパスにある必要がありますが、設定のために早く取得する必要があります。第二に、この機能の経緯から、接続パラメータではなくOracleのパラメータに設定が含まれています。そのため、我々は構成できることはそれほど多くありません。(Oracleタブに加えて)以下の図に示すように、WebLogic Server 12.2.1.1管理コンソールでは、[接続プール]の詳細パラメータでエントリを確認し、設定することができます。最後に、インタフェースはユニバーサル接続プール(UCP)インターフェイスであることにご注意ください。このコールバックをUCPアプリケーションで共有することができます(全てのドライバタイプをDatabase 12.1.0.2以降でサポートしています)。

    この機能は管理ガイドのApplication Continuityの章に記載があります。
    Oracle® Fusion Middleware Administering JDBC Data Sources for Oracle WebLogic Server 12c (12.2.1.1)
    Advanced Configurations for Oracle Drivers and Databases
    Application Continuity > Configuring Application Continuity > Using a Connection Callback
    http://docs.oracle.com/middleware/12211/wls/JDBCA/ds_oracledriver.htm#CCHFJDHF
    このエントリでは、コールバックを使って実際に何もしなかったことに失望されているかもしれませんが、次回のエントリで、別の新しいWLS12.2.1.1の機能でどのように使われているかを示すために再びこのコールバックを使用する予定です。