2014年9月7日日曜日

NetBeansを使ったJava EEアプリケーション開発


最近のJava Webフレームワークについて調べてみたところ、どうやらJava EEが良いようなので、今回はJava EEに手を出してみます。


Java EEについて調べていると、EclipseよりNetBeansで説明されていることが断然多いです。
単にJavaでの開発というとシェア的にはEclipseに分があるものの、Java EEやるならNetBeansって事でしょうか。

今まではEclipse派でしたが、NetBeansはインストールしたらすぐ使える的なことも良く書いてあるので、今回はNetBeansを試してみようと思います。


まずは、NetBeansのインストールからと言いたいところですが、NetBeansのサイトからダウンロードしてインストーラの指示通りインストールするだけでした。

インストールは割愛し、プロジェクトの作成、バッキングBeanの作成、JSFページの作成について、基本的な部分を試してみます。

今回は、ユーザー名を入力してログインボタンを押すと、ログインしたユーザー名を表示し、ログアウトボタンを押すとユーザー名が消えるだけのサイトを作成します。

  • プロジェクトの作成

新規プロジェクト⇒Java Web⇒WEBアプリケーション

プロジェクト名の入力

Java EEのバージョンやアプリケーションサーバの選択

フレームワークの選択

必要なファイルと階層構造が生成されます。

おもむろに実行すると、初期状態のindex.xhmlが開きます。

ここまでは細かい設定いらず、非常に簡単です。


また、コードを触る前にLombokというライブラリを入れておきます。
ボイラープレートコードをアノテーションだけでコンパイル時に生成してくれるかなり使えるライブラリです。

設定はLombokのサイトからlombok.jarをダウンロードして、ライブラリフォルダに登録するだけです。


  • バッキングBeanの作成

新規⇒JavaServer Faces⇒JSF管理対象Bean

Bean名やパッケージ名の入力

ソース・パッケージフォルダに指定した名前のjavaファイルが生成されます。
表示させると以下のようなコードになっています。

package monawebwallet;

import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;

@Named(value = "loginBean")
@SessionScoped
public class LoginBean implements Serializable {

    /**
     * Creates a new instance of LoginBean
     */
    public LoginBean() {
    }
   
}

いわゆるJavaBeansですが、@Named@SessionScopedの二つのアノテーションを使用しています。

@Namedアノテーションは決まりごとで、ここで指定した名前(value)でELからアクセス出来ます。

@SessionScopedアノテーションは、バッキングBeanのスコープを定義します。
他にも@RequestScoped@ApplicationScopedなどがありますが、アカウントを保持させるので、ここではセッションスコープにしました。

このコードにアカウント文字列を保持するプロパティを追加し、Lombokの@NoArgsConstructor@Getter@Setterアノテーションを付けます。

package monawebwallet;

import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import lombok.NoArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@Named(value = "userBean")
@SessionScoped
@NoArgsConstructor
@Getter
@Setter
public class UserBean implements Serializable {

    String accountStr;
}

非常にすっきりしていますが、これでデフォルトコンストラクタとゲッター、セッターがコンパイル時に生成されます。


  • JSFページの作成

新規⇒JavaServer Faces⇒JSFページ

ファイル名の入力

Webページフォルダ直下に指定した名前のxhtmlファイルが生成されます。

ちなみにこのページにアクセスするには、http://localhost:8080/MonaWebWallet/login.xhtmlではなく、http://localhost:8080/MonaWebWallet/faces/login.xhtmlです。

デフォルトのindex.xhtmlについては、http://localhost:8080/MonaWebWallet/でアクセス可能ですが、実際にはweb.xmlでウェルカムページとして設定されている、faces/index.xhtmlにアクセスしています。

詳しくはweb.xmlを見て頂きたいのですが、faces配下のファイルがFacesServletの管理対象としてマッピングされています。

これ、faces配下じゃないほうにアクセスしても普通のhtml部分は表示されるため、ちょっとハマりました。
そして、そのままFacesServletが処理する前のソースが見えてしまうのでなんだか微妙なのですが、表示させない方法についてはまた別の機会に。


新規でJSFページを作る際は上記の流れですが、今回はデフォルトで生成されているindex.xhtmlを書き換えて使います。

表示させると以下のようになっています。

<?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:h="http://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        Hello from Facelets
    </h:body>
</html>

<h:body>タグ内を以下のように書き換えます。

<h:form>
    <h:inputText id="account" size="30" value="#{userBean.accountStr}" />
    <h:commandButton id="login" value="ログイン" />
    <h:commandButton id="logout" value="ログアウト" actionListener="#{userBean.setAccountStr('')}" />
</h:form>
<b><h:outputText value="#{userBean.accountStr}" /></b>

#{userBean.accountStr}のように、ELを使用することでバッキングBeanのプロパティにアクセス出来ます。

<h:form>タグの中に<h:inputText>タグを入れて、valueにELでバッキングBeanのプロパティを設定しておくと、フォームをSubmitした際に、プロパティのセッターが呼ばれて値が格納されます。

<h:outputText>タグのvalueに設定すると、プロパティのゲッターが呼ばれて、値が取り出されます。

ログイン前

ログイン後

  • 日本語対応

日本語を入力すると壮大に文字化けしました。

新規⇒Glassfish⇒Glassfish ディスクリプタ

そのまま進めると、「このプロジェクトのデプロイメント構成が見つかりません。デプロイメント・ディスクリプタのバージョンを正しく設定できませんでした。」とエラーが出ましたが、とりあえず放置します。

構成ファイルフォルダの中にsun-web.xmlが生成されるので、以下のように<parameter-encoding>タグを追加します。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD GlassFish Application Server 3.0 Servlet 3.0//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd">
<sun-web-app error-url="">
    <class-loader delegate="true"/>
    <jsp-config>
        <property name="keepgenerated" value="true">
            <description>Keep a copy of the generated servlet class' java code.</description>
        </property>
    </jsp-config>
    <parameter-encoding default-charset="UTF-8" />
</sun-web-app>

うまくいきました。