<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>技術ブログ &#124; 株式会社クラウディア</title>
	<atom:link href="https://cloudear.jp/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>https://cloudear.jp/blog</link>
	<description>クラウド専門の業務システム・社内ツール開発</description>
	<lastBuildDate>Fri, 12 Nov 2021 05:00:35 +0000</lastBuildDate>
	<language>ja</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.0.1</generator>
	<item>
		<title>Ruby on Rails 導入方法【初級編】</title>
		<link>https://cloudear.jp/blog/?p=2282</link>
		<comments>https://cloudear.jp/blog/?p=2282#comments</comments>
		<pubDate>Fri, 25 Nov 2016 09:25:08 +0000</pubDate>
		<dc:creator><![CDATA[yusuke]]></dc:creator>
				<category><![CDATA[未分類]]></category>

		<guid isPermaLink="false">https://cloudear.jp/blog/?p=2282</guid>
		<description><![CDATA[yusukeです。ruby編に引き続き、Railsの初級編を行いたいと思います。  Rubyのインストール  Bundlerのインストール  Railsのインストール 1 Rubyのインストール ruby編では、Clou [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>yusukeです。ruby編に引き続き、Railsの初級編を行いたいと思います。</p>
<ol>
<li> Rubyのインストール</li>
<li> Bundlerのインストール</li>
<li> Railsのインストール</li>
</ol>
<p><span id="more-2282"></span></p>
<p><span style="font-size: 14pt">1 Rubyのインストール</span></p>
<p>ruby編では、Cloud9というオンラインIDEサービスを使いましたが、今回はMacの環境でrubyのインストールからrails構築まで行います。rubyのインストールにはrbenvとruby-buildを使います。rbenvはrubyのバージョンを切り替えるために便利なツールです。複数のバージョンを管理してくれます。rubyのバージョンが違うプロジェクトを複数担当することもあるので、このツールで切り替えができると便利です。ruby-buildはrbenvのプラグインでrubyをインストールする際に使います。</p>
<p>rbenvをインストールする方法は２通ります。</p>
<p>最新バージョンを使いたいなら、githubからインストールします。<br />
簡単にインストールしたいなら、homebrewからインストールします。<a href="https://github.com/rbenv/rbenv#basic-github-checkout">github</a>にて２つのインストール方法が記載されています。以下の手順はhomebrewを使うインストールです。1.1 homebrewでのインストール<br />
まずはそのhomebrewのインストールを行います。<br />
前提として以下の２つが必要となります。<br />
①Javaのインストール<br />
②Xcode Command Line Toolsのインストール<br />
上記が終わったら<br />
<a href="http://brew.sh/">homebrew公式</a><br />
に書かれているように、（HPの記載が変更になっている場合もあるので注意）<br />
<code>コマンドプロンプトにて<br />
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"<br />
</code><br />
をコマンドプロンプトにて実行します。<br />
El Capitanの場合、/usr/localのパーミッション関係でエラーが起こることがるので、パーミッションの変更を行ってください。homebrewをインストールしたら、rbenvのインストールを行います。</p>
<div class="code-frame">
<div class="highlight">
<pre>$ brew install rbenv ruby-build
</pre>
</div>
</div>
<div class="code-frame">
<div class="highlight">
<pre>$ echo 'eval "$(rbenv init -)"' &gt;&gt; ~/.bash_profile
$ source ~/.bash_profile
</pre>
</div>
</div>
<p>rbenvのバージョン確認をします。</p>
<pre>rbenv -v
</pre>
<p>次にrbenvを使ってインストールできるrubyのバージョンを表示します。</p>
<pre>rbenv install -l
</pre>
<p>上記のコマンドでバージョンが複数表示されるので、使いたいバージョンを指定して<br />
rbenv install　コマンドを使い、rubyをインストールします。今回は2.2.2を指定しました。</p>
<div class="code-frame">
<div class="highlight">
<pre class="">rbenv install 2.2.2</pre>
</div>
</div>
<p>以上でhomebrewでのrubyインストールは終了です。次の章のBundlerインストールを行ってください。</p>
<h4><span id="以下はgithubを用いたインストール" class="fragment"></span>以下はgithubを用いたインストール</h4>
<p>1.2 githubでのインストール<br />
rbenvインストール。<br />
<code></code></p>
<pre>$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ cd ~/.rbenv &amp;&amp; src/configure &amp;&amp; make -C src
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' &gt;&gt; ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' &gt;&gt; ~/.bash_profile
$~/.rbenv/bin/rbenv init
</pre>
<p>これでrbenvが使えます。</p>
<p>次はruby-buildをインストールします。<br />
<code><br />
$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build<br />
</code></p>
<p>rbenvのバージョン確認をします。</p>
<pre>rbenv -v
</pre>
<p>次にrbenvを使ってインストールできるrubyのバージョンを表示します。</p>
<pre>rbenv install -l
</pre>
<p>上記のコマンドでバージョンが複数表示されるので、使いたいバージョンを指定して<br />
rbenv install　コマンドを使い、rubyをインストールします。今回は2.2.2を指定しました。</p>
<div class="code-frame">
<div class="highlight">
<pre class="">rbenv install 2.2.2</pre>
</div>
</div>
<p>以上でgithubでのrubyインストールは終了です。次の章のBundlerインストールを行ってください。<br />
<span style="font-size: 14pt">2 Bundlerのインストール</span><br />
rubyのインストールの次はBundlerのインストールです。BundlerとはGemのバージョンや依存関係を管理してくれます。。Gemとはrubyのライブラリのことです。インストールの手順は以下です。</p>
<div class="code-frame">
<div class="highlight">
<pre class="">$ rbenv exec gem install bundler</pre>
<p>下記はrubyのバージョンやGemをインストールした際に実行します。rbenvで管理しているバージョンでGemが使えるようになります。</p>
<pre>$ rbenv rehash</pre>
<p>バージョン確認をします。</p>
<pre>$ bundler -v
</pre>
<p>rbenv execが冒頭についているのは、rbenvで管理しているruby環境で確実にコマンドが実行されるようにするためです。以上でBundlerのインストールは終了です。次はいよいよRailsのインストールになります。</p>
</div>
</div>
<p><span style="font-size: 14pt">3 Railsのインストール</span></p>
<p>今回は新規アプリケーションを作成する場合を説明したいと思います。Bundlerを使ってRailsをインストールすると複数のプロジェクトに関わっている際にプロジェクト間のGemのバージョンの差異に悩まなくて良くなります。（下記のbundler insatallの項目を参照）<br />
①新規アプリケーションを作成する場合<br />
railsのプロジェクトフォルダを作成し、そこに移動し、</p>
<pre>$ mkdir ProjectDir
$  cd ProjectDir
</pre>
<p>下記コマンドでGemfileを作成し、そのファイルにrailsをインストールするように書きます。GemfileとはBundlerで使うGemのバージョンが指定されており、このファイルに従ってGemfile.lockを作成します。Gemfile.lockにはGemfileで書かれているGemと、それと依存関係にあるGemの名前やバージョンが記載されています。</p>
<pre>$ bundle init
</pre>
<p>Gemfileにインストール設定を記述します。ここではバージョン4.0.5を指定しています。</p>
<pre>$ echo 'gem "rails", "4.0.5"' &gt;&gt; Gemfile</pre>
<p>インストールコマンドを実行します。これによりvendor/bundle以下にRailsと関連するGemがインストールされます。このオプションを付けることでこのプロジェクト内だけにGemがインストールされます。</p>
<pre>$ bundle install --path vendor/bundle
</pre>
<p>これでrailsコマンドでアプリケーションを作成できるようになりました。以下のコマンドで作成しましょう。</p>
<pre>bundle exec rails new .</pre>
<p>Gemfileの上書きの確認をされたら許可してください。</p>
<p>アプリケーションが作成できたら以下のコマンドでサーバーを立ち上げましょう。</p>
<pre>bundle exec rails server</pre>
<p>ブラウザでhttp://localhost:3000にアクセスして、Railsの初期画面が表示されているか確認しましょう。<br />
これでRailsの導入は完了です。お疲れ様でした。</p>
]]></content:encoded>
			<wfw:commentRss>https://cloudear.jp/blog/?feed=rss2&#038;p=2282</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby 環境構築〜クラス作成まで【初級編】</title>
		<link>https://cloudear.jp/blog/?p=2164</link>
		<comments>https://cloudear.jp/blog/?p=2164#comments</comments>
		<pubDate>Fri, 25 Nov 2016 08:52:37 +0000</pubDate>
		<dc:creator><![CDATA[yusuke]]></dc:creator>
				<category><![CDATA[未分類]]></category>

		<guid isPermaLink="false">https://cloudear.jp/blog/?p=2164</guid>
		<description><![CDATA[はじめまして。yusukeと申します。Rubyについて技術ブログを書かせていただくことになりました。このブログを機にRubyを始めようと思ってくれると嬉しいです。では早速参りたいと思います。 目次 Ruby開発環境構築  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>はじめまして。yusukeと申します。Rubyについて技術ブログを書かせていただくことになりました。このブログを機にRubyを始めようと思ってくれると嬉しいです。では早速参りたいと思います。</p>
<p><span id="more-2164"></span></p>
<p><span style="font-size: 18pt"><strong>目次</strong></span></p>
<p><strong><em>Ruby開発環境構築</em></strong><br />
<em>1. オンラインIDE（Cloud9）</em><br />
<em>2. ローカル環境にインストールしたい場合</em></p>
<p><strong><em>Rubyを触ってみよう</em></strong><br />
<em>1. 変数と条件分岐</em><br />
<em>2. 繰り返し</em><br />
<em>3. メソッド</em><br />
<em>4. クラス</em></p>
<p>&nbsp;</p>
<p><span style="font-size: 14pt"><strong><span style="font-size: 18pt">開発環境構築</span><br />
</strong></span></p>
<p><strong> <span style="font-size: 12pt"> 1.　オンラインIDEサービス（Cloud9）</span></strong><br />
Cloud9とはオンラインIDE（統合開発環境）サービスです。小規模なアプリケーションの開発やデータベースなどをクラウド環境で利用できるサービスです。<br />
開発環境を整えるのは、プログラミングを学ぶ者にとって最初の難関となりますが、このサービスを使うと面倒な作業は必要ありません。すぐに始めたい人や、ローカル環境にインストールできなかった人はCloud9を使ってみましょう。<br />
<a title="Cloud9" href="https://c9.io/" target="_blank">Cloud9</a></p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2016/04/59c4a7e27a50903606f4422bccdebbe9.png"><img class="alignnone size-full wp-image-2189" src="https://cloudear.jp/blog/wp-content/uploads/2016/04/59c4a7e27a50903606f4422bccdebbe9.png" alt="スクリーンショット 2016-04-22 14.55.01のコピー" width="720" height="418" /></a></p>
<p>利用する手順は以下のとおりです。<br />
１，Cloud9で新規ユーザー登録します。Sign_upをクリックし、必要な情報を記入してください。(GithubやBitBitbucketとも連携しており、そのアカウントからもログインできます。)</p>
<p>2,登録完了後、ダッシュボードが表示されるので、「Create a new workspace」をクリック。以下の様な画面が表示されます。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2016/04/7f7ca923c466497be8a2bea58b04aef3.png"><img class="alignnone size-full wp-image-2190" src="https://cloudear.jp/blog/wp-content/uploads/2016/04/7f7ca923c466497be8a2bea58b04aef3.png" alt="スクリーンショット 2016-04-22 16.15.08のコピー" width="720" height="450" /></a></p>
<p>3,workspace名や公開設定を変更し、Blankテンプレートを選択。「create workspace」をクリック。<br />
※RailsテンプレートやRails_Tutorialテンプレートは今回は使用しません。<br />
※ターミナルで確認した所、BlankテンプレートはRailsは入っていませんが、Ruby(執筆時２．３)はインストールされています。<br />
４，作成したworkspaceが表示されれば、完了です。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2016/04/4090742393b9307a9f07ab43014ff074.png"><img class="alignnone size-full wp-image-2191" src="https://cloudear.jp/blog/wp-content/uploads/2016/04/4090742393b9307a9f07ab43014ff074.png" alt="スクリーンショット 2016-04-22 16.22.26のコピー" width="720" height="450" /></a></p>
<p>簡単ですね。これでクラウド環境でRubyが使えるようになりました。<br />
左に表示されているファイルツリーで右クリックして、フォルダやファイルを作成します。拡張子は「.rb」を使います。</p>
<p><strong><span style="font-size: 12pt">2．ローカル環境にインストールしたい場合</span></strong><br />
ローカルの環境にRubyをインストールする際には、公式サイトのドキュメントを利用すると良いでしょう。ここでは詳しいやり方は省略させていただきます。<br />
<a title="公式サイトのドキュメント" href="https://www.ruby-lang.org/ja/documentation/installation/" target="_blank">公式サイト</a></p>
<p>Windows向け<br />
公式サイトにあるようにWindowsにRubyをインストールする方法はいくつかあります。ソースからコンパイルしてインストール出来ない場合は、より簡単にインストールできるサードパーティ製のコンパイル済みのバイナリを使用すると良いでしょう。</p>
<p>Mac向け<br />
MacではRubyは標準コマンドとして利用することができますが、使用したいバージョンよりも古い可能性があります。<br />
自分で追加してインストールする場合、ソースからコンパイルしてインストールするか、パッケージ管理システムを利用してインストールするか選べます。</p>
<p>&nbsp;</p>
<p><span style="font-size: 18pt"><strong>Rubyを触ってみよう<br />
</strong></span><br />
<strong><span style="font-size: 12pt">1. 変数と条件分岐</span></strong><br />
まずは変数の使い方と条件分岐です。</p>
<pre class="theme:sublime-text lang:ruby decode:true " title="sample01.rb">#変数の定義
#名前
name01="田中"
name02="高橋"

#点数
a=60
b=80

#点数の平均を求める式
ave=(a+b)/2

#条件分岐　if構文
=begin
if 条件 then
  条件が成り立った時に実行する処理
else
  条件が成り立たなかった時に実行する処理
end
=end
if a&gt;b then
  max=a
  min=b
else
  max=b
  min=a
end

#コンソールに引数を出力する
print(name01,"さんの点数は",a,"点\n")
print(name02,"さんの点数は",b,"点\n")
print("二人の点数の平均は",ave,"点\n")
print("最高点は",max,"点\n")
print("最低点は",min,"点\n")


</pre>
<p>RubyではJavaと違い、変数の型定義を明示的に行いません。上記のようにそのまま変数に代入しています。<br />
Rubyでは文末に；（セミコロン）は使いません。改行を文の区切りとして捉えます。そのため、インデント（字下げ）を行い、まとまりを強調し見やすくします。<br />
条件分岐にif文を使います。thenを書き忘れないようにしてください。<br />
printメソッドは引数をコンソールに出力するメソッドです。複数の引数を扱う場合は「,」で区切ります。</p>
<p>ファイルを作成したら、画面下部のターミナルで、実行してみましょう。<br />
実行の仕方は「ruby ファイル名.rb」です。</p>
<pre class="theme:terminal lang:sh decode:true ">aiueo111:~/workspace $ ruby sample01.rb
田中さんの点数は60点
高橋さんの点数は80点
二人の点数の平均は70点
最高点は80点
最低点は60点</pre>
<p>&nbsp;</p>
<p><strong><span style="font-size: 12pt">2. 繰り返し</span></strong></p>
<pre class="theme:sublime-text lang:ruby decode:true" title="sample02.rb">##繰り返し　for構文
=begin
for 変数 in オブジェクト do
  繰り返す処理
end
=end
sum=0
for i in 1..5
  sum=sum+i
end
print sum,"\n"

#繰り返し while構文：
=begin
while 繰り返し続ける条件 do
  繰り返す処理
end
=end
i=1
while i&lt;4do
  print(i,"\n")
  i=i+1
end
#繰り返し timesメソッド
=begin
繰り返す回数.times do
  繰り返す処理
end
=end
2.times do
  print("２回繰り返します。\n")
end

</pre>
<pre class="theme:terminal lang:sh decode:true ">aiueo111:~/workspace $ ruby sample02.rb
15
1
2
3
２回繰り返します。
２回繰り返します。</pre>
<p>do~endをブロックと呼びます。ブロックの中に繰り返したい処理を書きます。<br />
この他にも繰り返しメソッドがあるので、興味がある方は調べてみてください。</p>
<p><strong><span style="font-size: 12pt"><br />
3. メソッド</span></strong></p>
<pre class="theme:sublime-text lang:ruby decode:true" title="sample03.rb">=begin
メソッド構文:
def メソッド名(引数１，引数２，・・・・)
　　実行したい処理
end
=end

#メソッド定義
#コンソールに引数を出力するメソッド
def test(name="Ruby",point=0)
  print(name,"さんの点数は",point,"点\n") #()省略可
end

#メソッド呼び出し。
test()
test("田中",60)
test("高橋",80)

#平均点を求めるメソッド
def average(point01=10,point02=0)
  ave=(point01+point02)/2  
  return ave   #return文は省略可
end

#平均点のメソッド呼び出し
print("平均点は",average(60,80),"点\n")

#最高点を求めるメソッド
def max(a,b)
  #return文は省略している
  if a&gt;b then
    max=a
  else
    max=b
  end
end
#最高点のメソッド呼び出し
print("最高点は",max(60,80),"点\n" )
</pre>
<p>name,point引数が空の状態でhelloメソッドが呼び出された時、メソッド定義部分で記載されている引数がデフォルトの値として代入されます。<br />
メソッドの中でreturn文を用いて返り値を指定できますが、省略することも可能です。省略した場合は、メソッドの中で最後に得られる値が返り値となります。</p>
<pre class="theme:terminal lang:sh decode:true ">aiueo111:~/workspace $ ruby sample03.rb
Rubyさんの点数は0点
田中さんの点数は60点
高橋さんの点数は80点
平均点は70点
最高点は80点</pre>
<p>&nbsp;</p>
<p><strong><span style="font-size: 12pt">4. クラス</span></strong></p>
<pre class="theme:sublime-text lang:ruby decode:true" title="sample04.rb">class EnglishTest
  #initializeメソッドは初期化のためのメソッド(Javaだとコンストラクタ)
  def initialize(name="Ruby",point=0)
    @name=name  #インスタンス変数に引数を代入
    @point=point
  end
  
  #ゲッター　参照のみ可能
  attr_reader :name,:point
  #セッター　変更のみ可能
  #attr_writer :name,:point
  #アクセスメソッド（参照、変更の両方を可能にする）
  #attr_accessor :name :point
  
  #インスタンスメソッド定義
  #コンソールに引数を出力するメソッド
  def test
   print(@name,"さんの点数は",@point,"点\n") #()省略可
  end
  
end
#オブジェクトの生成
ruby=EnglishTest.new
tanaka=EnglishTest.new("田中",60)
takahashi=EnglishTest.new("高橋",80)
#メソッド呼び出し
ruby.test
tanaka.test
takahashi.test
#ゲッターにより、nameやpointを参照できるようになる。
p tanaka.name
p takahashi.point</pre>
<p>クラスを使うことによって初期化メソッドのinitializeメソッドとインスタンス変数が使えるようになりました。<br />
initializeメソッドはオブジェクトが生成される際に呼ばれ、必要な初期化処理はここに記載します。ここでも引数がない状態でオブジェクト生成されるときは、デフォルトの値が呼ばれます。<br />
@で始まる変数はインスタンス変数と呼ばれ、同じインスタンス内であれば、他のメソッドからもその値を参照や変更ができます。<br />
ゲッターにより、他のインスタンスからnameとpointが呼び出せるようになりました。</p>
<pre class="theme:terminal lang:sh decode:true ">aiueo111:~/workspace $ ruby sample04.rb
Rubyさんの点数は0点
田中さんの点数は60点
高橋さんの点数は80点
"田中"
80</pre>
<p>&nbsp;</p>
<p><span style="font-size: 18pt"><strong>最後に</strong></span><br />
<span style="font-size: 10pt">だいぶ駆け足でRubyを紹介しましたが、いかがでしたでしょうか？わかりづらいところや、</span>もう少し詳しく書いて欲しい所があれば、コメントなどでいただけるとありがたいです。</p>
<p><span style="font-size: 10pt">今後もRubyの続きや新しくRailsの技術ブログも書く予定なので、気になる方はチェックしてみてください。</span></p>
]]></content:encoded>
			<wfw:commentRss>https://cloudear.jp/blog/?feed=rss2&#038;p=2164</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby モジュールと例外処理【応用編】</title>
		<link>https://cloudear.jp/blog/?p=2242</link>
		<comments>https://cloudear.jp/blog/?p=2242#comments</comments>
		<pubDate>Tue, 25 Oct 2016 11:42:39 +0000</pubDate>
		<dc:creator><![CDATA[yusuke]]></dc:creator>
				<category><![CDATA[雑談]]></category>

		<guid isPermaLink="false">https://cloudear.jp/blog/?p=2242</guid>
		<description><![CDATA[yusukeです。前回のRuby【初級編】の続きを書きたいと思います。 目次 クラス（クラスメソッドとクラス変数） 継承 モジュール 例外処理 前回はクラスを作り、インスタンスメソッドを使うところまでを記載しました。今回 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>yusukeです。前回のRuby【初級編】の続きを書きたいと思います。</p>
<p><span style="font-size: 18pt">目次</span></p>
<ol>
<li style="text-align: left"><span style="font-size: 14pt">クラス（クラスメソッドとクラス変数）</span></li>
<li style="text-align: left"><span style="font-size: 14pt">継承</span></li>
<li style="text-align: left"><span style="font-size: 14pt">モジュール</span></li>
<li style="text-align: left"><span style="font-size: 14pt"><span style="font-size: 14pt">例外処理</span></span></li>
</ol>
<p><span id="more-2242"></span></p>
<p>前回はクラスを作り、インスタンスメソッドを使うところまでを記載しました。今回はクラスメソッドの書き方から始めたいと思います。</p>
<p><span style="font-size: 24pt">1. クラスメソッドとクラス変数</span></p>
<pre class="theme:sublime-text lang:ruby decode:true" title="english_test.rb">class EnglishTest
#クラスメソッド
=begin
def クラス名(もしくはself).メソッド名
  実行したい処理
end
=end
  def EnglishTest.title(title)
    print title,"テストの点数を発表します。\n"
  end
end
#クラスメソッドの呼び出し
EnglishTest.title("英語")
</pre>
<p>クラスメソッドは、def クラス名(もしくはself).メソッド ~ endで表します。クラスメソッドを呼び出すには「クラス名.メソッド名」と書きます。</p>
<p>複数のクラスメソッドを纏める書き方もあります。</p>
<pre class="theme:sublime-text lang:ruby decode:true " title="english_test.rb">class EnglishTest
#発表した人数をカウント
  @@count=0

#初期化メソッド
  def initialize(name="Ruby",point=0)
    @name=name  
    @point=point
  end
#アクセスメソッド
  attr_reader :name,:point
  
#インスタンスメソッド
  def test
   @@count+=1
   print(@name,"さんの点数は",@point,"点\n") #()省略可
  end
 
#クラスメソッド
  class &lt;&lt; EnglishTest
    def title(title)
      print title,"テストの点数を発表します。\n"
    end

    def count
      @@count
    end
  end
end

#クラスメソッドの呼び出し
EnglishTest.title("英語")

#オブジェクトの生成
ruby=EnglishTest.new
tanaka=EnglishTest.new("田中",60)
takahashi=EnglishTest.new("高橋",80)
#メソッド呼び出し
ruby.test
tanaka.test
takahashi.test
#クラス変数の呼び出し
puts EnglishTest.count,"人の点数を発表しました。\n"</pre>
<p>クラスメソッドを複数書く場合はclass &lt;&lt; EnglishTest ~ endの中に書きます。インスタンスメソッドと同じような書き方ができ、わかりやすくなります。</p>
<p>@@で始まる変数はクラス変数と呼ばれるものです。このクラスのすべてのインスタンスで共有できる変数です。クラス変数を参照するには自分でアクセスメソッドを用意しなければいけません。上記ではtestメソッドが呼び出される回数を記録しています。</p>
<p>以下は実行結果です。</p>
<pre class="theme:terminal lang:default decode:true " title="実行結果">英語テストの点数を発表します。
Rubyさんの点数は0点
田中さんの点数は60点
高橋さんの点数は80点
3
人の点数を発表しました。</pre>
<p>&nbsp;</p>
<p><span style="font-size: 24pt">２. 継承</span></p>
<pre class="theme:sublime-text lang:ruby decode:true" title="human.rb">class Human
  def initialize(name="you")
    @name=name
  end

  def morning
    print "おはよう\n"
  end

  def hello
    print "こんにちは, ", @name,"さん\n"
  end 
end

#継承の構文
#class クラス名 &lt; スーパークラス ~ end
class John &lt; Human
  def morning
    print "Goodmorning\n"
  end
  
　　def bye
　　　　　print "Goodbye\n"
 end
end

john=John.new("John")
john.morning
john.hello
john.bye</pre>
<p>スーパクラスがHuman,サブクラスがJohnになります。スーパークラスのmorningメソッドをサブクラスのmorningメソッドでオーバーライド（上書き）し、サブクラスで新しいbyeメソッドを追加しています。スーパークラスのinitializeとhelloメソッドはサブクラスには記載されていませんが、継承されているので、呼び出すことができます。</p>
<pre class="theme:terminal lang:default decode:true" title="実行結果">Goodmorning
こんにちは, Johnさん
Goodbye</pre>
<p>&nbsp;</p>
<p><span style="font-size: 24pt">３. モジュール</span></p>
<p>モジュールはクラスと書き方が似ていますが、クラスと違いインスタンスを持つことができません。また継承もできません。処理だけを纏める機能を持ちます。以下のように記載します。</p>
<pre class="theme:sublime-text lang:ruby decode:true" title="math.rb">#モジュール作成
=begin
構文
module モジュール名
  モジュールの定義
end
=end

module AbcModule
 Number="1.0"  #定数

 def hello(name)
 print name,"さん、こんにちは\n"
 end 
#モジュール関数として登録
 module_function :hello
end

p AbcModule::Number
AbcModule.hello("John")

include AbcModule
p Number
hello("Sara")
</pre>
<p>モジュールは「モジュール名.メソッド名」という形で参照できます。これをモジュール関数といいます。注意しなければいけないのは、モジュール関数を定義しただけでは、モジュール名.メソッド名で呼び出せません。module_functionでモジュール関数を外部に公開して呼び出せるようになります。</p>
<p>モジュールをincludeすることによって、モジュール名を省略することができます。</p>
<pre class="theme:terminal lang:default decode:true" title="実行結果">"1.0"
Jognさん、こんにちは
"1.0"
Saraさん、こんにちは</pre>
<p>モジュールをクラスにインクルードすることを「Mix-in」とよびます。モジュール内のメソッドなどをクラスに取り込むことができます。</p>
<pre class="theme:sublime-text lang:ruby decode:true" title="module.rb">module AbcModule
  #Class1とClass２で共通のメソッドをまとめる
end

class Class1
  include AbcModule
  #固有のメソッドを記載
end

class Class2
  include AbcModule
  #固有のメソッドを記載
end</pre>
<p><span style="font-size: 14pt"> </span></p>
<p><span style="font-size: 24pt">４. 例外処理</span></p>
<p>プログラム実行で起きるエラーは以下のものがあります。</p>
<ul>
<li>データのエラー</li>
<li>システムのエラー</li>
<li>プログラムのエラー</li>
</ul>
<p>例外処理はこのようなエラーが発生した際に、実行されます。今回はraiseメソッドを使って、自分で例外を発生させます。</p>
<pre class="theme:sublime-text lang:ruby decode:true " title="error_test.rb">class ErrorTest
=begin
  begin
    例外が発生するかもしれない処理
  rescue
    例外が発生した際の処理
  end
=end  
  def initialize(name)
    @name=name
  end
 
  def hello
    begin
      raise
      print @name,"\n"
    rescue
      print "エラーが発生しました。\n"
    end
  end  
end

john=ErrorTest.new("John")
john.hello</pre>
<p>&nbsp;</p>
<p>例外処理は、begin~rescue~endを使います。beginに例外が発生するかもしれない処理を書き、rescueに例外が発生した際の処理を書きます。</p>
<p>上記では例外が発生するかもしれない処理の中でまずraiseメソッドが呼ばれ、その後printメソッドが呼ばれています。しかしraiseメソッドは例外を起こすメソッドなので、このメソッドが呼ばれた時点でrescueに処理が移ります。処理が移ったので、rescue側のprintメソッドが呼ばれ、以下が実行結果として出力されます。</p>
<pre class="theme:terminal lang:default decode:true" title="実行結果">エラーが発生しました。
</pre>
<p>&nbsp;</p>
<p>早足でRubyを紹介してきましたが、いかがでしたでしょうか？<br />
Rubyが気になった方は是非、開発環境を整えて、コードを書いてみてください。<br />
次回はRubyのフレームワークであるRailsの紹介をしたいと思います。</p>
]]></content:encoded>
			<wfw:commentRss>https://cloudear.jp/blog/?feed=rss2&#038;p=2242</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JPAを深掘りする〜Criteria APIで型安全な検索を追求しよう！【応用編】</title>
		<link>https://cloudear.jp/blog/?p=2143</link>
		<comments>https://cloudear.jp/blog/?p=2143#comments</comments>
		<pubDate>Fri, 18 Mar 2016 03:11:58 +0000</pubDate>
		<dc:creator><![CDATA[tomo]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[O/Rマッパー]]></category>
		<category><![CDATA[フレームワーク]]></category>
		<category><![CDATA[プログラム]]></category>

		<guid isPermaLink="false">https://cloudear.jp/blog/?p=2143</guid>
		<description><![CDATA[JPAを深掘りするシリーズの応用編です。 前回はCriteria APIの基本と利点をご紹介しました。今回はCriteria APIの実戦的な機能をいろいろとご紹介します。 準備・エンティティクラスとメタモデルクラスのサ [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>JPAを深掘りするシリーズの応用編です。</p>
<p>前回はCriteria APIの基本と利点をご紹介しました。今回はCriteria APIの実戦的な機能をいろいろとご紹介します。</p>
<p><span id="more-2143"></span></p>
<h2>準備・エンティティクラスとメタモデルクラスのサンプル</h2>
<p>次のようなエンティティクラスとメタモデルクラスが存在することを前提に進めていきます。</p>
<p>まずはUserエンティティクラスです。</p>
<pre class="lang:java decode:true" title="User.java">package sandbox.entity;

import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long      id;

    @Column(length = 150, unique = true, nullable = false)
    String    name;

    // getter/setterは省略
}
</pre>
<p>次にUserエンティティのプロパティの型を表すメタモデルクラスです。</p>
<pre class="lang:java decode:true " title="User_.java">package sandbox.entity;

import javax.annotation.Generated;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;

@Generated(value="Dali", date="2016-02-12T22:59:19.623+0900")
@StaticMetamodel(User.class)
public class User_ {
	public static volatile SingularAttribute&lt;User, String&gt; name;
	public static volatile SingularAttribute&lt;User, Long&gt; id;
}
</pre>
<p>それではCriteria APIを見ていきましょう。</p>
<h2>Where条件にメタモデルクラスを使う</h2>
<p><strong>メタモデルクラス</strong>は、Criteria APIによるクエリの型安全性を高めるという重要な役割を持っています。</p>
<p>冒頭で示したUserというエンティティクラスをnameプロパティの値で絞り込むクエリを作ってみましょう。</p>
<pre class="lang:java decode:true ">private static void selectUsersByName(final EntityManager em, final String pUserName) {
    final CriteriaBuilder builder = em.getCriteriaBuilder();
    final CriteriaQuery&lt;User&gt; query = builder.createQuery(User.class);
    final Root&lt;User&gt; root = query.from(User.class);
    query.where( //
            // メタモデルクラスを使ってカラムを指定する
            builder.equal(root.get(User_.name), pUserName) //
    );
    final List&lt;User&gt; result = em.createQuery(query).getResultList();
    for (final User user : result) {
        System.out.println(user);
    }
}
</pre>
<p>eclipseの入力補完の様子を見ると、fromに指定したエンティティクラスに応じたメタモデルクラスが候補として表示されることが分かると思います。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2016/02/jps-typesafe-query.png"><img class="alignnone size-full wp-image-2123" src="https://cloudear.jp/blog/wp-content/uploads/2016/02/jps-typesafe-query.png" alt="jps-typesafe-query" width="593" height="170" /></a></p>
<p>&nbsp;</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2016/02/jps-typesafe-query-2.png"><img class="alignnone size-full wp-image-2124" src="https://cloudear.jp/blog/wp-content/uploads/2016/02/jps-typesafe-query-2.png" alt="jps-typesafe-query-2" width="644" height="135" /></a></p>
<h2>Where句に複雑な条件を設定する</h2>
<p>検索画面のようにWhere句が動的かつ複雑になる時に、Criteria APIは威力を発揮します。例えば入力のある条件はWhere句に加えるが、入力のない条件はWhere句に加えない、という処理をJPQLで書くのは割と大変です。</p>
<pre class="lang:java decode:true">private static void selectUsersByName(final EntityManager em, final String name) {
    final StringBuilder s = new StringBuilder("select e from User e where 1 = 1");
    if (name != null) {
        s.append(" and e.name = :name");
    }

    final TypedQuery&lt;User&gt; query = em.createQuery(new String(s), User.class);

    if (name != null) { // 存在しないパラメータを設定すると例外が生じるため、再度チェックせざるを得ない！
        query.setParameter("name", name);
    }

    final List&lt;User&gt; result = query.getResultList();
    for (final User user : result) {
        System.out.println(user);
    }
}
</pre>
<p>これをCriteria APIで書き直すと、とても素直なプログラムになります。</p>
<pre class="lang:java decode:true ">private static void selectUsersByName(final EntityManager em, final String name) {
    final CriteriaBuilder builder = em.getCriteriaBuilder();
    final CriteriaQuery&lt;User&gt; query = builder.createQuery(User.class);
    final Root&lt;User&gt; root = query.from(User.class);

    final List&lt;Predicate&gt; where = new ArrayList&lt;&gt;();
    if (name != null) {
        where.add(builder.equal(root.get(User_.name), name));
    }

    query.where(where.toArray(new Predicate[where.size()]));

    final List&lt;User&gt; result = em.createQuery(query).getResultList();
    for (final User user : result) {
        System.out.println(user);
    }
}
</pre>
<h2> 関連クラスを同時に取得する</h2>
<p>JPAの強みの１つにエンティティクラスの関連をコードで表現出来ることがあります。下記はUserを親に持つTagというエンティティを作っています。</p>
<pre class="lang:java decode:true">package sandbox.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

@Entity
public class Tag {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long   id;

    @Column(length = 50, unique = false, nullable = false)
    String name;

    @ManyToOne(fetch = FetchType.LAZY)
    User   user;

    @Column(nullable = false)
    long   starCount;

    // getter/setterは省略
}</pre>
<p>Tagを取得する際、親のUserも同時に取ってくるようなクエリを作ってみましょう。</p>
<pre class="lang:java decode:true">private static void selectTagWithUser(final EntityManager em) {
    final CriteriaBuilder builder = em.getCriteriaBuilder();
    final CriteriaQuery&lt;Tag&gt; query = builder.createQuery(Tag.class);
    final Root&lt;Tag&gt; root = query.from(Tag.class);

    root.fetch(Tag_.user, JoinType.LEFT); // 関連エンティティを同時に取ってくるように指定

    final List&lt;Tag&gt; result = em.createQuery(query).getResultList();
    for (final Tag tag : result) {
        System.out.println(tag.getUser());
    }
}
</pre>
<p>9行目がポイントです。実はこの行がなくても関連エンティティは取得できるのですが、SQLの実行回数が格段に変わってきます。俗に言う「N+1問題」を回避する手法です。</p>
<h2>関連先のエンティティの条件を指定する</h2>
<p>JPAの強力な機能の１つに、関連先エンティティの条件指定がとても簡単な点があります。</p>
<pre class="lang:java decode:true">private static void selectTagByUserName(final EntityManager em, final String pUserName) {
    final CriteriaBuilder builder = em.getCriteriaBuilder();
    final CriteriaQuery&lt;Tag&gt; query = builder.createQuery(Tag.class);
    final Root&lt;Tag&gt; root = query.from(Tag.class);

    query.where(builder.equal(root.get(Tag_.user).get(User_.name), pUserName));

    final List&lt;Tag&gt; result = em.createQuery(query).getResultList();
    for (final Tag tag : result) {
        System.out.println(tag);
    }
}</pre>
<p>6行目がポイントです。「Tagクラス#userプロパティ」→「Userクラス#nameプロパティ」とたどって条件指定しています。SQLで同じことをしようとするとJOINを書く必要があり手間がかかるところですが、JPAではかなりシンプルに書けることが分かります。</p>
<h2>Where句に IN条件を指定する</h2>
<p>IN条件は少し特殊な書き方をするのでハマることがあります。</p>
<pre class="lang:java decode:true">private static void selectUsersByNames(final EntityManager em, final String... names) {
    final CriteriaBuilder builder = em.getCriteriaBuilder();
    final CriteriaQuery&lt;User&gt; query = builder.createQuery(User.class);
    final Root&lt;User&gt; root = query.from(User.class);

    if (names != null &amp;&amp; names.length &gt; 0) {
        query.where(root.get(User_.name).in(names));
    }

    final List&lt;User&gt; result = em.createQuery(query).getResultList();
    for (final User user : result) {
        System.out.println(user);
    }
}
</pre>
<p>7行目でIN条件を指定しています。CriteriaBuilderを使わない点に注意してください。</p>
<p>また要素数が0の時の挙動は、残念ながらDB製品依存となるようなので、プログラムで明示的にチェックするのが無難でしょう。</p>
<h2>Tupleを使って柔軟な結果を得る</h2>
<p>Tupleという汎用クラスを使えばエンティティにとらわれない形でデータを取得できます。例えば、JOINを使って複数のテーブルからデータを取得しつつ集計するような用途に有用です。</p>
<p>ただし、型安全性が失われる点には注意が必要です。</p>
<pre class="lang:java decode:true">private static void selectTupleWithJoin(final EntityManager em) {
    final CriteriaBuilder builder = em.getCriteriaBuilder();

    // Tupleで結果を受け取る
    final CriteriaQuery&lt;Tuple&gt; query = builder.createTupleQuery();

    // Tagを主テーブルにする
    final Root&lt;Tag&gt; root = query.from(Tag.class);

    // JOINする
    final Join&lt;Tag, User&gt; join = root.join(Tag_.user);

    final Path&lt;String&gt; userName = join.get(User_.name);

    // ユーザ名で集計する
    query.groupBy(userName);

    // Userから特定のカラムのみ取得しつつTagのstarCountを合計する
    // 後で取り出しやすいように、カラムには別名を付けておく
    query.multiselect( //
            userName.alias("user_name") //
            , builder.sum(root.get(Tag_.starCount)).alias("tag_count") //
    );

    final List&lt;Tuple&gt; result = em.createQuery(query).getResultList();
    for (final Tuple e : result) {
        System.out.println(e.get("user_name") + " " + e.get("tag_count"));
    }
}</pre>
<h2>任意のデータクラスをクエリの結果の型にする</h2>
<p>Tupleの弱点は、Tupleが汎用的すぎて「どんなデータがいくつ入っているか分かりにくい」ことです。これを補うために、任意の型をクエリの結果とすることができます。</p>
<p>Tupleの例を書き直してみます。まずは結果を受け取るためのクラスを作ります。コンストラクタで全ての値を受け取るようにする必要があります。</p>
<pre class="lang:java decode:true">public class StarSummary {

    private final String userName;
    private final long   tagCount;

    public StarSummary(final String pUserName, final long pTagCount) {
        this.userName = pUserName;
        this.tagCount = pTagCount;
    }

    // getterは省略
}</pre>
<p>作ったクラスをクエリの結果とするには、<code>CriteriaBuilder#construct(Class, Selection&lt;?&gt;...)</code>を使ってクエリを組み立てます。</p>
<pre class="lang:java decode:true">    private static void selectStartSummary(final EntityManager em) {
        final CriteriaBuilder builder = em.getCriteriaBuilder();
        final CriteriaQuery&lt;StarSummary&gt; query = builder.createQuery(StarSummary.class);
        final Root&lt;Tag&gt; root = query.from(Tag.class);

        final Join&lt;Tag, User&gt; join = root.join(Tag_.user);

        query.select( //
                builder.construct(StarSummary.class //
                , join.get(User_.name) //
                , builder.sum(root.get(Tag_.starCount)) //
        ));
        query.groupBy(join.get(User_.name));

        final List&lt;StarSummary&gt; result = em.createQuery(query).getResultList();
        for (final StarSummary e : result) {
            System.out.println(e);
        }
    }
</pre>
<p>9〜11行目でデータクラスを扱っています。</p>
<p>Tupleに比べ扱いやすい型で結果を得られますが、一方でコンストラクタ引数の順番に依存するプログラムとなってしまうのが弱点です。ですがTupleの「どんなデータがいくつ入っているか分かりにくい」という欠点はとても重大ですので、できれば、こちらのデータクラスを使う方が望ましいです。</p>
<h2>型安全になりきれていない箇所</h2>
<p>ここまで見てきたように、Criteria APIは型安全にクエリを組み立てられる非常に便利な機能なのですが、残念ながら型安全になりきれていない箇所があります。代表的なのは<code>CriteriaBuilder#equal(Expression&lt;?&gt; exp, Object value)</code>メソッドです。</p>
<p>例えば次のコードを見てください。</p>
<pre class="lang:java decode:true">    query.where( //
        builder.equal(root.get(User_.name), pUserName) //
    );
</pre>
<p>これを次のように書き間違えたとしても、コンパイルエラーにはならないのです。</p>
<pre class="lang:java decode:true">    query.where( //
        builder.equal(root.get(User_.id), pUserName) //
    );
</pre>
<p>このケースでは実行時例外がスローされますが、場合によっては例外がスローされず普通に実行されてしまうため、分かりにくいバグの原因となる可能性があります。</p>
<p>このメソッドのシグニチャが</p>
<pre class="lang:java decode:true ">&lt;C&gt; Predicate equal(Expression&lt;C&gt; exp, C value)</pre>
<p>となっていればよかったのに・・・と思えてなりません。頻繁に使うメソッドだけに残念です。</p>
<h2>JPAのその他の機能</h2>
<p>最後に、ちょっとした便利機能をいくつか紹介しておきます。</p>
<h3>ページングに使える２つのメソッド</h3>
<p>Webアプリケーションでは検索結果が大量になる場合、ページング表示するのが普通です。JPAには簡単にページングを実装するためのメソッドがあります。</p>
<p><code>setFirstResult()/setMaxResults()</code>です。</p>
<pre class="lang:java decode:true">private static List&lt;User&gt; selectUsersWithPaging(final EntityManager em, final int pPageIndex, final int pCountPerPage) {
    final CriteriaBuilder builder = em.getCriteriaBuilder();
    final CriteriaQuery&lt;User&gt; query = builder.createQuery(User.class);
    query.from(User.class);
    return em.createQuery(query) //
            .setFirstResult(pPageIndex * pCountPerPage) //
            .setMaxResults(pCountPerPage) //
            .getResultList();
}
</pre>
<p>7行目と8行目でページングを指定しています。</p>
<h3>結果が必ず1件と分かっている場合に使えるメソッド</h3>
<p>結果が必ず1件と分かっている時には<code>getSingleResult()</code>メソッドが使えます。</p>
<pre class="lang:java decode:true">private static void countAllUsers(final EntityManager em) {
    final CriteriaBuilder builder = em.getCriteriaBuilder();
    final CriteriaQuery&lt;Long&gt; query = builder.createQuery(Long.class);
    final Root&lt;User&gt; root = query.from(User.class);

    query.select(builder.count(root));

    final long count = em.createQuery(query).getSingleResult().longValue();
    System.out.println(count);
}
</pre>
<p>ただし、結果が1件でなかった時は例外がスローされますので、絶対に1件と確信が持てる場合にのみ使ってください。</p>
<h2> まとめ</h2>
<p>Criteria APIを中心に、２回に渡ってJPAの様々な機能を解説してきましたがいかがでしたでしょうか。</p>
<p>JPAには他にも便利で重要な機能がたくさんあります。特にエンティティクラスの設計は工夫のしがいがあり、別の機会でご紹介したいところです。</p>
<p>非常にパワフルなJPA。JavaEEを使う場合はぜひJPAを使って効率的かつ安全にDBアクセスを実装していただきたいと思います。</p>
]]></content:encoded>
			<wfw:commentRss>https://cloudear.jp/blog/?feed=rss2&#038;p=2143</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JPAを深掘りする〜Criteria APIで型安全な検索を追求しよう！【基本編】</title>
		<link>https://cloudear.jp/blog/?p=2101</link>
		<comments>https://cloudear.jp/blog/?p=2101#comments</comments>
		<pubDate>Mon, 22 Feb 2016 02:10:59 +0000</pubDate>
		<dc:creator><![CDATA[tomo]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[O/Rマッパー]]></category>
		<category><![CDATA[データベース]]></category>
		<category><![CDATA[フレームワーク]]></category>
		<category><![CDATA[プログラム]]></category>

		<guid isPermaLink="false">https://cloudear.jp/blog/?p=2101</guid>
		<description><![CDATA[今回はJavaEEの中でも特に重要な「JPA（Java Persistence API）」を深掘りしてみます。基本編と応用編の２回に渡ってじっくりとJPAをご紹介します。 JPAとは JPAは一言で言えば「高機能なDBア [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>今回はJavaEEの中でも特に重要な<strong>「JPA（Java Persistence API）」</strong>を深掘りしてみます。基本編と応用編の２回に渡ってじっくりとJPAをご紹介します。</p>
<h2>JPAとは</h2>
<p>JPAは一言で言えば「高機能なDBアクセスフレームワーク」です。DBアクセスフレームワークは実に様々なものがありますが、JPAの特徴は</p>
<p><span id="more-2101"></span></p>
<ul>
<li>エンティティクラスへの操作を通してDB操作を実現する（DBの都合はプログラマから極力隠される）</li>
<li>型安全を追求するための様々な機能を備える</li>
</ul>
<p>が挙げられます。Javaの良さを引き出す工夫に満ちたフレームワークと言えるでしょう。</p>
<p>様々な機能を備えたJPAですが、本エントリでは、検索、中でもCriteria APIを使った型安全な検索を中心にご紹介します。コードをしっかり載せていきますので、Criteria APIのコンセプトを感じ取っていただけると思います。</p>
<p>なお、JPAを動作させる環境を構築する方法は「<a title="JavaEEだけでここまで出来る！GlassFish+Eclipseで高速Webアプリ開発【環境構築編】" href="https://cloudear.jp/blog/?p=1375">JavaEEだけでここまでできる！GlassFish+Eclipseで高速Webアプリ開発【環境構築編】</a>」をご覧下さい。</p>
<h2>準備１・メタモデルクラスを自動生成する設定</h2>
<p>メタモデルクラスとは、エンティティクラスのプロパティに関する情報を表すクラスであり、型安全にJPAを使うためには欠かせないクラスです。</p>
<p>例えば次のようなエンティティクラスがあったとしましょう。</p>
<pre class="lang:java decode:true" title="User.java">package sandbox.entity;

import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long      id;

    @Column(length = 150, unique = true, nullable = false)
    String    name;

    // getter/setterは省略
}
</pre>
<p>このエンティティクラスに対するメタモデルクラスは次のようになります。</p>
<pre class="lang:java decode:true " title="User_.java">package sandbox.entity;

import javax.annotation.Generated;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;

@Generated(value="Dali", date="2016-02-12T22:59:19.623+0900")
@StaticMetamodel(User.class)
public class User_ {
	public static volatile SingularAttribute&lt;User, String&gt; name;
	public static volatile SingularAttribute&lt;User, Long&gt; id;
}
</pre>
<p>メタモデルクラスはeclipseのような開発環境に自動で作ってもらうことができますので、有効にしておきましょう。</p>
<p>ecliseの場合の手順を紹介しておきます。プロジェクトのプロパティを開き、「プロジェクト・ファセット」から「Convert to faceted form&#8230;」をクリックします。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2016/02/convert-to-faceted-form.png"><img class="alignnone size-full wp-image-2107" src="https://cloudear.jp/blog/wp-content/uploads/2016/02/convert-to-faceted-form.png" alt="convert-to-faceted-form" width="833" height="348" /></a></p>
<p>&nbsp;</p>
<p>プロジェクト・ファセットが有効になったので、JPAサポートを有効にします。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2016/02/project-facets-jpa.png"><img class="alignnone size-full wp-image-2109" src="https://cloudear.jp/blog/wp-content/uploads/2016/02/project-facets-jpa.png" alt="project-facets-jpa" width="806" height="408" /></a></p>
<p>ここで「 OK」を押していったんプロパティ画面を閉じます。</p>
<p>再びプロパティ画面を開くと「JPA」という設定項目が増えていますので、メタモデルクラスの自動生成を有効にします。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2016/02/eclipse-jpa-metamodel.png"><img class="alignnone size-full wp-image-2110" src="https://cloudear.jp/blog/wp-content/uploads/2016/02/eclipse-jpa-metamodel.png" alt="eclipse-jpa-metamodel" width="834" height="713" /></a></p>
<p>これで、エンティティクラスに変更が入る度にメタモデルクラスが自動生成されます。メタモデルクラスの名前はエンティティクラスの名前の後ろに _ を付けたものになります。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2016/02/entity-metamodel.png"><img class="alignnone size-full wp-image-2113" src="https://cloudear.jp/blog/wp-content/uploads/2016/02/entity-metamodel.png" alt="entity-metamodel" width="268" height="81" /></a></p>
<p>&nbsp;</p>
<h2>準備２・SQLをコンソールに出力する設定</h2>
<p>JPAを使いこなすコツはJavaコードを中心に考えることですが、さすがにSQLが見えないと辛すぎます。せめてコンソールにSQLを出力するようにしておきましょう。JPAの設定ファイルであるpersistence.xmlにプロパティを追記します。</p>
<h3>EclipseLinkの場合</h3>
<pre class="lang:xhtml decode:true">&lt;property name="eclipselink.logging.level.sql" value="FINE" /&gt;
&lt;property name="eclipselink.logging.parameters" value="true" /&gt;
&lt;property name="eclipselink.logging.logger" value="org.eclipse.persistence.logging.DefaultSessionLog"/&gt;</pre>
<h3>OpenJPAの場合</h3>
<pre class="lang:xhtml decode:true">&lt;property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE"/&gt;
&lt;property name="openjpa.ConnectionFactoryProperties" value="PrintParameters=true" /&gt;</pre>
<p>APサーバにGlassFishを使っているのであれば、EclipseLinkの方を設定してください。</p>
<h2>スキーマ定義をエンティティクラスで行う</h2>
<p>JPAの良さを引き出すコツは、Javaコードを中心に考えることです。まずはスキーマ定義をエンティティクラスで行うようにしてみましょう。</p>
<p>ただ、実はJPAの仕様にはエンティティクラスからDDLを作る機能は含まれていません。JPAの実装であるEclipseLinkやOpenJPAの機能を使います。通常、persistence.xmlにプロパティを追記します。</p>
<h3>EclipseLinkの場合</h3>
<pre class="lang:xhtml decode:true" title="persistence.xml">&lt;property name="eclipselink.ddl-generation" value="create-tables" /&gt;</pre>
<h3>OpenJPAの場合</h3>
<pre class="lang:default decode:true">&lt;property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)" /&gt;</pre>
<p>APサーバにGlassFishを使っているのであれば、EclipseLinkの方を設定してください。</p>
<h2>Criteria APIによる検索</h2>
<p>JPAの検索には、JPQLとCriteria APIの２つのやり方があります。JPQLは文字列でクエリを記述するため、コンパイル時に型チェックが全く働きません。</p>
<p>例えば以下のコードは実行時にClassCastExceptionがスローされてしまいます。</p>
<pre class="lang:java decode:true">private static void selectByJPQL(final EntityManager em) {
    final String q = "select e from Tag e";
    for (final User user : em.createQuery(q, User.class).getResultList()) {
        System.out.println(user);
    }
}
</pre>
<p>よく見ると、クエリ文字列が<code>from Tag</code>となっています。結果のエンティティは<code>User</code>型で受けていますから、型が異なっていおり、<strong>実行時に</strong>ClassCastExceptionがスローされるのです。</p>
<p>しかしCriteria APIを使うと、このようなミスは<strong>コンパイル時に</strong>検出できるようになります。上のJPQLをCriteria APIで描き直してみましょう。</p>
<pre class="lang:java decode:true">private static void selectByCriteria(final EntityManager em) {
    final CriteriaBuilder builder = em.getCriteriaBuilder();
    final CriteriaQuery&lt;Tag&gt; criteria = builder.createQuery(Tag.class);
    criteria.from(User.class);

    final TypedQuery&lt;User&gt; query = em.createQuery(criteria);
    for (final User user : query.getResultList()) {
        System.out.println(user);
    }
}</pre>
<p>eclipseでこのコードを書くと、以下のようにコンパイルエラーとしてミスを教えてくれます。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2016/02/jpa-criteria-error.png"><img class="alignnone size-full wp-image-2116" src="https://cloudear.jp/blog/wp-content/uploads/2016/02/jpa-criteria-error.png" alt="jpa-criteria-error" width="708" height="104" /></a></p>
<p>&nbsp;</p>
<p>このように、Criteria APIを使うと<span style="font-size: 12pt;"><strong>クエリのミスをコンパイル時にチェックできる</strong></span>ようになります。これがCriteria APIの最大の利点です。</p>
<p>また、副次的な効果ですが<strong>変なクエリが書かれない</strong>ようになります。実際の開発現場では、変態的なSQLが横行してチューンングの足枷になったり、特定のDB製品でしか実行できない書き方がされていたりと、SQL周りの問題が起きやすいです。しかしCriteria APIを使えばクエリの記述方法がある程度統一されるため、問題が起きにくく、またレビューしやすくなります。</p>
<h2>Criteria APIによるクエリの基本形</h2>
<p>Criteria APIはJPQLの構造をJavaクラスで表現したものと考えることができます。JPQLの構成要素の基本は次の３つです。</p>
<ol>
<li>from句：どのエンティティ（≒テーブル）からデータを取得するか</li>
<li>where句：抽出条件</li>
<li>select句：どのエンティティ、あるいはプロパティなどを取得するか</li>
</ol>
<p>この３つを踏まえると、Criteria APIを使ったプログラムの基本形は次のようになります。</p>
<pre class="lang:java decode:true">private static void selectUsersByName(final EntityManager em, final String pUserName) {
    // クエリを組み立てるためのオブジェクトを得る
    final CriteriaBuilder builder = em.getCriteriaBuilder();

    // クエリ全体を表現するオブジェクトを作成.
    // 引数として、クエリ結果の型を指定する.
    final CriteriaQuery&lt;User&gt; query = builder.createQuery(User.class);

    // from句指定
    final Root&lt;User&gt; root = query.from(User.class);

    // where句指定
    query.where( //
            builder.equal(root.get(User_.name), pUserName) //
            , builder.isNotNull(root.get(User_.name)) //
    );

    // select句指定.
    // ここではプロパティではなくエンティティそのものを指定.
    // ただしfromと同じエンティティを指定する場合はこの行は省略可能.
    query.select(root);

    // クエリ実行
    final List&lt;User&gt; result = em.createQuery(query).getResultList();
    for (final User user : result) {
        System.out.println(user);
    }
}
</pre>
<p>結果の型を指定できるのがとても強力です。例えば全件数を得るクエリは次のように書けます。</p>
<pre class="lang:java decode:true ">private static void countAllUsers(final EntityManager em) {
    final CriteriaBuilder builder = em.getCriteriaBuilder();

    // 件数なので結果は数値で得るようにする
    final CriteriaQuery&lt;Long&gt; query = builder.createQuery(Long.class);
    final Root&lt;User&gt; root = query.from(User.class);

    // count関数を使う
    query.select(builder.count(root));

    final long count = em.createQuery(query).getSingleResult().longValue();
    System.out.println(count);
}</pre>
<hr />
<p>基本編はここまでです。次回の応用編では、Criteria APIの実戦的な機能をご紹介します。</p>
]]></content:encoded>
			<wfw:commentRss>https://cloudear.jp/blog/?feed=rss2&#038;p=2101</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaEEで簡単WebSocketサーバ</title>
		<link>https://cloudear.jp/blog/?p=2053</link>
		<comments>https://cloudear.jp/blog/?p=2053#comments</comments>
		<pubDate>Tue, 19 Jan 2016 08:07:37 +0000</pubDate>
		<dc:creator><![CDATA[tomo]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[フレームワーク]]></category>
		<category><![CDATA[プログラム]]></category>

		<guid isPermaLink="false">https://cloudear.jp/blog/?p=2053</guid>
		<description><![CDATA[本エントリでは近代的なWebアプリケーションでは欠かせないWebSocketをJavaEEで実現する方法を説明します。 前段・WebSocketはなぜ生まれたか 伝統的なWebアプリケーションは、HTTPというプロトコル [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>本エントリでは近代的なWebアプリケーションでは欠かせない<strong>WebSocket</strong>をJavaEEで実現する方法を説明します。</p>
<h2>前段・WebSocketはなぜ生まれたか</h2>
<p><span id="more-2053"></span></p>
<p>伝統的なWebアプリケーションは、HTTPというプロトコルで成立していました。HTTPとは単純なリクエスト・レスポンスモデルであり「クライアントであるWebブラウザがWebサーバに対してリクエストを投げ、返って来たレスポンスを処理する」というモデルで成り立っていました。あくまでクライアントが処理の起点となっているのです。</p>
<p>一方、Webアプリケーションであっても「サーバ側で起きた何らかの出来事を、Webブラウザに通知したい」というニーズは常にありました。これを「サーバプッシュ」と言います。これまで、HTTPを使って擬似的なサーバプッシュを実現するために技術者は様々な工夫を凝らしてきました。しかしやはり、リクエスト・レスポンスモデルの下では無理があったのです。</p>
<p>このような経緯があり、Webブラウザでの真のサーバプッシュを実現するべく策定されたのが<strong>WebSocket</strong>というプロトコルです。</p>
<p>もちろんJavaEEでもWebSocketはサポートされています。</p>
<p>本エントリではJavaEE7で導入されたWebSocketサーバを簡単に実現する機能をご紹介します。</p>
<h2>最小のサンプル</h2>
<p>これまで紹介してきたように、JavaEEでは、ある機能を使うのにアノテーションを付与したクラスを単に作成するだけで良い、というスタイルが広く採用されています。WebSocketも例外ではありません。</p>
<p>下記は最小のサンプルです。</p>
<pre class="lang:java decode:true">package sandbox.websocket.minimum;

import javax.websocket.OnMessage;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/ws/min")
public class MinimumEndpoint {

    @OnMessage
    public String onMessage(final String pText) {
        System.out.println(pText);
        return "Re: " + pText;
    }
}
</pre>
<p>@ServerEndpointアノテーションを付けたクラスはWebSocketサーバとなります。このようなクラスを<strong>Endpointクラス</strong>と呼びます。</p>
<p>さらに@OnMessageアノテーションでクライアントから送信されたメッセージを処理するメソッドを指定しています。メッセージの処理内容は、送信されたメッセージの頭に「Re: 」を付けて送り返しています。</p>
<p>このクラスのテストのために、次のようなHTMLを作ってみましょう。</p>
<pre class="lang:xhtml decode:true">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;WebSocket最小のサンプル&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;input type="text"&gt;
    &lt;button type="button" class="btn btn-primary form-control"&gt;送信&lt;/button&gt;
    &lt;script src="https://code.jquery.com/jquery-2.2.0.min.js"&gt;&lt;/script&gt;
    &lt;script&gt;
       var ws = null;
       var onOpen = function() {
           $('button').click(function() {
               ws.send($('input').val());
           });
       };
       var onMessage = function(e) {
           alert(e.data);
       };
       var connect = function() {
           ws = new WebSocket('ws://localhost:' + location.port + '/ws/min');
           ws.onopen = onOpen;
           ws.onmessage = onMessage;
       };
       connect();
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>テキストフィールドに文字を入力して「送信」ボタンを押すと、先頭に「Re: 」を付けた文字列がアラートで表示されるサンプルです。</p>
<p>&nbsp;</p>
<hr />
<p>&nbsp;</p>
<p>いかがでしょうか。いとも簡単にWebSocketを使ったアプリケーションが作れてしまうことが分かっていただけたかと思います。</p>
<p>ただ、このサンプルはWebブラウザからのリクエストが起点であるため、Ajaxでも実現可能でありWebSocketの旨味がないサンプルです。そこで以降では、WebSocketを使うための実践的な機能を紹介していきます。</p>
<h2>@OnMessage以外のアノテーション</h2>
<p>@OnMessageアノテーションの他にも@OnOpen/@OnError/@OnCloseというアノテーションがあり、これらのアノテーションが付与されたメソッドは、適切なタイミングでJavaEEコンテナから呼び出されるコールバックメソッドとなります。</p>
<p>下記に典型的なEndpointクラスの宣言方法を示します。</p>
<pre class="lang:java decode:true" title="SampleEndpoint.java">package sandbox.websocket.sample;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/ws/sample")
public class SampleEndpoint {

    @OnOpen
    public void onOpen(Session pSession) {
    }

    @OnMessage
    public void onMessage(String pMessage) {
    }

    @OnError
    public void onError(Throwable pError) {
    }

    @OnClose
    public void onClose(Session pSession) {
    }
}
</pre>
<p>各メソッドはpublicである必要があります。</p>
<p>また@OnErrorコールバックメソッドは、Throwableを引数に取る必要があります。</p>
<p>それ以外のメソッドの引数は必要に応じて増減させることが可能です。例えば、@OnMessageのコールバックでSessionが必要なら、引数に追加してください。</p>
<h2>URIテンプレート</h2>
<p>接続先を分類するために、URLにパラメータを含めることが出来ます。</p>
<pre class="lang:java decode:true" title="DescriptorWebSocketServer.java">@ServerEndpoint("/ws/rooms/{room-descriptor}")
public class DescriptorEndpoint {
    ...</pre>
<p>これを使うと、チャットルームの入室管理のようなことが比較的簡単に実装できます。簡単なチャットサーバのコードをご紹介します。</p>
<pre class="lang:java decode:true" title="DescriptorWebSocketServer.java">package sandbox.websocket.descritpor;

import java.io.IOException;

import javax.inject.Inject;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/ws/rooms/{room-descriptor}")
public class DescriptorEndpoint {

    @Inject
    WebSocketSessionManager sessionManager;

    @OnOpen
    public void onOpen(@PathParam("room-descriptor") final String pRoomDescriptor, final Session pSession) {
        this.sessionManager.addSession(pRoomDescriptor, pSession);
    }

    @OnClose
    public void onClose(@PathParam("room-descriptor") final String pRoomDescriptor, final Session pSession) {
        this.sessionManager.removeSession(pRoomDescriptor, pSession);
    }

    @OnMessage
    public void onMessage(@PathParam("room-descriptor") final String pRoomDescriptor, final String pText) {
        for (final Session session : this.sessionManager.getSessions(pRoomDescriptor)) {
            try {
                session.getBasicRemote().sendText("Re: " + pText);
            } catch (final IOException e) {
                e.printStackTrace();
            }
        }
    }
}
</pre>
<p>注目していただきたいのは次の２点です。</p>
<ul>
<li>@ServerEndpointの引数に<code>room-descriptor</code>というパラメータを含めている</li>
<li>メソッドの引数に<code>@PathParam("room-descriptor")</code>を指定することでパラメータの値を得ている</li>
</ul>
<p>なおEndpointクラスはCDIによるスコープ管理が効きません。たとえシングルトンな作りにしたくても、それが叶わないのです。</p>
<p>しかしインジェクション対象にすることはできます。ここでは、チャットルーム毎のWebSocket接続を管理するクラス（WebSocketSessionManager）をシングルトンとして作成し、@Injectアノテーションでインジェクションしています。</p>
<p>WebSocketSessionManagerクラスのコードも掲載しておきます。</p>
<pre class="lang:java decode:true" title="WebSocketSessionManager.java">package sandbox.websocket.descritpor;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.enterprise.context.ApplicationScoped;
import javax.websocket.Session;

@ApplicationScoped
public class WebSocketSessionManager {

    private final ConcurrentMap&lt;String, Lock&gt;          locks    = new ConcurrentHashMap&lt;&gt;();
    private final ConcurrentMap&lt;String, List&lt;Session&gt;&gt; sessions = new ConcurrentHashMap&lt;String, List&lt;Session&gt;&gt;() {
        public List&lt;Session&gt; get(final Object key) {
            List&lt;Session&gt; ret = super.get(key);
            if (ret == null) {
                ret = new CopyOnWriteArrayList&lt;&gt;();
                this.put((String) key, ret);
            }
            return ret;
        }
    };

    public void addSession(final String pRoomDescriptor, final Session pSession) {
        synchronized (this.getLock(pRoomDescriptor)) {
            this.sessions.get(pRoomDescriptor).add(pSession);
        }
    }

    public List&lt;Session&gt; getSessions(final String pRoomDescriptor) {
        return this.sessions.get(pRoomDescriptor);
    }

    public void removeSession(final String pRoomDescriptor, final Session pSession) {
        synchronized (this.getLock(pRoomDescriptor)) {
            this.sessions.get(pRoomDescriptor).remove(pSession);
        }
    }

    private Lock getLock(final String pRoomDescriptor) {
        final Lock newLock = new Lock();
        final Lock alreadyLock = this.locks.putIfAbsent(pRoomDescriptor, newLock);
        return alreadyLock == null ? newLock : alreadyLock;
    }

    private static class Lock {
        // nodef
    }

}
</pre>
<p>スレッドセーフにするために少し複雑なコードになっていますが、結局やっていることは部屋毎にWebSocket接続を束ねているだけなので、臆さず読み解いてみてください。</p>
<p>最後に、これをテストするためのHTMLを掲載します。</p>
<pre class="lang:xhtml decode:true">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;WebSocket識別子のサンプル&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;input type="text" name="desc" placeholder="部屋の識別子"&gt;
    &lt;button type="button" class="connector"&gt;接続&lt;/button&gt;
    &lt;hr/&gt;
    &lt;input type="text" name="text" placeholder="送信テキスト"&gt;
    &lt;button type="button" class="sender" disabled="disabled"&gt;送信&lt;/button&gt;
    &lt;hr/&gt;
    &lt;h3&gt;レスポンス&lt;/h3&gt;
    &lt;p class="response"&gt;&lt;/p&gt;
    &lt;script src="https://code.jquery.com/jquery-2.2.0.min.js"&gt;&lt;/script&gt;
    &lt;script&gt;
       var ws = null;
       $('button.connector').click(function() {
           if (ws) ws.close();
           var url = 'ws://localhost:' + location.port + '/ws/rooms/' + $('input[name="desc"]').val();
           ws = new WebSocket(url);
           ws.onmessage = function(e) {
               $('.response').text(e.data);
           };
           ws.onopen = function() {
               $('button.sender').removeAttr('disabled');
           };
           ws.onclose = function() {
               $('button.sender').attr('disabled', 'disabled');
           };
       });
       $('button.sender').click(function() {
            if (!ws || ws.readyState !== WebSocket.OPEN) {
               alert('先に接続して下さい。');
               return;
           }
           ws.send($('input[name="text"]').val());
       });
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>動作を見てみるときは、ぜひ複数のWebブラウザを開いてください。誰かの投稿が同じ部屋の全員に配信されることが分かると思います。とてもシンプルですが、チャットアプリケーションができました。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2016/01/websocket_desc.png"><img class="alignnone size-full wp-image-2075" src="https://cloudear.jp/blog/wp-content/uploads/2016/01/websocket_desc.png" alt="websocket_desc" width="732" height="283" /></a></p>
<h2>DecoderとEncoder</h2>
<p>WebSocketはテキストデータとバイナリデータをやり取りできます。一般的には扱いやすいJSON形式のテキストを使うことが多いでしょう。しかしEndpointクラスを普通に作ると、@OnMessageコールバックの引数や戻り値の型は、単なるString型です。せっかくJavaを使っているのですから、ここはデータクラスに変換して型安全にメッセージを扱いたいものです。</p>
<p>この要求に応えるのが、<strong>Decoder/Encoder</strong>です。</p>
<h3>Decoderクラス</h3>
<p>Decoderクラスにはクライアント（一般的にはWebブラウザ）から送られてきたメッセージ内容を任意のJavaオブジェクトに変換する処理を実装します。このクラスを作成すると、Endpointクラスの@OnMessageコールバックメソッドに引数にString以外の型が使えるようになります。</p>
<p>ここでは ClientMessageというクラスを導入して、Decoderクラスを作ってみます。なおJSONとJavaオブジェクトの変換にはJSONICというライブラリを使っています。</p>
<p>まずはClientMessageクラスです。getterとsetterのみの単なるデータクラスとして作りましょう。</p>
<pre class="lang:java decode:true" title="ClientMessage.java">package sandbox.websocket.json;

import java.util.Date;

public class ClientMessage {
    private Date   date;
    private String body;
    // getter/setterは省略
}
</pre>
<p>次にDecoderです。JsonDecoderという名前で作ります。なお使い方は後で説明します。</p>
<pre class="lang:java decode:true" title="JsonDecoder.java">package sandbox.websocket.json;

import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;

import net.arnx.jsonic.JSON;

public class JsonDecoder implements Decoder.Text&lt;ClientMessage&gt; {

    @Override
    public void init(@SuppressWarnings("unused") final EndpointConfig pConfig) {
        // nop
    }

    @Override
    public boolean willDecode(@SuppressWarnings("unused") final String pRequest) {
        return true; // デコード対象としない場合はfalseを返すが、通常はtrueでOK.
    }

    @Override
    public ClientMessage decode(final String pRequestJsonString) throws DecodeException {
        return JSON.decode(pRequestJsonString, ClientMessage.class);
    }

    @Override
    public void destroy() {
        // nop
    }
}</pre>
<p>なおJSON文字列とJavaオブジェクトの変換には<a href="http://jsonic.osdn.jp/index.html">JSONIC</a>というライブラリを使っています。</p>
<h3>Encoderクラス</h3>
<p>次にEncoderクラスを作ってみます。</p>
<p>Encoderクラスには、Javaオブジェクトをクライアントに送信するメッセージに変換する処理を実装します。このクラスを作成すると、Endpointクラスの@OnMessageコールバックメソッドの戻り値にString以外の型が使えるようになります。</p>
<p>ここではServerMessageというクラスを導入して、Encoderクラスを作ってみます。</p>
<p>ServerMessageクラスも、getterとsetterのみの単なるデータクラスとして作ります。</p>
<pre class="lang:default decode:true ">package sandbox.websocket.json;

import java.util.Date;

public class ServerMessage {
    private Date   date;
    private String body;
    private String senderSessionId;
    // getterとsetterは省略
}</pre>
<p>次に、JsonEncoderを作りましょう。これも使い方は後で説明します。</p>
<pre class="lang:default decode:true" title="JsonEncoder.java">package sandbox.websocket.json;

import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;

import net.arnx.jsonic.JSON;

public class JsonEncoder implements Encoder.Text&lt;ServerMessage&gt; {

    @Override
    public void init(@SuppressWarnings("unused") final EndpointConfig pConfig) {
        // nop
    }

    @Override
    public String encode(final ServerMessage pResponse) throws EncodeException {
        return JSON.encode(pResponse);
    }

    @Override
    public void destroy() {
        // nop
    }
}</pre>
<h3 class="p1">DecoderとEncoderを使う</h3>
<p>作成したDecoderとEncoderはEndpointクラスの中で使います。ポイントは次の２点です。</p>
<ul>
<li>Endpointクラスの@ServerEndpointアノテーションのdecodersとencodersに作ったクラスを指定</li>
<li>@OnMessageコールバックメソッドの引数と戻り値にデータクラスを指定</li>
</ul>
<p>それではサンプルコードを見てみましょう。</p>
<pre class="lang:java decode:true" title="DecEncEndpoint.java">package sandbox.websocket.json;

import java.util.Calendar;

import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/ws/dec-enc" //
, decoders = JsonDecoder.class //
, encoders = JsonEncoder.class)
public class DecEncEndpoint {

    @OnMessage
    public ServerMessage onMessage(final Session pSession, final ClientMessage pRequest) {
        final ServerMessage ret = new ServerMessage();
        ret.setBody("Re: " + pRequest.getBody());
        ret.setDate(Calendar.getInstance().getTime());
        ret.setSenderSessionId(pSession.getId());
        return ret;
    }
}
</pre>
<p>String型がなくなり、データクラスを通して型安全にデータ操作ができるようになりました。</p>
<p>テスト用のHTMLも掲載します。</p>
<pre class="lang:xhtml decode:true " title="dec-enc.html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;title&gt;Decoder/Encoderのサンプル&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;input type="text" name="text" placeholder="送信テキスト"&gt;
    &lt;button type="button" class="btn btn-primary form-control"&gt;送信&lt;/button&gt;
    &lt;script src="https://code.jquery.com/jquery-2.2.0.min.js"&gt;&lt;/script&gt;
    &lt;script&gt;
       var ws = null;
       var onOpen = function() {
           $('button').click(function() {
               ws.send(JSON.stringify({ body: $('input[name="text"]').val() }));
           });
       };
       var onMessage = function(e) {
           alert(e.data);
       };
       var connect = function() {
           ws = new WebSocket('ws://localhost:' + location.port + '/ws/dec-enc');
           ws.onopen = onOpen;
           ws.onmessage = onMessage;
       };
       connect();
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>動作させてみると、JSON形式のデータをやり取り出来ていることが分かると思います。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2016/01/dec-enc.png"><img class="alignnone size-full wp-image-2086" src="https://cloudear.jp/blog/wp-content/uploads/2016/01/dec-enc.png" alt="dec-enc" width="607" height="395" /></a></p>
<p>&nbsp;</p>
<h3>データ変換の流れのまとめ</h3>
<p>登場人物が多くなり少し複雑になったため、データ変換の流れを整理してみました。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2016/01/websocket_dec_enc_flow.png"><img class="alignnone size-full wp-image-2084" src="https://cloudear.jp/blog/wp-content/uploads/2016/01/websocket_dec_enc_flow.png" alt="websocket_dec_enc_flow" width="465" height="496" /></a></p>
<p>&nbsp;</p>
<p>変換処理の流れと、Decoder/Encoderがどのような役割を担っているかを理解いただけたでしょうか。</p>
<h2>最後に</h2>
<p>以上、JavaEEのWebSocketに関する機能をご紹介しました。</p>
<p>実戦ではもっとたくさんのことに気を配る必要があります。例えばエラー処理やスケーリング、認証、リクエスト内容の解析などの処理が必要です。</p>
<p>しかしWebSocketの根幹となる機能は、本エントリでご紹介した機能で充分カバーされていると思います。JavaEEで作るWebアプリケーションにもどんどんWebSocketを取り入れて、新しいユーザ体験を提供していきましょう。</p>
]]></content:encoded>
			<wfw:commentRss>https://cloudear.jp/blog/?feed=rss2&#038;p=2053</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaEEでもできる！JAX-RSでお手軽REST開発</title>
		<link>https://cloudear.jp/blog/?p=2005</link>
		<comments>https://cloudear.jp/blog/?p=2005#comments</comments>
		<pubDate>Tue, 22 Dec 2015 01:25:02 +0000</pubDate>
		<dc:creator><![CDATA[tomo]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[フレームワーク]]></category>
		<category><![CDATA[プログラム]]></category>

		<guid isPermaLink="false">https://cloudear.jp/blog/?p=2005</guid>
		<description><![CDATA[最近のWebアプリケーションはRESTインターフェイスによるAPIを備えることが多くなってきました。 APIはWebアプリケーションの用途を大きく広げる重要な要素であり、また、これをシンプルなインターフェイスであるRES [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>最近のWebアプリケーションはRESTインターフェイスによるAPIを備えることが多くなってきました。</p>
<p>APIはWebアプリケーションの用途を大きく広げる重要な要素であり、また、これをシンプルなインターフェイスであるREST形式で提供することは、より APIを利用しやすくするための重要な手法となっています。</p>
<p>本エントリではJavaEEでRESTインターフェイスを提供するための仕様である<strong>JAX-RS</strong>をご紹介します。</p>
<p><span id="more-2005"></span></p>
<h2>JAX-RSとは</h2>
<p>前述のように、RESTによるAPI提供の重要性は増すばかりです。JavaEEにおいても、JavaEE6からRESTインターフェイスを開発するための仕様である<strong>JAX-RS</strong>が提供されるようになりました。</p>
<p>JAX-RSの特徴として、アノテーションを使ったシンプルな開発スタイルが挙げられます。まずは基本的な使い方を見てみましょう。</p>
<h2>最小のサンプル</h2>
<p>それではJAX-RSの最小のサンプルを作ってみましょう。JavaEEコンテナ環境下であれば、たった２つのファイルを作るだけで済みます。</p>
<h3>JAX-RSの設定クラス</h3>
<p>まずはJAX-RSの設定を持つクラスを作りましょう。</p>
<pre class="lang:java decode:true">package sandbox.web.api;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/api")
public class RestApplication extends Application {
    // nodef
}
</pre>
<p>ポイントは２つ。</p>
<ol>
<li><code>@ApplicationPath("/api")</code>というアノテーションにより<code>/api</code>以下がJAX-RSで扱うURLになります</li>
<li><code>javax.ws.rs.core.Application</code>クラスを継承します。</li>
</ol>
<p>クラス名はどんな名前でも構いません。また実装は何も必要ありません。</p>
<h3>リソースクラス</h3>
<p>JAX-RSによる開発の主たる作業は、リソースクラスを作ることです。</p>
<p>リソースというのは情報の断片のことで、URLで識別されるものです。リソースクラスは、リソースに対する操作をリクエストに従って処理するクラスとなります。</p>
<p>ここでは次のような仕様のリソースを、リソースクラスで実装してみましょう。</p>
<ul>
<li><code>Hello, World</code>というテキストをリソースとする</li>
<li><code>/api/hello/text</code>というパスに対するGETメソッドでテキストが得られる</li>
<li>テキストのContent-Typeは<code>text/plain</code></li>
</ul>
<p>クラス名は何でもいいのですが、ここでは分かりやすく<code>HelloResource</code>としましょう。</p>
<pre class="lang:java decode:true">package sandbox.web.api;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class HelloResource {

    @Path("/text")
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String asText() {
        return "Hello, World";
    }
}
</pre>
<p>仕様がそのままアノテーションで表現されていますね。</p>
<p>ではブラウザで次のURLにアクセスしてみましょう。</p>
<address><a href="http://localhost:8081/api/hello/text">http://localhost:8081/api/hello/text</a></address>
<p>次のような画面が表示されるはずです。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/12/jax-rs_first.png"><img class="alignnone wp-image-2031 size-full" src="https://cloudear.jp/blog/wp-content/uploads/2015/12/jax-rs_first.png" alt="jax-rs_first" width="325" height="93" /></a></p>
<h2>リソースクラスのポイント</h2>
<p>JAX-RSの根幹、リソースクラスを詳しく見てみましょう。とはいえ非常に直感的なコードになっていますので、読み解きやすいと思います。</p>
<h3>@PathアノテーションとURLの関係</h3>
<p>クラスとメソッドに<code>@Path</code>アノテーションを付与することで、このリソースクラスにアクセスするためのパス（≒URLの一部）を表現しています。</p>
<p>クラス宣言の<code>@Path</code>アノテーションは、このリソースが<code>/hello</code>というパスで表されることを示しています。</p>
<pre class="lang:java decode:true">@Path("/hello")
public class HelloResource</pre>
<p>メソッド宣言の<code>@Path</code>アノテーションは、このリソースに実際にアクセスするためのパスを示しています。</p>
<pre class="lang:java decode:true ">@Path("/text")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String asText()
</pre>
<p>実際にアクセスするためのパスは、JAX-RSの設定クラスに付与した<code>@ApplicationPath</code>アノテーションにも影響されることに注意してください。</p>
<p><code>/api/hello/text</code>というパスの階層毎に対応するアノテーションをまとめてみましたので、イメージしてみてください。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/12/jax-rs_url_path_mapping1.png"><img class="alignnone size-full wp-image-2038" src="https://cloudear.jp/blog/wp-content/uploads/2015/12/jax-rs_url_path_mapping1.png" alt="jax-rs_url_path_mapping" width="778" height="197" /></a></p>
<h3>メソッドに付与された@GET/@Producesアノテーション</h3>
<p>リソースクラスのメソッドには、<code>@Path</code>の他にも２つのアノテーションが付いています。いずれも重要なアノテーションです。</p>
<p><code>@GET</code>アノテーションは、メソッドが動作するHTTPメソッドがGETであることを示しています。HTTPメソッドに該当するアノテーションとして、他にも@PUT/@POST/@DELETEなどがあります。</p>
<p><code>@Produces</code>アノテーションは、このメソッドが返す値をどのようなデータ形式で返すかを示していて、HTTP応答ヘッダ内の<code>Content-Type</code>を指定していることに相当します。</p>
<hr />
<p>&nbsp;</p>
<p>このようにJAX-RSによるREST開発は、<strong>HTTPインターフェイスをアノテーションを駆使して表現する</strong>というスタイルになります。</p>
<p>それではJAX-RSが提供する様々な機能を見ていきましょう。多数の機能があるのですが、重要なものに絞ってご紹介します。</p>
<h2>POSTメソッドに対応する</h2>
<p>POSTメソッドでアクセスされた時に動くメソッドには<code>@POST</code>アノテーションを付与します。</p>
<pre class="lang:java decode:true">@Path("text")
@POST
public void postText(@FormParam("text") final String pText) {
    System.out.println(pText);
}
</pre>
<p>パラメータを<code>@FormParam</code>アノテーションで受け取っています。これは後ほど、もっと詳しく解説します。</p>
<p>同じ考え方で、PUTメソッドやDELETEメソッドにも対応できます。単に<code>@PUT</code>や<code>@DELETE</code>アノテーションを付与すればいいのです。直感的ですね。</p>
<h2>@QueryParamアノテーションでクエリパラメータを受け取る</h2>
<p>クエリパラメータとは、URLの?以降の部分を言います。例えば以下のURLのクエリパラメータは<code>format=json</code>です。</p>
<pre class="lang:default decode:true">http://example.com/api/hello/text?format=json</pre>
<p>これをリソースクラスで受け取るには、メソッド引数に<code>@QueryParam</code>アノテーションを付与します。</p>
<pre class="lang:java decode:true">@Path("/text-with-format")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getTextWithFormat(@QueryParam("format") final String pFormat) {
    return "Hello, World" + "(format=" + pFormat + ")";
}
</pre>
<p>ブラウザで次のURLにアクセスしてみてください。</p>
<address><a href="http://localhost:8081/api/hello/text-with-format?format=json">http://localhost:8081/api/hello/text-with-format?format=json</a></address>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/12/jax-rs_resource-class_queryparameter.png"><img class="alignnone size-full wp-image-2033" src="https://cloudear.jp/blog/wp-content/uploads/2015/12/jax-rs_resource-class_queryparameter.png" alt="jax-rs_resource-class_queryparameter" width="517" height="94" /></a></p>
<p>確かにクエリパラメータが受け取れていますね。</p>
<h2>@FormParamアノテーションでformのパラメータを受け取る</h2>
<p>HTMLのformタグで送信するデータは<code>application/x-www-form-urlencoded</code>という形式であり、次のような書式のデータです。</p>
<pre class="lang:default decode:true">param1=value1&amp;param2=value2</pre>
<p>JAX-RSではこの形式のデータは特別扱いであり、メソッドの引数に<code>@FormParam</code>アノテーションを付与することで値を受け取ることができます。</p>
<pre class="lang:java decode:true">@Path("text")
@POST
@Produces(MediaType.TEXT_PLAIN)
public void postText(@FormParam("text") final String pText) {
    System.out.println(pText);
}</pre>
<h2>少し横道・JAX-RSのクライアントAPIによるテスト</h2>
<p>RESTインターフェイスのテストを実施する際、GETであればブラウザで手軽にテストできますが、POSTやPUT、DELETEはそうはいきません。ところがJAX-RSにはクライアント用のAPIが備わっており、手軽にリソースクラスをテストすることができます。</p>
<p>JAX-RSのクライアント APIを使ってPOSTを送るサンプルを掲載しておきます。</p>
<pre class="lang:java decode:true">public static void main(final String[] pArgs) {
    final Response response = ClientBuilder.newClient() //
            .target("http://localhost:8081/api") // 実行するWeb APIのエントリポイント
            .path("/hello/text") // リクエストを投げるURLのパス部分
            .request(MediaType.TEXT_PLAIN_TYPE) // 受け入れ可能なレスポンス形式(HTTPヘッダでいうAcceptに相当)
            // application/x-www-form-urlencoded形式でデータを作成(HTTPヘッダでいうContent-Typeに相当)し、リクエストを送信.
            .post(Entity.&lt;String&gt; entity("text=hoge", MediaType.APPLICATION_FORM_URLENCODED_TYPE));
    System.out.println(response.getStatusInfo());
}</pre>
<h2>パスパラメータを受け取る</h2>
<p>URLの一部がパラメータになっているケースがよくあります。例えばよくあるブログエントリのURLがこれに相当します。</p>
<p><code>http://example.com/blog/2015/12/17</code></p>
<p>2015年12月17日のエントリという意味ですね。JAX-RSでこのようなパラメータを受け取るには、２つのアノテーションを併用します。</p>
<ol>
<li>メソッドの@PathアノテーションでURLパラメータを表現</li>
<li>メソッド引数に@PathParamアノテーションを付与し値を受け取る</li>
</ol>
<p>以下、サンプルです。</p>
<pre class="lang:java decode:true ">@Path("/date/{year}/{month}/{date}")
@GET
@Produces("text/plain; charset=UTF-8")
public String getDateText( //
        @PathParam("year") final int pYear //
        , @PathParam("month") final int pMonth //
        , @PathParam("date") final int pDate //
) {
    return String.format("%d年%d月%d日", pYear, pMonth, pDate);
}
</pre>
<p><code>@Path</code>アノテーションに<code>{パラメータ名}</code>というスタイルでパラメータを表現しているのが分かると思います。</p>
<p>ブラウザで次のURLにアクセスしてみてください。</p>
<address><a href="http://localhost:8081/api/hello/date/2015/12/17">http://localhost:8081/api/hello/date/2015/12/17</a></address>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/12/jax-rs_pathparam.png"><img class="alignnone size-full wp-image-2034" src="https://cloudear.jp/blog/wp-content/uploads/2015/12/jax-rs_pathparam.png" alt="jax-rs_pathparam" width="456" height="71" /></a></p>
<h2>HTTPリクエストのヘッダ情報を受け取る</h2>
<p>時にはクライアントから送信されてきたHTTPヘッダの情報が必要な時があります。この場合、<code>HttpHeaders</code>型のメソッド引数を作り<code>@Context</code>アノテーションを付与します。すると<code>HttpHeaders</code>を通してヘッダ情報が得られます。</p>
<pre class="lang:java decode:true ">@Path("/headers/{headerName}")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String getRequestHeaderValue( //
        @PathParam("headerName") final String pHeaderName //
        , @Context final HttpHeaders pHeaders) {
    return String.valueOf(pHeaders.getRequestHeader(pHeaderName));
}
</pre>
<p>ブラウザで次のURLにアクセスしてみてください。</p>
<address><a href="http://localhost:8081/api/hello/headers/accept">http://localhost:8081/api/hello/headers/accept</a></address>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/12/jax-rs_header.png"><img class="alignnone size-full wp-image-2035" src="https://cloudear.jp/blog/wp-content/uploads/2015/12/jax-rs_header.png" alt="jax-rs_header" width="526" height="99" /></a></p>
<h2></h2>
<h2>Servlet APIにアクセスする</h2>
<p>リソースクラスの中でServlet APIにアクセスしたい場合、メソッド引数にServlet APIのオブジェクトを指定し、そこに<code>@Context</code>アノテーションを付与します。</p>
<pre class="lang:java decode:true ">@Path("/text")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String asText( //
        @Context final HttpServletRequest pRequest //
        , @Context final ServletContext pContext) {
    System.out.println(pRequest);
    System.out.println(pContext);
    return "Hello, World";
}
</pre>
<p>上記のように、<code>HttpServletRequest</code>と<code>ServletContext</code>は取得可能ですが、<code>HttpSession</code>はこの方法では取得できません。本来、RESTとHttpSessionは相容れないものですのでこの仕様は妥当と言えますが、どうしてもHttpSessionが必要な場合は、次のようにして取得してください。</p>
<pre class="lang:java decode:true">@Path("/session-info")
@GET
@Produces(MediaType.TEXT_PLAIN)
public String sessionInfo(@Context final HttpServletRequest pRequest) {
    return String.valueOf(pRequest.getSession());
}</pre>
<h2>CDIの適用</h2>
<p>リソースクラスはJavaEEコンテナ管理であるためCDI連携が可能です。ただ、CDI対象であることをコンテナに示すために、クラス宣言に<code><span class="s1">@</span>Dependent</code>アノテーションを付与する必要があることに注意してください。</p>
<p>このことを踏まえると、リソースクラスは下記のようなコードになります。</p>
<pre class="lang:java decode:true">@Path("/hello")
@Dependent
public class HelloResource {

    @Inject
    HogeService hogeService;
</pre>
<p>なおCDIの詳しいことについては本ブログの「<a title="JavaEE屈指の便利機能、CDIを触ってみよう" href="https://cloudear.jp/blog/?p=1945">JavaEE屈指の便利機能、CDIを触ってみよう</a>」というエントリをご参照ください。</p>
<h2>JSONでデータをやり取りする</h2>
<p>最後に、実践的な内容としてJSONでデータをやり取りする方法をご紹介します。</p>
<p>昨今のWebAPIの多くはJSON形式でデータをやり取りしますが、JAX-RSはデフォルトではJSONを扱えません。多少の設定追加が必要ですので、この章で見て行きましょう。</p>
<h3>データ変換用のクラスを作成する</h3>
<p>JAX-RSには、Content-Typeに応じてJavaオブジェクトを変換する処理を選択／実行する機能が備わっています。</p>
<p>ここではContent-Typeが<code>application/json</code>の時に動作する変換用クラスを作成します。<code>MessageBodyReader</code>と<code>MessageBodyWriter</code>インターフェイスを実装し、<code>@Provider</code>アノテーションを付与するのがポイントです。</p>
<p>実装すべきメソッドは５つあります。各メソッドの意味はコメントに書いておきました。どれも引数が多く見にくいかもしれませんが、実際のメソッドの中身はどれも１行ですので、臆さず読んでみてください。</p>
<pre class="lang:java decode:true">package sandbox.jax_rs;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;

import net.arnx.jsonic.JSON;

@Provider
@Consumes(MediaType.APPLICATION_JSON) // リクエストのContent-Typeがapplication/jsonの時に当クラスが実行される
@Produces(MediaType.APPLICATION_JSON) // レスポンスのContent-Typeがapplication/jsonの時に当クラスが実行される
public class JsonConverter implements MessageBodyReader&lt;Object&gt;, MessageBodyWriter&lt;Object&gt; {

    /**
     * クライアントに返すデータの長さを返しますが、不明な場合は-1を返します.
     */
    @Override
    public long getSize(final Object pT, final Class&lt;?&gt; pType, final Type pGenericType, final Annotation[] pAnnotations, final MediaType pMediaType) {
        return -1;
    }

    /**
     * クライアントから送られてきたデータのContent-Typeが、このクラスで処理可能かどうかを返します. &lt;br&gt;
     * このクラスの場合、application/jsonを処理するようにします.
     */
    @Override
    public boolean isReadable(final Class&lt;?&gt; pType, final Type pGenericType, final Annotation[] pAnnotations, final MediaType pMediaType) {
        return pMediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE);
    }

    /**
     * クライアントに送り返すデータのContent-Typeが、このクラスで処理可能かどうかを返します. &lt;br&gt;
     * このクラスの場合、application/jsonを処理するようにします.
     */
    @Override
    public boolean isWriteable(final Class&lt;?&gt; pType, final Type pGenericType, final Annotation[] pAnnotations, final MediaType pMediaType) {
        return pMediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE);
    }

    /**
     * クライアントからのデータをJavaオブジェクトに変換して返します. &lt;br&gt;
     * ここではクライアントからのデータをJSONと決め打ちして処理します. &lt;br&gt;
     */
    @Override
    public Object readFrom(final Class&lt;Object&gt; pType, final Type pGenericType, final Annotation[] pAnnotations, final MediaType pMediaType,
            final MultivaluedMap&lt;String, String&gt; pHttpHeaders, final InputStream pEntityStream) throws IOException, WebApplicationException {
        return JSON.decode(pEntityStream, pType);
    }

    /**
     * Javaオブジェクトを変換してクライアントに返します. &lt;br&gt;
     * ここではJSONに変換します. &lt;br&gt;
     */
    @Override
    public void writeTo(final Object pT, final Class&lt;?&gt; pType, final Type pGenericType, final Annotation[] pAnnotations, final MediaType pMediaType,
            final MultivaluedMap&lt;String, Object&gt; pHttpHeaders, final OutputStream pEntityStream) throws IOException, WebApplicationException {
        JSON.encode(pT, pEntityStream);
    }
}
</pre>
<p>なおこJSONとJavaオブジェクトの変換には<a href="http://jsonic.osdn.jp/index.html">JSONIC</a>というライブラリを使っています。</p>
<h3>リソースクラスでJSONレスポンスを返す</h3>
<p>それではリソースクラスにJSON形式でデータを返すメソッドを追加しましょう。</p>
<pre class="lang:java decode:true">@Path("/json")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Map&lt;String, Object&gt; asJson() {
    final Map&lt;String, Object&gt; ret = new HashMap&lt;&gt;();
    ret.put("response", "Hello, World");
    return ret;
}
</pre>
<p><code><span class="s1">@Produces</span><span class="s2">(MediaType.</span>APPLICATION_JSON</code><span class="s2"><code>)</code>というアノテーションにより、レスポンスをJSON形式にすることを示しています。</span></p>
<p>それではブラウザで次のURLにアクセスして下さい。</p>
<address><a href="http://localhost:8081/api/hello/json">http://localhost:8081/api/hello/json</a></address>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/12/jax-rs_json_01.png"><img class="alignnone size-full wp-image-2043" src="https://cloudear.jp/blog/wp-content/uploads/2015/12/jax-rs_json_01.png" alt="jax-rs_json_01" width="879" height="511" /></a></p>
<p>&nbsp;</p>
<p>レスポンスがJSON形式のデータであることや、レスポンスヘッダのContent-Typeがapplication/jsonになっていることが確認できます。</p>
<h3>リソースクラスでJSONを受け取る</h3>
<p>次にJSON形式のデータをPOSTで受け取るメソッドを作ってみましょう。</p>
<pre class="lang:java decode:true">@Path("/json")
@POST
@Consumes(MediaType.APPLICATION_JSON)
public void postJson(final Map&lt;String, Object&gt; pJson) {
    System.out.println(pJson.get("request"));
}
</pre>
<p class="p1"><code><span class="s1">@Consumes</span><span class="s2">(MediaType.</span>APPLICATION_JSON</code><span class="s2"><code>)</code>というアノテーションで、リクエストのContent-Typeがapplication/jsonである場合にこのメソッドが動作することを示しています。</span></p>
<p class="p1">クライアントAPIで動作確認をしてみましょう。</p>
<pre class="lang:java decode:true ">public static void main(final String[] pArgs) {
    final Response response = ClientBuilder.newClient() //
            .target("http://localhost:8081/api") //
            .path("/hello/json") //
            .request() //
            .post(Entity.&lt;String&gt; entity("{ \"request\": \"This is json request.\" }", MediaType.APPLICATION_JSON));
    System.out.println(response.getStatusInfo());
}
</pre>
<p>このメソッドを実行すると、リソースクラスのpostJson()メソッドが動作することが確認できるはずです。</p>
<h2>まとめ</h2>
<p>駆け足でJAX-RSを見てきました。実にシンプルな上、RESTの考え方にマッチした分かりやすい仕様になっているため、学びやすいと思います。</p>
<p>本エントリでは紹介しきれなかった機能の中には、サブリソースやキャッシュ制御、レスポンスの詳細な制御など重要なものがあります。幸い、<a href="http://www.oreilly.co.jp/books/9784873114675/">オライリーから良いJAX-RSの指南書</a>が出ています。分量が少なく読みやすいため、ぜひご一読をおすすめします。</p>
<p>冒頭に書いたように、Web APIの重要性は増すばかりです。JAX-RSを使ってRESTフルなAPIをどんどん開発し、Webサービスの価値を高めましょう。</p>
]]></content:encoded>
			<wfw:commentRss>https://cloudear.jp/blog/?feed=rss2&#038;p=2005</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AWSで簡単にリレーショナルデータベース (RDS編)</title>
		<link>https://cloudear.jp/blog/?p=1980</link>
		<comments>https://cloudear.jp/blog/?p=1980#comments</comments>
		<pubDate>Tue, 01 Dec 2015 04:57:04 +0000</pubDate>
		<dc:creator><![CDATA[hayato]]></dc:creator>
				<category><![CDATA[AWS]]></category>
		<category><![CDATA[サーバー]]></category>
		<category><![CDATA[データベース]]></category>

		<guid isPermaLink="false">https://cloudear.jp/blog/?p=1980</guid>
		<description><![CDATA[みなさんこんにちは。クラウドで簡単にリレーショナルデータベースを設定しようということでAWSのRDSというサービスを利用してサクサクっとデータベースを構築して行きましょう。 マネジメントコンソールよりRDSを選択 &#038;nb [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>みなさんこんにちは。クラウドで簡単にリレーショナルデータベースを設定しようということでAWSのRDSというサービスを利用してサクサクっとデータベースを構築して行きましょう。</p>
<p><span id="more-1980"></span></p>
<p><strong>マネジメントコンソールよりRDSを選択</strong></p>
<p>&nbsp;</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/c35e090509e9415cc9a952196d84336e.png"><img class="alignnone size-full wp-image-1983" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/c35e090509e9415cc9a952196d84336e.png" alt="マネジメントコンソールRDS" width="1224" height="539" /></a></p>
<p>RDSをクリック。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/663c9ff0157b41e1e730e1724ceea334.png"><img class="alignnone size-full wp-image-1985" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/663c9ff0157b41e1e730e1724ceea334.png" alt="RDSスタート" width="1255" height="484" /></a></p>
<p>&nbsp;</p>
<p>今すぐ始めるをクリック</p>
<p><strong>DBの選択をする</strong></p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/aff540014decd1e76ee34d7c4880c60d.png"><img class="alignnone size-full wp-image-1986" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/aff540014decd1e76ee34d7c4880c60d.png" alt="DB選択" width="1231" height="486" /></a></p>
<p>&nbsp;</p>
<p>データベースを選択する。</p>
<p>※今回はpostgreSQLを選択</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/acbcd9b2f7ba01a0ed6001fb71a42424.png"><img class="alignnone size-full wp-image-1987" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/acbcd9b2f7ba01a0ed6001fb71a42424.png" alt="RDSインスタンス" width="1254" height="484" /></a></p>
<p>立ち上げるRDSインスタンスを本番用で立ち上げるかを問われます。</p>
<p>今回は無料枠を使用したいので&#8221;いいえ&#8221;にチェックをつけて&#8221;次のステップ&#8221;をクリック。</p>
<p><strong>RDSの詳細設定</strong></p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/ced3702695da488c4d69b8a6c15b3263.png"><img class="alignnone size-full wp-image-1988" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/ced3702695da488c4d69b8a6c15b3263.png" alt="RDS詳細1" width="1236" height="461" /></a></p>
<p>&nbsp;</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/69c4f7e3bf044e9fa57756fb0c407810.png"><img class="alignnone size-full wp-image-1989" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/69c4f7e3bf044e9fa57756fb0c407810.png" alt="RDS詳細2" width="1230" height="279" /></a></p>
<p>各種設定を行います。</p>
<p>※DBインスタンスのクラスはテスト用なので一番小さいプランにしてます。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/367eb073991bb73d691e0827adccb12d.png"><img class="alignnone size-full wp-image-1990" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/367eb073991bb73d691e0827adccb12d.png" alt="RDS詳細設定1" width="1227" height="443" /></a></p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/4e26bee9edcad4d80c238fb1ae0575f1.png"><img class="alignnone size-full wp-image-1991" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/4e26bee9edcad4d80c238fb1ae0575f1.png" alt="RDS詳細設定2" width="1228" height="326" /></a></p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/350372e59d19ba584a8215f6a1298cb3.png"><img class="alignnone size-full wp-image-1992" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/350372e59d19ba584a8215f6a1298cb3.png" alt="RDS詳細設定3" width="1225" height="344" /></a></p>
<p>VPCセキュリティグループをデフォルトを選択。</p>
<p>DBの名前を決めます。</p>
<p>バックアップの保存期間などは後からでも変更可能です。</p>
<p>DBインスタンスの作成をクリックしてインスタンスを立ち上げましょう。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/fc7f7f828c0c153ef197c8f3471c0d77.png"><img class="alignnone size-full wp-image-1993" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/fc7f7f828c0c153ef197c8f3471c0d77.png" alt="RDS作成中1" width="1229" height="439" /></a></p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/798a26bc55ab57e248f3c42837c8c77d.png"><img class="alignnone size-full wp-image-1994" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/798a26bc55ab57e248f3c42837c8c77d.png" alt="RDS作成中2" width="1220" height="130" /></a></p>
<p>DBインスタンスを作成中となります。</p>
<p>DBインスタンスの表示をクリックしてみましょう。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/72a341ede6d198355e85bb89c084bdd3.png"><img class="alignnone size-full wp-image-1995" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/72a341ede6d198355e85bb89c084bdd3.png" alt="DBダッシュボード" width="1239" height="443" /></a></p>
<p>ステータスが作成中となっていますね？</p>
<p>5分ほど待っていると、、、</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/a06fe7e1172ea224449ec2989c37be271.png"><img class="alignnone size-full wp-image-1999" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/a06fe7e1172ea224449ec2989c37be271.png" alt="DBダッシュボード2" width="1239" height="476" /></a></p>
<p>ステータスが&#8221;利用可能&#8221;になりました。</p>
<p>これでもうpostgreSQLが使えるようになりました。</p>
<p>せっかくなので作ったdbに接続してみます。</p>
<p><strong>pgAdminでDB(RDS)に接続</strong></p>
<p><span class="emphasis"><em>pgAdmin</em></span> は<a title="pgAdmin インストール" href="http://www.pgadmin.org/">http://www.pgadmin.org/</a>からインストールできます。</p>
<p>pgAdminを起動したらファイル→サーバーの追加を選択。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/pgAdmin2.png"><img class="alignnone size-full wp-image-2000" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/pgAdmin2.png" alt="pgAdmin2" width="592" height="535" /></a></p>
<p>RDSのダッシュボードにてDB インスタンスのエンドポイントが記載されています。</p>
<p>それをpgAdminのダイアログのホストへ入力します。</p>
<p>※コロンとポート番号は含めない</p>
<p>先ほど決めたユーザー名、パスワード、port番号を入力します。</p>
<p>OKを選択。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/6c82d8a5ca75a8f014bd2a59cb7d36cf.png"><img class="alignnone size-medium wp-image-2001" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/6c82d8a5ca75a8f014bd2a59cb7d36cf.png" alt="スクリーンショット 2015-11-24 14.50.32" width="300" height="83" /></a></p>
<p>&nbsp;</p>
<p>接続されるとDBが追加されます。</p>
<p>&nbsp;</p>
<p>※server dosen&#8217;t listenとエラーになる場合はRDSのセキュリティグループで5432のポートを開放しましょう。</p>
]]></content:encoded>
			<wfw:commentRss>https://cloudear.jp/blog/?feed=rss2&#038;p=1980</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaEE屈指の便利機能、CDIを触ってみよう</title>
		<link>https://cloudear.jp/blog/?p=1945</link>
		<comments>https://cloudear.jp/blog/?p=1945#comments</comments>
		<pubDate>Fri, 20 Nov 2015 03:47:24 +0000</pubDate>
		<dc:creator><![CDATA[tomo]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[フレームワーク]]></category>

		<guid isPermaLink="false">https://cloudear.jp/blog/?p=1945</guid>
		<description><![CDATA[本エントリではJavaEEの中でも屈指の便利機能、CDI（Contexts and Dependency Injection）を紹介します。 なお、本エントリではJavaEE7に搭載されているCDI1.1を前提とします。 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>本エントリではJavaEEの中でも屈指の便利機能、<strong>CDI</strong>（<strong>Contexts and Dependency Injection）</strong>を紹介します。</p>
<p>なお、本エントリではJavaEE7に搭載されているCDI1.1を前提とします。JavaEE6はCDI1.0となり、本エントリのコードに一部動作しなくなる箇所がありますのでご注意ください。</p>
<p><span id="more-1945"></span></p>
<h2>CDIとは</h2>
<p>CDIとは、JavaEE6から採用された、JavaEEにおけるDI機能のことです。DIについての詳しいことは<a title="依存性注入（DIコンテナ）について" href="https://cloudear.jp/blog/?p=1247">こちらのエントリ</a>をご覧いただくとして、本エントリではCDIの特筆すべき機能に焦点を当てることにします。</p>
<h2>CDIの真髄・スコープ管理</h2>
<p>CDIの真髄はインスタンスの存命期間、すなわちスコープを管理してくれることです。</p>
<p>Webアプリケーションを作っていると「このオブジェクトの持つ情報をしばらくの間保持したままにしておきたい」と思うことがあります。例えば次のようなケースです。</p>
<h3>設定ファイルの内容</h3>
<p>Webアプリ起動中は不変な情報であり、一度ファイルから読み込んだ内容をメモリにキャッシュして読み取り専用情報として使いたい。いわゆるシングルトンとして扱いたい。</p>
<h3>DBに格納されたコードテーブル（コード値をラベル文字列に変換するテーブル）の内容</h3>
<p>変更される可能性があるが、だからと言って頻繁に使う処理だから毎回DBにアクセスするのは遅すぎる・・・リクエストの先頭でまとめてDBから読み込んでリクエスト中のみ有効なキャッシュとしたい。</p>
<h2>CDIがない場合</h2>
<p>CDIなしに前述のような要求を実現するのは不可能ではありませんが、とても間違えやすく、また変更しにくいプログラムが必要です。試しにリクエスト単位で動作するカウンターを持つクラスを作ってみましょう。</p>
<p>まずはServletです。</p>
<pre class="lang:java decode:true">@WebServlet(urlPatterns = "/cdi-sample")
public class CDISampleServlet extends HttpServlet {

    @Override
    protected void doGet(final HttpServletRequest pReq, final HttpServletResponse pResp) throws ServletException, IOException {
        ScopedService.Factory.get(pReq).countUp();
        ScopedService.Factory.get(pReq).countUp();
        pResp.setContentType("text/plain");
        pResp.getWriter().println("Counter Value -&gt; " + ScopedService.Factory.get(pReq).getCounter());
    }
}
</pre>
<p>次にServletから使うServiceです。</p>
<pre class="lang:java decode:true">public class ScopedService {

    private int counter = 0;

    public void countUp() {
        this.counter++;
    }

    public int getCounter() {
        return this.counter;
    }

    public static class Factory {

        public static ScopedService get(final HttpServletRequest pReq) {
            final String KEY = ScopedService.class.getName();
            ScopedService ret = (ScopedService) pReq.getAttribute(KEY);
            if (ret == null) {
                ret = new ScopedService();
                pReq.setAttribute(KEY, ret);
            }
            return ret;
        }
    }
}
</pre>
<p>いかがでしょうか？確かにこれで「リクエスト単位で状態を保持する」という要求を実現できたのですが、かなりいや〜な感じの実装になっていますね。</p>
<ul>
<li>ScopedService.Factory.get()メソッドの実装が煩雑。そもそもこんなメソッドを作らないといけないのが手間</li>
<li>もしスコープに変更が入ったら・・・例えばシングルトンに変更する場合、マルチスレッドに気を払いながらScopedService.Factory.get()メソッドの中を修正する必要がある</li>
</ul>
<p>これをCDIを使って書き換えてみましょう。</p>
<h2>CDIがある場合</h2>
<p>まずServletです。</p>
<pre class="lang:java decode:true ">@WebServlet(urlPatterns = "/cdi-sample")
public class CDISampleServlet extends HttpServlet {

    @javax.inject.Inject
    ScopedService scopedService;

    @Override
    protected void doGet(final HttpServletRequest pReq, final HttpServletResponse pResp) throws ServletException, IOException {
        this.scopedService.countUp();
        this.scopedService.countUp();
        pResp.setContentType("text/plain");
        pResp.getWriter().println("Counter Value -&gt; " + this.scopedService.getCounter());
    }
}
</pre>
<p>@Injectアノテーションが最大のポイントです。このアノテーションが付いているインスタンス変数には、CDIが適切なオブジェクトをDIしてくれます。</p>
<p>次にServletから使うServiceです。</p>
<pre class="lang:java decode:true">@javax.enterprise.context.RequestScoped
public class ScopedService {

    private int counter = 0;

    public void countUp() {
        this.counter++;
    }

    public int getCounter() {
        return this.counter;
    }
}
</pre>
<p>こちらは@RequestScopedアノテーションが最大のポイントです。このアノテーションが付いているクラスのオブジェクトは、CDIにより同じリクエスト内では使い回されます。つまり<strong>このクラスのオブジェクトはリクエストスコープになる</strong>わけです。</p>
<p>そしてアノテーションが付いている以外は、ごくごく普通のクラスになりました。</p>
<h2>スコープを変更する</h2>
<p>CDIのすごいところは、アノテーションを変えるだけでスコープを簡単に変えることができる点です。先ほどのScopedServiceをリクエストスコープからアプリケーションスコープ（＝シングルトン、Webアプリ中に１つしかないオブジェクト）に変更してみます。</p>
<pre class="lang:java decode:true">@javax.enterprise.context.ApplicationScoped
public class ScopedService {

    private int counter = 0;

    public void countUp() {
        this.counter++;
    }

    public int getCounter() {
        return this.counter;
    }
}
</pre>
<p>全コードを掲載するのはバカバカしいのですが、あえて掲載しました。変わったのは先頭のアノテーションのみです。</p>
<p>たったこれだけでスコープが変わりました。Servlet側は何も変更していません。すごいですね。</p>
<h2>少し複雑な話・スコープの短いオブジェクトのDIがなぜ可能か</h2>
<p>さて、CDIの凄さを知るために、少し複雑な話をします。</p>
<p>これまでの例では、何気なくServletにリクエストスコープのServiceをDIしていました。Servletはアプリケーションスコープで動作します。そこにリクエストスコープのオブジェクトをDIして、正しく動作するのでしょうか？</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/CDI_singleton_request.png"><img class="alignnone size-full wp-image-1955" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/CDI_singleton_request.png" alt="CDI_singleton_request" width="735" height="442" /></a></p>
<p>結論から言うと、もちろん正しく動作します。CDIはこのようなケース、つまり自身よりスコープの短いオブジェクトをDIするケースでは、「プロキシ」というオブジェクトを生成し、その中で適切に処理対象を振り分けるのです。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/11/CDI_proxy.png"><img class="alignnone size-full wp-image-1956" src="https://cloudear.jp/blog/wp-content/uploads/2015/11/CDI_proxy.png" alt="CDI_proxy" width="709" height="596" /></a></p>
<p>裏でこれだけのことをやってのけるCDIですが、使う側はアノテーションを付けるだけ！</p>
<p>驚異の高機能をごく簡単な記述で使う・・・CDIってすごいですね。</p>
<h2>@Injectの別の付け方</h2>
<p>ここまで@Injectアノテーションはインスタンス変数に付けていましたが、コンストラクタやsetterに付けることも出来ます。この場合、DIしたいオブジェクト引数に取るようにします。次の例はコンストラクタに付ける場合のサンプルです。</p>
<pre class="lang:java decode:true">@WebServlet(urlPatterns = "/cdi-sample")
public class CDISampleServlet extends HttpServlet {

    private final ScopedService scopedService;

    @javax.inject.Inject
    public CDISampleServlet(final ScopedService pScopedService) {
        this.scopedService = pScopedService;
    }

    @Override
    protected void doGet(final HttpServletRequest pReq, final HttpServletResponse pResp) throws ServletException, IOException {
        this.scopedService.countUp();
        this.scopedService.countUp();
        pResp.setContentType("text/plain");
        pResp.getWriter().println("Counter Value -&gt; " + this.scopedService.getCounter());
    }
}</pre>
<p>こちらの方がテストしやすくなるため、より望ましいと思います。</p>
<h2>CDIの美点</h2>
<h3>スコープ制御が不要に</h3>
<p>これまで見てきた通り、スコープ制御のための複雑なコードが不要になります。</p>
<h3>クラスの実装がシンプルに</h3>
<p>スコープ制御のコードがなくなり、クラスには本来の処理のみを記述すればよくなります。これによりコードがシンプルになります。</p>
<h3>テスタビリティが向上</h3>
<p>これはCDIというよりはDIの美点です。</p>
<p>@Injectを付けておくと、実行時に適切なオブジェクトを生成／注入（＝インジェクション）してくれるのがDIの機能ですが、これにより<strong>newを書かずに済み</strong>、状況に応じたオブジェクトの差し替えが可能になります。このためテスト用のモックを適用しやすくなり、テスタビリティが向上します。</p>
<p>この辺りの話は<a href="http://builder.japan.zdnet.com/sp_oracle/weblogic/35045391/">「newの連鎖」という言葉で解説されているWebページ</a>がありますので参考にしてください。</p>
<h2>CDIのその他の機能</h2>
<p>CDIには他にも便利な機能が多数あります。中でも有用な２つの機能をご紹介します。</p>
<h3>AOPインターセプター</h3>
<p>メソッドの前後に任意の処理を織り込むことをAOP、織り込む処理のことをインターセプターと言います。CDIでは簡単にインターセプターを作ることができます。</p>
<p>インターセプターを作るには次の２つのモジュールを作成します。</p>
<ol>
<li>アノテーション：メソッドにどのインターセプターを適用するか、というマーカーとなるアノテーションを作ります。</li>
<li>インターセプタークラス：メソッドの前後に織り込む処理を実装します。</li>
</ol>
<p>ここではメソッドの名前と実行後の戻り値を、コンソールに表示するインターセプターを作ってみます。</p>
<h4>マーカーとなるアノテーション</h4>
<pre class="lang:java decode:true">package javaee.sandbox.interceptor;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.interceptor.InterceptorBinding;

@InterceptorBinding
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodPrint {
    // nodef
}</pre>
<p>マーカーとなるアノテーションはほとんどん場合このパターンで実装できます。</p>
<h4>インターセプタークラス</h4>
<pre class="lang:java decode:true">package javaee.sandbox.interceptor;

import javax.enterprise.context.Dependent;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

@Interceptor
@MethodPrint
@Dependent
public class MethodPrintInterceptor {

    @AroundInvoke
    Object intercept(final InvocationContext pContext) throws Exception {
        System.out.println(pContext.getMethod().getName() + "メソッド実行開始.");
        final Object ret = pContext.proceed();
        System.out.println(pContext.getMethod().getName() + "メソッド実行終了. 戻り値 -&gt; " + ret);
        return ret;
    }
}</pre>
<p>型宣言に付いた２つのアノテーション、@Interceptorと先に作ったマーカーとなるアノテーション（@MethodPrint）がポイントです。@Interceptorにより、このクラスがインターセプタークラスであると宣言しています。また@MethodPrintにより、どのマーカーアノテーションに反応するのかを示しています。</p>
<p>織り込む処理はメソッドとして実装します。次のようなルールで作成します。</p>
<ul>
<li>@AroundInvokeアノテーションを付与</li>
<li>名前は何でもい</li>
<li>戻り値はObject型</li>
<li>引数はInvocationContext型１つのみ</li>
<li>本来のメソッドを実行するにはInvocationContext#proceed()メソッドを実行</li>
</ul>
<p>ここでは、本来のメソッドの実行前後にコンソール表示を行っています。また、InvocationContext#proceed()メソッドの戻り値は本来のメソッドの戻り値です。場合によってはこの戻り値を加工して差し替える、などということも可能です。</p>
<h4>beans.xmlに追記</h4>
<p>インターセプターを使うにはbeans.xmlにクラス名を書いておく必要があります。beans.xmlはWEB-INFディレクトリ直下に起きます。内容は以下のようにします。</p>
<pre class="lang:xhtml decode:true ">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans bean-discovery-mode="annotated"
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"&gt;

    &lt;interceptors&gt;
        &lt;class&gt;javaee.sandbox.interceptor.MethodPrintInterceptor&lt;/class&gt;
    &lt;/interceptors&gt;

&lt;/beans&gt;</pre>
<p>&lt;class&gt;タグにインターセプタークラスのフルネームを書きます。</p>
<h4>インターセプタークラスを使う</h4>
<p>インターセプターで処理を織り込みたいメソッドにマーカーとなるアノテーション（ここでは@MethodPring）を付与するだけで使えます。例を見てみましょう。</p>
<pre class="lang:java decode:true">import javaee.sandbox.interceptor.MethodPrint;

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class ScopedService {

    private int counter = 0;

    public void countUp() {
        this.counter++;
    }

    @MethodPrint
    public int getCounter() {
        return this.counter;
    }
}</pre>
<p>たったこれだけです。簡単ですね。このクラスを実行すると、コンソールに次のように表示されます。</p>
<pre class="lang:default decode:true ">getCounterメソッド実行開始.
getCounterメソッド実行終了. 戻り値 -&gt; 4</pre>
<h3>@PostConstruct</h3>
<p>この機能は便利・・・と言うより知らないと困るかもしれません。CDIで管理されるオブジェクトの初期化タイミングで何か処理をしたい、というのはよくあることです。例えば設定ファイルの中身をロードしてキャッシュしておく、というケースです。しかし、コンストラクタでは初期化できないことが多いです。コンストラクタの中ではDI対象のフィールドが初期化されていないことが多いからです。例えば下記のようなケースです。</p>
<pre class="lang:java decode:true">@ApplicationScoped
public class NonInitializationService {

    @Inject
    ConfigurationLoader               loader;

    private final Map&lt;String, String&gt; configurationCache;

    public NonInitializationService() {
        // 下記はNG.
        // コンストラクタの中では this.service が null なので.
        this.configurationCache = this.loader.loadConfiguration();
    }
}
</pre>
<p>このような場合に使えるのが@PostConstructアノテーションです。このアノテーションを付けたメソッドは、全てのDIが完了した後に呼び出されますので、初期化処理には最適です。先ほどの例は次のように書き直すとうまく動作します。</p>
<pre class="lang:java decode:true ">@ApplicationScoped
public class InitializationService {

    @Inject
    ConfigurationLoader         loader;

    private Map&lt;String, String&gt; configurationCache;

    @PostConstruct
    void postConstruct() {
        this.configurationCache = this.loader.loadConfiguration();
    }
}
</pre>
<h2> 詳しい文献</h2>
<p>本エントリではCDIを凝縮したエッセンスをご紹介しました。さらに詳しい情報を得たい方のために文献をご紹介しておきます。</p>
<h3>Oracleによるチュートリアル（英語）</h3>
<p><a href="https://docs.oracle.com/javaee/6/tutorial/doc/gjbnr.html">こちらのページ</a>へどうぞ。</p>
<h3>日本語での説明</h3>
<p><a href="http://qiita.com/opengl-8080/items/431de9175dca33a09ba8">Qiitaの記事「JavaEE使い方メモ（CDI）」</a>が最も詳しいと思われます。</p>
<h2>まとめ</h2>
<p>CDIのもたらすインパクトは大きいものです。アノテーションさえ付ければスコープ管理のための余計なコーディングが必要なく、コアな実装に集中することができます。結果、テストのしやすさや変更のしやすさ、コードの見通しの良さなど、様々な恩恵が得られるはずです。</p>
<p>うまく使って楽にWebアプリケーションを開発しましょう。</p>
]]></content:encoded>
			<wfw:commentRss>https://cloudear.jp/blog/?feed=rss2&#038;p=1945</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>画像サイズが合わない、イメージに合う画像がない、ちょっと足りないをどうするか？</title>
		<link>https://cloudear.jp/blog/?p=1873</link>
		<comments>https://cloudear.jp/blog/?p=1873#comments</comments>
		<pubDate>Mon, 09 Nov 2015 02:42:53 +0000</pubDate>
		<dc:creator><![CDATA[Tammys]]></dc:creator>
				<category><![CDATA[PhotoShop]]></category>
		<category><![CDATA[デザイン]]></category>
		<category><![CDATA[写真]]></category>

		<guid isPermaLink="false">https://cloudear.jp/blog/?p=1873</guid>
		<description><![CDATA[イメージに合う画像があるけどレイアウトのサイズに合わない。トリミング出来そうにもない。文字を入れるスペースが無い。お客様からもらった画像が小さい。 そんなちょっと足りない経験をしたことありませんか？ そんな時の対処法を今 [&#8230;]]]></description>
				<content:encoded><![CDATA[<div>イメージに合う画像があるけどレイアウトのサイズに合わない。トリミング出来そうにもない。文字を入れるスペースが無い。お客様からもらった画像が小さい。</div>
<div></div>
<div>そんなちょっと足りない経験をしたことありませんか？</div>
<div></div>
<div>そんな時の対処法を今回はお教えします。</div>
<div></div>
<p><span id="more-1873"></span></p>
<div></div>
<h2>キャンパスサイズを変える</h2>
<div></div>
<div>基本のおさらい</div>
<div><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/8b14caeb0dc9b52d921a31f271f3efc3.jpg"><img class="aligncenter size-full wp-image-1876" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/8b14caeb0dc9b52d921a31f271f3efc3.jpg" alt="ドラゲナイ加工前" width="1382" height="922" /></a></div>
<div></div>
<div></div>
<div>まずはイメージから「カンバスサイズを調整」を開く。（ショートカットで カンバスサイズ変更は「Cmd＋Opt＋C」）</div>
<div></div>
<div><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/67af76ae599960d2383e95c5acc8e58a.png"><img class="aligncenter size-full wp-image-1881" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/67af76ae599960d2383e95c5acc8e58a.png" alt="スクリーンショット 2015-10-28 23.16.56" width="965" height="646" /></a></div>
<div></div>
<div></div>
<div>今回は現在のサイズに幅を広げたいから幅を100mm追加。現在の大きさを基準にしたい場合は相対にチェックをいれる。基準位置を選択することで伸ばしたい方向を指定することができます。カンバス拡張カラーは拡張した部分の色を選べるのです。今回は説明がわかりやすいよう白を選択しましたが、こういう背景が黒の画像なら、拡張色に黒を選べばそれで画像加工が終わる時もあります。</div>
<div></div>
<div><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/1b734bb5cd3d5b7016a6d47691e2938f.png"><img class="aligncenter size-full wp-image-1885" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/1b734bb5cd3d5b7016a6d47691e2938f.png" alt="スクリーンショット 2015-10-28 23.17.54" width="975" height="649" /></a></div>
<div></div>
<div></div>
<div></div>
<div>OKをクリックすると。幅が広がりました。右側の白い部分が拡張された部分です。</div>
<div></div>
<div><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/63f1a382301693b1a3b536bf0caefb1c.png"><img class="aligncenter size-full wp-image-1884" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/63f1a382301693b1a3b536bf0caefb1c.png" alt="スクリーンショット 2015-10-28 23.19.49" width="1074" height="597" /></a></div>
<div></div>
<div>さて、この拡張された部分を塗りつぶしましょう。白の部分を選択して、編集から「塗りつぶし」をクリック。内容の使用を「コンテンツに応じる」を選択してOKをクリック。（ショートカットでコンテンツに応じて塗りつぶしは「Shift＋F5」）</div>
<div></div>
<div><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/55cf2fc53d500665ce24ec273112ca261.png"><img class="aligncenter size-full wp-image-1888" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/55cf2fc53d500665ce24ec273112ca261.png" alt="スクリーンショット 2015-10-28 23.20.40" width="1059" height="607" /></a></div>
<div></div>
<div>はい、できあがり！これでタイトルを入れることができました。</div>
<div></div>
<div><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/53f042c1681d4c62c97eabc53591cdc7.png"><img class="aligncenter size-full wp-image-1891" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/53f042c1681d4c62c97eabc53591cdc7.png" alt="スクリーンショット 2015-10-28 23.36.15" width="973" height="459" /></a></div>
<div></div>
<h2>コンテンツに応じて塗りつぶしを使いこなせ！</h2>
<div></div>
<div>さらっと使ってしまいましたが、「コンテンツに応じて塗りつぶし」は大変便利な機能でして</div>
<div> 例えばこんな画像</div>
<div><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/342d7834f2c82554e3fe0d929cd2b31b.png"><img class="aligncenter size-full wp-image-1894" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/342d7834f2c82554e3fe0d929cd2b31b.png" alt="スクリーンショット 2015-10-29 0.03.39" width="923" height="621" /></a></div>
<div></div>
<div></div>
<div>先ほどと同じく、幅を広げて「コンテンツに応じて塗りつぶし」で、はい！いっちょあがり。一番上の段の線のズレは修正しないと駄目ですが、他はきれいに合成されています。</div>
<div></div>
<div></div>
<div><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/5a8d7c664c4d5df62bf450ee39599eda.png"><img class="aligncenter size-full wp-image-1896" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/5a8d7c664c4d5df62bf450ee39599eda.png" alt="スクリーンショット 2015-10-29 0.06.31" width="884" height="468" /></a></div>
<div></div>
<div></div>
<div> 「コンテンツに応じて塗りつぶし」はいらないものを消すときにも使えますね。風景の電線、室内のポスター、偶然写りこんだ人物。既存の画像に入っている文字を消して使いまわしたい、なんていうときもバッチリです。消したいものの範囲を囲って 「コンテンツに応じて塗りつぶし」や「コンテンツに応じたパッチ」を使用するだけで魔法のように消えてしまいます。</div>
<div> 「コンテンツに応じて塗りつぶし」は背景がある程度複雑でも使えるのがいいところです。</div>
<div>ごちゃつきすぎてると、びっくりするような合成されるときもありますが……。そういうときは地道にコピースタンプなどでコツコツ直しましょう。</div>
<div></div>
<h2>コンテンツに応じたパッチも覚えちゃおう！</h2>
<div>一応「コンテンツに応じたパッチ」の使い方も解説しておきましょう。</div>
<div> パッチツールをクリックしたら、複製元を囲って選びます。</div>
<div></div>
<div><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/c6ef3fe1351c8b241262a8f3543a9d1c.jpg"><img class="aligncenter size-full wp-image-1927" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/c6ef3fe1351c8b241262a8f3543a9d1c.jpg" alt="１ぱっち" width="1076" height="733" /></a></div>
<div></div>
<div> 囲った部分をドラッグ&amp;ドロップでスライドさせると……コピーされました。</div>
<div>
<div></div>
<div>パッチツールにはツールオプションに「適応」という項目があります。</div>
<ul>
<li>「厳密に」や「非常に厳密に」を選択すると、周囲となじませる範囲が狭く、元画像はある程度保持されるが、なじみきらず違和感がでる場合がある。</li>
<li>「ゆるく」や「非常にゆるく」を選択すると、移動先の背景となじませる範囲が広く、自然になじませることになります。ただし元画像は保持されず、合成で失敗することも。</li>
</ul>
</div>
<div>どれがなじむか ためしてみてくださいね。</div>
<div><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/0d64789f378ac2eb4d58cc468df6fa4e.jpg"><img class="aligncenter size-full wp-image-1929" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/0d64789f378ac2eb4d58cc468df6fa4e.jpg" alt="ぱっち２" width="1090" height="769" /></a></div>
<div></div>
<div>
<h2>コンテンツに応じて拡大縮小という手もあり！</h2>
<p>この画像を大きくしてみましょう。先ほどと同じくカンバスサイズは大きくしました。</p>
<p><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/876b905a95313c15b7d6727b07ae6ec2.jpg"><img class="aligncenter size-full wp-image-1905" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/876b905a95313c15b7d6727b07ae6ec2.jpg" alt="海辺元" width="2000" height="1423" /></a></p>
</div>
<div></div>
<div>元の画像部分を選択し、編集メニューから「コンテンツに応じて拡大縮小」を選択します。</div>
<div></div>
<div><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/967aaa2d548e9ea6259ce455ef2b1b0f.jpg"><img class="aligncenter size-full wp-image-1906" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/967aaa2d548e9ea6259ce455ef2b1b0f.jpg" alt="海辺１" width="1145" height="861" /></a></div>
<div></div>
<div>元の画像部分から、ぐいっとドラックすると好きなだけ拡大縮小できます。ここで忘れてはいけないのが、人物が入っている画像の場合は上の人間マークをクリックすること。これで人物には影響が無い状態で拡大縮小できます。</div>
<div></div>
<div><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/0076967ef2111eace086765f35f8f344.jpg"><img class="aligncenter size-full wp-image-1918" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/0076967ef2111eace086765f35f8f344.jpg" alt="海辺３" width="1143" height="842" /></a></div>
<div></div>
<div>わかりづらいかもしれませんが、「スキントーンを保護」をしないで拡大すると……人物が太って、いや横に間延びしてしまっていますね。</div>
<div></div>
<div><a href="https://cloudear.jp/blog/wp-content/uploads/2015/10/e3800bccec32854d7da6283f7187e943.jpg"><img class="aligncenter size-full wp-image-1921" src="https://cloudear.jp/blog/wp-content/uploads/2015/10/e3800bccec32854d7da6283f7187e943.jpg" alt="海辺５" width="1012" height="530" /></a></div>
<h2></h2>
<div></div>
<h2>まとめ　使い分けの秘訣</h2>
<ul>
<li>「コンテンツに応じて塗りつぶし」→周囲のパターンを読み取って、カンバスの広げた部分のみ塗りつぶす。（元の画像には影響は無い）ある程度は複雑な背景でも適用できる。うまくいかないときは「コンテンツに応じたパッチツール」を使うのも良い。</li>
</ul>
<ul>
<li> 「コンテンツに応じて拡大縮小」→人物など保護をかけたもの以外の背景を拡大縮小。背景の画質は少々落ちる。</li>
</ul>
<p>物によってどれが合うか違いますので色々試してみてください。</p>
<p>基礎的なことかもしれませんが、画像のサイズを変えることが出来ればデザインの幅がひろがります。これでちょっと足りないを乗り切ってくださいね。</p>
<p>&nbsp;</p>
<p>今回の写真は<a href="https://www.pakutaso.com">フリー写真素材ぱくたそ </a>さんの素材を使わせていただきました。</p>
<div></div>
]]></content:encoded>
			<wfw:commentRss>https://cloudear.jp/blog/?feed=rss2&#038;p=1873</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
