GlassFish: Java EE 7 入門ではまったこと

Java EE 7 入門 NetBeansで始めるJava EE 7 First Tutorial

を実装していてはまった箇所を記録します。
※環境はNetBeans 8.0.1+GlassFish Server 4.0

P.70のユニットテストの実行は失敗します。

重大: Exception while preparing the app : Invalid resource : jdbc/tutorial__pm

恐らく、テスト・ライブラリに含まれているGlassFish Server 4 (埋込み可能コンテナ)にデータソースの設定をしてやる必要があるのだと思いますが、ここは解決せずにスルーしました。

P.97のlist.xhtmlファイルの実行で、やはりエラーが発生します。

重大:   Exception while invoking class org.glassfish.persistence.jpa.JPADeployer prepare method
重大:   java.lang.RuntimeException: Invalid resource : jdbc/tutorial__pm
重大:   Exception while preparing the app : Invalid resource : jdbc/tutorial__pm

もちろんglassfish-resources.xmlにはjdbc/tutorialの定義はされています。
対応策としては、GlassFish Serverのドメイン管理コンソールから「JDBC接続プール」と「JDBCリソース」を登録すること。
f:id:soutoku:20141008114329p:plain
f:id:soutoku:20141008134228p:plain
Windows7の場合、下記のファイルに設定が追加されるので、うまく行かない場合はこのファイルを直接書き換えてもよい。
※ファイルの編集はバックアップを取ってから行うこと。
C:\Users\ユーザ名\AppData\Roaming\NetBeans\8.0\config\GF_4.0\domain1\config\domain.xml
設定値は以下のとおり。

    <jdbc-connection-pool datasource-classname="org.apache.derby.jdbc.ClientDataSource" res-type="javax.sql.DataSource" name="TutorialPool">
      <property name="User" value="tutorial"></property>
      <property name="DatabaseName" value="tutorial"></property>
      <property name="Password" value="tutorial"></property>
      <property name="ServerName" value="localhost"></property>
      <property name="PortNumber" value="1527"></property>
      <property name="URL" value="jdbc:dervy://localhost:1527/tutorial"></property>
    </jdbc-connection-pool>
    <jdbc-resource pool-name="TutorialPool" jndi-name="jdbc/tutorial"></jdbc-resource>


P.154の「存在しないtodoidを指定してリクエストを送信」して「404 Not Found」エラーを表示させる処理は、チュートリアルのコードのままでは「500 Internal Server Error」になります。
原因は、ErrorModel.javaに引数無しのコンストラクタが存在しない為です。

Exception Description: The class todo.app.common.exception.ErrorModel requires a zero argument constructor or a specified factory method.  Note that non-static inner classes do not have zero argument constructors and are not supported.

オリジナルのコードを以下のように書き換えると想定の動作になります。
ErrorModel.java

public class ErrorModel {
    //errorMessagesをインスタンス生成後設定可能なように、final属性を除去
    //private final List<String> errorMessages;
    private List<String> errorMessages;
    
    //デフォルトコンストラクタを追加
    public ErrorModel() {
        this.errorMessages = null;
    }
    
    public ErrorModel(List<String> errorMessages) {
        this.errorMessages = errorMessages;
    }
    
    public List<String> getErrorMessages() {
        return errorMessages;
    }
    
    //セッターメソッドを追加
    public void setErrorMessages(List<String> errorMessages) {
        this.errorMessages = errorMessages;
    }
}

ResourceNotFoundExceptionMapper.java

@Provider
public class ResourceNotFoundExceptionMapper implements ExceptionMapper<ResourceNotFoundException> {
    
    @Override
    public Response toResponse(ResourceNotFoundException exception) {

        //ErrorModelをデフォルトコンストラクタで生成するように変更
        //ErrorModel errorModel = new ErrorModel(Arrays.asList(exception.getMessage()));
        ErrorModel errorModel = new ErrorModel();
        errorModel.setErrorMessages(Arrays.asList(exception.getMessage()));
        
        return Response.status(Response.Status.NOT_FOUND).entity(errorModel).build();
    }
}

※随時追加予定