• How to set the value in ValueChangeListener

    JSFには値が変更されたことをハンドリングするためのイベントとしてValueChangeEventが用意されています。 このイベントは、コンポーネントのValueChangeListenerによって発行されます。 ValueChangEventを利用してテキストフィールドに入力された値の検証を行っているのですが、 値が不正だった場合に、エラーを表示するのではなく正常な値を設定したい場合があります。 このとき、単純にValueChangeListenerの中でテキストフィールドのプロパティに値を設定しても、画面には反映されません。 これは、ValueChangeEventがJSFのライフサイクルのUpdate Model Valuesフェーズの前に呼ばれるからであり、 ValueChangeListenerで設定した値はUpdate Model Valuesフェーズで入力値によって上書きされてしまうからです。 これを解決するには、ValueChangeListenerにおいて、ちょっとした工夫が必要です。 以下にその例を示します。 public void valueChangeListener(ValueChangeEvent event) { if (event.getPhaseId() == PhaseId.UPDATE_MODEL_VALUES) { property = "9:00"; } else { String value = (String) event.getNewValue(); if (false == value.matches("([0-9]{1,2}|1[0-9]|2[0-3]):[0-5][0-9]") { event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES); event.queue(); } } } この例では、時間の入力に対する検証を行い、不正な値が入力された場合にデフォルト値である「9:00」を設定しています。 値の検証をUpdate Model Valuesフェーズの前に実施し、値が不正である場合には、ValueChangeEventをUpdate Model Valuesフェーズにエンキューします。 このようにすることで、Update Model Valuesフェーズでもう一度ValueChangeListenerが呼び出されます。 二度ValueChangeListenerが呼ばれることになるので、イベントのフェーズIDを判定し、 Update Model Valuesフェーズで呼ばれた場合にデフォルト値を設定することで画面にその値を反映させます。 JSFは、ライフサイクルを知っていないと対処が難しい場合があるのがちょっといけてないですね…。 というわけで何かの参考になれば幸いです。 Enjoy !
  • Examples to FizzBuzz of Java8

    業務では未だJava6だし、Java7自体いつ導入されるか分からないし、Java8を本格的に使うようになるのはすごい先だと思うけど、 Java8を触っている時間がほとんどなくて、Lambdaの構文自体を忘れてしまいそうなので、ちょっとリハビリでFizzBuzzを書いた。 FizzBuzzとはこれのことです。 CODING HORROR: Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”. コードは下記になります。 Enjoy !
  • EclipseLinkでの一意制約例外

    @kikutaro_さんのブログで、 EclipseLinkの一意制約例外について書かれた 「EclipseLinkで一意制約の例外を拾ってみたけど…」 の記事が Twitterで言及されていたので、ちょっと読んでたらjavax.persistence.EntityExistsExceptionがスローされないってあって、 あれ、そうだったけ?とちょっと疑問に思ったので調べてみた。 で、まあググると確かにスローされないって言っている人が沢山いたけど、 やっぱり自分で試してみないと気が済まないので、下記のようなコードを書いて試してみる。 (コードにはlombokを適用してます) persistence.xml: <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0"> <persistence-unit name="testPU" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>entity.Account</class> <properties> <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/> <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost/test;create=true"/> <property name="javax.persistence.jdbc.user" value="APP"/> <property name="javax.persistence.jdbc.password" value="APP"/> <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/> </properties> </persistence-unit> </persistence> Account.java: @Entity @NoArgsConstructor @RequiredArgsConstructor public class Account { @Getter @NonNull @Id private Long id; @Getter @Setter @NonNull private String name; } AccountTest.java: @Test(expected = EntityExistsException.class) public void testPersist() throws Exception { Account account = new Account(1L, "名前"); em.
  • java7u51 Web Startセキュリティアップデートの回避方法

    1月14日にJava7u51がリリースされました。 このアップデートによってセキュリティが強化されて、署名のないアプレットが起動できなくなりました。 また署名があっても、ユーザ独自の署名の場合ではその証明書をクライアントにインポートしておかないと、 同じく起動することができないようです。 あまり頻繁に行う作業ではないので、手順をまとめておきたいと思います。 1. MANIFEST.MFの編集 jarファイル内のMANIFEST.MFに下記を追記します。 Permissions: all-permissions Mavenを利用している場合は、下記をpom.xmlに追加することで、 ビルド時にMANIFEST.MFに追加することができます。 <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.4</version> <configuration> <archive> <manifestEntries> <Permissions>all-permissions</Permissions> <Codebase>*</Codebase> </manifestEntries> </archive> </configuration> </plugin> </plugins> </build> Antであれば下記で同様のことができます。 <target name="dist"> <jar destfile="${basedir}/out/sample.jar" basedir="${basedir}/out/classes/"> <manifest> <attribute name="Permissions" value="all-permissions"/> <attribute name="Codebase" value="*"/> </manifest> </jar> </target> 2. jnlpファイルの編集 jnlpファイルに下記を追記します。 <security> <all-permissions/> </security> 3. keystoreの生成 keystoreを生成します。[]内は任意の文字列を指定します。 keytool -selfcert -alias [sample] -genkey -keystore [sample.keystore] -validity [3650] 4. 証明書の生成 keytool -export -keystore [sample.
  • JAX-RSで複数ファイルをアップロードするには

    この記事はJava Advent Calendar 2013の22日目の記事です。 昨日は@nagaseyasuhitoさんの「mvn siteのtips三連発」でした。 明日は monzou さんです。 ファイルアップロードを実現するために何を使っていますか? 私はもっぱらJAX-RSを使っています。 ファイルアップロードはAX-RSの仕様には含まれていないのですが、ほとんどの実装でサポートされているようです。 その実装の中から、今回はJerseyを使った複数ファイルのアップロードについて紹介しようかと思います。 今回利用したJerseyはGlassFish4に含まれているものを利用します。 ライブラリとしては以下のjarになります。 <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-multipart</artifactId> <version>2.4.1</version> </dependency> さっそくHTMLから。複数のファイルをアップロードするので同じnameのfileフィールドを用意します。 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>JAX-RS upload multiple files example</title> </head> <body> <form enctype="multipart/form-data" method="post" action="rest/upload/multipleFiles"> <div><input type="file" name="file"/></div> <div><input type="file" name="file"/></div> <input type="submit" value="Upload"> </form> </body> </html> で、実際にリクエストを受け取るJavaのコード。 package org.katsumi.resources; import org.glassfish.jersey.media.multipart.FormDataBodyPart; import org.glassfish.jersey.media.multipart.FormDataParam; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.
  • JSF 2.2 でさらに便利になったMarkupを使ってみよう

    この記事は、Java EE Advent Calendar 2013の18日目の記事です。 昨日は @yumix_h さんの私がJava EE開発の現場から学んだことでした。 明日は誕生日の @aoetk さんです。 みなさんJSF使ってますか? JSFってちょっと取っ付きにくいところがありますよね。でもそんなJSFもバージョンが2.2になって、 ちょっと良い感じになってきたので使ってみませんか、 ということでJSFのマークアップについて書いてみたいと思います。 デザイナーとプログラマの作業の分担 JSFはデザイナーとプログラマで作業が分担できるということを良く聞きます。 デザイナーを雇うほど大きなプロジェクトでJSFを使ったことがないし、 分担しているということもあまり見聞きしませんが、実際この分担というのはどういうことなんでしょう? デザイナーはHTMLは分かりますがJSFはわかりません。 プログラマはHTMLもJSFも分かりますが、デザインセンスはそれを専属でやっているデザイナーのほうに 一日の長があると思うので、素直にデザインは任せた方が良いでしょう。 このようにHTMLしか分からない人が、HTMLに注力できるようにするには、 そのファイルがHTMLとして認識、つまりAPサーバーを経由しなくても、ブラウザでレイアウトが表示できる必要があります。 昔のJSPのように、JSPのタグやスクリプトレットで動的にレイアウトをするようにしていると、 ブラウザでレイアウトが表示できないのでダメということですね。 JSFはFaceletsというテンプレートエンジンを取り込んでいるので、 特別なファイルではなく、XHTMLとして画面を作ることができます。 そのため、JSFのコンポーネントを埋め込まなければ、このままブラウザで表示することができます。 ですが、何も埋め込まないのでは静的なHPと何も変わらないので、 JSFのコンポーネントを埋め込んでいく必要があり、下記のようなコンポーネントを埋め込んでしまうと、 デザイナーが理解できない状態、ブラウザでレイアウトを確認できない状態になってしまいます。 <h:commandButton value="OK" action=" #{managedBean.doAction}"/> ではどうしたら良いのでしょう? JSF 2.1 JSF 2.1では、例えば下記のようにHTMLのタグにJSFのコンポーネント名を設定することによって、 JSFのコンポーネントとして認識させることができます。もちろんJSF 2.2でもできます。 <input type="submit" value="OK" jsfc="h:commandButton" action="#{managedBean.doAction}"/> これをブラウザで表示してみます。 h:commandButtonの方は見事に表示されませんが、jsfc属性で書いた方は普通のボタンとして表示されています。 JSF 2.2 jsfc属性でJSFコンポーネントをHTMLとして認識させるのには十分でしたが、 それぞれのJSFコンポーネント名をいちいち記載するのは面倒でした。コンポーネント名を正確に覚えていなければならないし…。 JSF 2.2ではそこがさらに改善され、下記のようにコンポーネント名を書かなくても、JSFコンポーネントとして認識してくれるようになりました。 namespaceはxmlns:jsf="http://xmlns.jcp.org/jsf"です。 <input type="submit" value="OK" jsf:action="#{managedBean.doAction}"/> 詳しくはJava EE 7 Tutorialを参考にしてください。
  • IntelliJ IDEA 13で作るJavaFXアプリケーション

    この記事は、JavaFX Advent Calendar 2013の8日目です。 昨日は@aoetkさんのListViewやTableViewのセルをカスタマイズする方法でした。 明日は@sk44_さんです。 祝!IntelliJ IDEA 13 リリース IntelliJ IDEA 13 が 12月3日にリリースされました!めでたいですね! たぶん説明はいらないと思うので書きませんが、Java界隈の人なら知る人ぞ知る素敵なIDEです。 IntelliJの最新版であるver.13はJavaFXもサポートされているので、 今回はこれを使ってJavaFXの簡単なアプリケーションを作ってみたいと思います。 6日目の記事で@khasunumaさんが書かれた、 「e(fx)clipseで作るJavaFXアプリケーション」のIntelliJ版ですね。 早速作ってみる IntelliJを初めて起動すると以下のような画面が表示されるので、右側にある「Create New project」を選択します。 今度はプロジェクトの作成画面が表示されるので、 左側からプロジェクトのタイプとして「JavaFX Application」を選択、右側の「Project name」に任意のプロジェクト名を入れます。 今回は「HelloJavaFX」という名前にしました。 Finishボタンをクリックすると、プロジェクトが作られます。 プロジェクトには簡単なファイルが3つ用意されていて、それぞれ以下のような内容になっています。 Mainクラスがちゃんと書かれているのでこれだけでも動きます。 初めてJavaFXのアプリケーションを作る人に必要最低限のファイルとコードを示すのに十分です。 これ以上のコードがあると、本来は不必要なものまで必要だと勘違いしてしまうと思います。 ただControllerとFXMLは空っぽなので、このままだと枠しか表示されなくて面白くない…。 ボタンをクリックしたら文字を表示するというぐらいはやりたいので、 ボタンとラベルをFXMLに追加していきます。 <?import javafx.geometry.Insets?> <?import javafx.scene.layout.GridPane?> <?import javafx.scene.control.Button?> <?import javafx.scene.control.Label?> <GridPane fx:controller="sample.Controller" xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"> <Label fx:id="label" GridPane.columnIndex="0" GridPane.rowIndex="0"/> <Button fx:id="button" text="OK" onAction="#click" GridPane.columnIndex="0" GridPane.rowIndex="1" GridPane.halignment="CENTER"/> </GridPane> ちなみに、以下のような感じでちょっとだけ入力すると補完候補が出てきます。 この辺はIntelliJ様々です。他のIDEもできるのかもしれないですけど。 次はControllerに動作を書いていきます。 package sample; import javafx.
  • JUnitでJPAのテスト

    JPAで作ったデータアクセスクラスのテストをJUnitで作る際に、EntityManagerの扱いが問題になってきます。 プロダクトコードだと、PersistenceUnitのtransactionTypeをJTAとするため、 この設定のままユニットテストを実行には、APサーバが起動している必要があります。 この状態だとJenkinsに食わせたりするときに色々大変だし、 そもそもテスト用にはデータベースを別にしたいので、設定をテスト時だけ書き直す必要が出てきて面倒です。 そこでプロダクトコードとテストコードで参照するPersistenceUnitを変更するようにしてみました。 ファイル構成 ファイルは下記のように、プロダクトコードとテストコード用にそれぞれpersistence.xmlを用意します。 root └ src ├ main │ ├ java │ │ ├ Account.java │ │ └ AccountFacade.java │ └ resources │ └ META-INF │ └ persistence.xml └ test ├ java │ └ AccountFacadeTest.java └ resources └ META-INF └ persistence.xml プロダクトコードのpersistence.xmlはこんな感じ。 transaction-typeをJTAにしているので、jta-data-sourceにAPサーバで設定したデータソース名を指定しています。 persistence.xml: <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0"> <persistence-unit name="mytestPU" transaction-type="JTA"> <jta-data-source>jdbc/mytest</jta-data-source> <properties> <property name="eclipselink.ddl-generation" value="create-tables"/> </properties> </persistence-unit> </persistence> テストコードのpersistence.xmlはこんな感じ。 プロダクトコードとは違い、APサーバが起動していなくてもユニットテストが実行できるように transaction-typeをRESOURCE_LOCALにしています。
  • springframeworkのjarファイル一式をダウンロードするには?

    久しぶりにSpringのサイトを見に行ったら、Spring Framework一式がZIPでダウンロードできなくなってた。 サイトは今風になって素敵なんだけど。 MavenとかGradleを使って取得するのが正しい方法として挙げられているけれども、一式を取得する方法は特に記載がない。 Mavenを利用したことがなくて一式欲しいという需要があるようなので、ここで一つの方法を書いてみようと思う。 Gradleの方が記述が簡単そうだけど、ちゃんと使ったことがないので今回はMavenを利用する。 Mavenでは maven-asembly-plugin がこの要望を満たしてくれる。 maven-assembly-plugin は pom.xml とは別に個別の設定ファイルが必要なので、それを用意する。 distribution.xml: <?xml version="1.0"?> <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd"> <id>distribution</id> <formats> <format>zip</format> </formats> <dependencySets> <dependencyset> <unpack>false</unpack> <scope>runtime</scope> <outputDirectory>/out</outputDirectory> </dependencyset> </dependencySets> </assembly> ファイルの内容を簡単に説明すると、format には出力形式として zip, tar, tar.gz が指定できる。 unpack では、取得する jar ファイルを解凍して一つの jar とするかどうかを指定する。 scope は、Maven の dependency の scope と同じ意味なので、必要な値を指定、 outputDirectory は zip の出力先を指定する。 次にpom.xmlにプラグインの追加とdistribution.xmlの場所を定義する必要がある。 pom.xml: <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.2.1</version> <configuration> <descriptors> <descriptor>distributions.xml</descriptor> </descriptors> </configuration> </plugin> </plugins> </build> Spring Framework のライブラリはリポジトリを別途指定する必要があるので、それを pom.
  • JDBCRealmのパッケージが変更 #glassfish-4

    GlassFish-4.0からJDBCRealmクラスのパッケージが変更になった。 今までのパッケージは下記の通り。 com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm GlassFish-4.0からは下記のパッケージとなる。 com.sun.enterprise.security.ee.auth.realm.jdbc.JDBCRealm Embeddedとして利用しているとかじゃないとあまり影響はないかもしれない。