Archive for 2013年5月11日
JJUG CCC 2013 Spring の発表資料について
本日、JJUG CCC 2013 Spring が開催されました。Oracle からはUS Oracle Corporation からJim Weaver (Twitter : @JavaFXpert) が基調講演で「What’s New for JavaFX in JDK 8」を発表し、午後一のセッションで、「Java EE 6 から Java EE 7 に向かって」というセッションを担当しそれぞれ発表しました。2人の発表資料を公開しましたのでご報告します。
(※ 私のプレゼン資料ですが、SlideShare にアップロードした際、SlideShare 側の問題で、フォントが無いせいか、私が使用しているオリジナル・フォントからは変わって表示されています。その点ご了承頂ければ幸いです。)
基調講演-2 What’s New for JavaFX in JDK 8
H-1 Java EE 6 から Java EE 7 に向かって
今日の私のプレゼン中で行った EL(Expression Language) 3.0のデモのソース・コードも下記に公開します。デモ用に簡単に作ったものであるため、本来 JPA で DB 接続すべき所を簡単にダミーデータ(Person#createDummyData())を作成しています。
本コードは JSF 2.0 と CDI をご存知の方であれば容易にご理解いただけるかと思いますが、「全データ抽出」のボタンを押下すると、CDI の getAllData() が呼び出され、indexManagedBean.data(ArrayList) に全データがコピーされ、その一覧が dataTable に表示されます。
次に、「年齢フィルタ」のテキストフィールド(デフォルト:0)に対して年齢を入力すると、入力された年齢以上のデータを表示しています。内部的には Ajax を使って、入力された年齢情報(indexManagedBean.ageFileter)をサーバに送信し、Ajax のリスナーとして定義しているindexManagedBean.updateData()を実行していいます。ただ、indexManagedBean.updateData()は処理は何もしていません、ここでは execute=”ageFilter” をサーバに送信し、その結果を render=”tabledata” 、つまり dataTable の内容を更新するためだけにupdateData()を呼び出しています。
<h:dataTable id="tabledata" value="#{afilter = indexManagedBean.ageFileter;indexManagedBean.data.stream().filter(p-> p.age >= afilter).toList()}" var="person" border="1">
この例では、一度 DBに対してクエリを実行し、その結果をコレクションにコピーした後、さらにそのコピーしたデータに対して絞り込みを行っています。DB に対して再度クエリをなげるのではなく、EL 3.0 の Lambda 式を使って、一旦取得したデータを元に再フィルタリングを 行っています。
セッション中でも話をしましたが EL 3.0 で Lambda 式(及び LINQ 式)が使えるようになった事でビューにロジックを埋め込む事が可能になりますが、あまりやりすぎると可読性の低下にもつながりますので使う範囲はよくご検討頂いた方がよいのではないかと思います。(※ .Net の LINQ 式は DB に対しても操作可能ですが、EL 3.0 における LINQ 式はコレクションに対してのみ有効です。)
今回の例では、一旦取得したデータのフィルタンリグ等でご使用頂く事で、DB に対する負荷、インメモリ・グリッドにあるキャッシュから取得するよりもパフォーマンスがよくなる事を想定し記載しています。なぜならばヒープメモリ内にあるデータを直接操作する方がパフォーマンス的に優れるためです。(※ コレクションに対して有効な操作である事をご認識頂き用途は十分にご検討ください。)
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" > <h:head> <title>Facelet Title</title> </h:head> <h:body> <h:form> <h:commandButton value="全データ抽出" action="#{indexManagedBean.getAllData()}"/><br/> <h:outputLabel value="年齢フィルタ"/>: <h:inputText id="ageFilter" value="#{indexManagedBean.ageFileter}" autocomplete="off"> <f:ajax event="keyup" execute="ageFilter" render="tabledata" listener="#{indexManagedBean.updateData()}"/> </h:inputText> <h:dataTable id="tabledata" value="#{afilter = indexManagedBean.ageFileter;indexManagedBean.data.stream().filter(p-> p.age >= afilter).toList()}" var="person" border="1"> <h:column> <f:facet name="header"> <h:outputText value="名前"/> </f:facet> <h:outputText value="#{person.name}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="年齢"/> </f:facet> <h:outputText value="#{person.age}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="性別"/> </f:facet> <h:outputText value="#{person.sex}"/> </h:column> </h:dataTable> </h:form> </h:body> </html>
package jp.co.oracle.ee7samples.cdi; import java.util.ArrayList; import javax.faces.view.ViewScoped; import javax.inject.Named; import jp.co.oracle.ee7samples.model.Person; @Named @ViewScoped public class IndexManagedBean { private ArrayList data; private Integer ageFileter; public ArrayList getData() { return data; } public void setData(ArrayList data) { this.data = data; } public Integer getAgeFileter() { if (ageFileter == null) { return new Integer(0); } return ageFileter; } public void setAgeFileter(Integer ageFileter) { this.ageFileter = ageFileter; } public String getAllData() { setData(Person.createDummyData()); return ""; } public String updateData() { return ""; } }
デモの中でもお伝えしましたが、本来 JPA で DB に接続して Person Entity に対して全レコードを抽出するコードを書く方が現実的なのですが、EL 3.0 は本来 Collection を対象とする事をわかりやすくするため、JPA を使わずに自分でダミーのデータをcreateDummyData()で作成しています。
package jp.co.oracle.ee7samples.model; import java.util.ArrayList; public class Person { private String name; private Integer age; private String sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public static ArrayList createDummyData() { ArrayList<Person> data = new ArrayList<>(); Person person; for (int i = 0; i < 100; i++) { person = new Person(); person.setAge(Integer.valueOf(i)); if (i % 2 == 1) { person.setName("山田 太郎" + i); person.setSex("男性"); } else { person.setName("山田 花子" + i); person.setSex("女性"); } data.add(person); } return data; } }