2014年11月6日木曜日

Java EEとmonacoindでWEB Walletを作ってみた① JSFでUIを作成する


前回作ったmonacoindユーティリティクラスを利用して、MonacoinのWEB Walletを作成してみます。


まず全体の構成としては、HTMLは1ページでログイン状態によって表示を変え、バッキングBeanはセッションスコープでアカウント名を保持するものと、リクエストスコープでアカウントの情報を保持するもので構成します。


  • 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"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>
        <title>Monacoin Web Wallet</title>
        #{accountBean.updateAccount()}
    </h:head>
    <h:body>
        <h:outputLink value="/MonaWebWallet/">トップ</h:outputLink>
        <h:form id="loginForm">
            <h:message for="account" /><br />
            <h:inputText id="account" value="#{userBean.accountStr}" rendered="#{! userBean.isLogin()}" />
            <h:commandButton value="Login" action="#{userBean.login()}" rendered="#{! userBean.isLogin()}" />
            <h:commandButton value="Logout" action="#{userBean.logout()}" rendered="#{userBean.isLogin()}" />
            <br />
        </h:form>

        <h:form rendered="#{userBean.isLogin()}">
            Account : <h:outputText value="#{userBean.accountStr}" />
            <br />
            Wallet Address : <h:outputText value="#{accountBean.addressStr}" />
            <br />
            Balance : 
            <h:outputText value="#{accountBean.balanceStr}">
                <f:convertNumber type="number" currencySymbol="#,##0.00000000" />
            </h:outputText>
            <br /><br /><br />
        </h:form>

        <h:form id="sendForm" rendered="#{userBean.isLogin()}">
            Send to : 
            <h:inputText id="sendTo" value="#{accountBean.toAddress}" size="50" maxlength="34" required="true">
                <f:validateLength maximum="34" minimum="34" />
            </h:inputText>
            <h:message for="sendTo" />
            <br />
            Amount : 
            <h:inputText id="sendAmount" value="#{accountBean.amount}" required="true">
                <f:validateDoubleRange minimum="0.00000001"/>
            </h:inputText>
            <h:message for="sendAmount" />
            <br />
            <h:commandButton id="send" value="Send" action="#{accountBean.send()}" rendered="#{userBean.isLogin()}" />
            <h:message for="send" />
            <br /><br />
        </h:form>

        <h:form rendered="#{userBean.isLogin()}">
            Transactions : <br />
            <h:dataTable border="1" var="transactionMap"
                         value="#{accountBean.transactionMapList}" rendered="#{accountBean.transactionMapList != null and ! accountBean.transactionMapList.isEmpty()}">
                <h:column>
                    <f:facet name="header">
                        <h:outputText value="Date"/>
                    </f:facet>
                    <h:outputText value="#{transactionMap.time * 1000}">
                        <f:convertDateTime pattern="yyyy/MM/dd HH:mm:ss" timeZone="JST"/>
                    </h:outputText>
                </h:column>
                <h:column>
                    <f:facet name="header">
                        <h:outputText value="Type"/>
                    </f:facet>
                    <h:outputText value="#{transactionMap.category}"/>
                </h:column>
                <h:column>
                    <f:facet name="header">
                        <h:outputText value="Address"/>
                    </f:facet>
                    <h:outputText value="#{transactionMap.address}"/>
                </h:column>
                <h:column>
                    <f:facet name="header">
                        <h:outputText value="Amount"/>
                    </f:facet>
                    <h:outputText value="#{transactionMap.amount}"/>
                </h:column>
                <h:column>
                    <f:facet name="header">
                        <h:outputText value="Confirmations"/>
                    </f:facet>
                    <h:outputText value="#{transactionMap.confirmations}"/>
                </h:column>
                <h:column>
                    <f:facet name="header">
                        <h:outputText value="Transaction ID"/>
                    </f:facet>
                    <h:outputText value="#{transactionMap.txid}"/>
                </h:column>
            </h:dataTable>
        </h:form>
    </h:body>
</html>


まず、ヘッダー部分にEL式でバッキングBeanのメソッドが仕込んであり、ここで初期化処理を行っています。

Javascriptで言うところの、bodyタグのonLoradのつもりで使っていますが、ここでやるのが正しいのかは良く分かりません。
何かもっとそれっぽい方法がありそうですが、色々調べたり実験したりしたのですが、これしかうまくいきませんでした。


続いて中身を見ていきますが、基本的に入力が必要なものはh:inputTextタグ、バッキングBean側から表示が必要なものはh:outputTextタグを利用しています。

トランザクション履歴については、h:dataTableタグでListtableに変換して表示します。

それぞれEL式でバッキングBeanのプロパティへバインドします。


バリデーション周りについては、アカウント名入力欄については、バッキングBean側でバリデーションをかけて入力必須にし、HTML側では特に何も設定していません。

送金先アドレスや金額欄については、f:validateLengthタグで文字列の長さ、f:validateDoubleRangeタグで数値の桁数、required属性で入力必須にしています。

入力必須にするだけであれば、後者のほうが楽なのでこっちに統一で良さそうな感じです。


エラーメッセージを表示したい場所については、h:messageタグを設置し、for属性でinput部品と関連付けます。

バリデーションのエラーを表示させたり、バッキングBeanから指定のメッセージを表示させたりします。


最後に表示非表示についてですが、ブロック毎にh:formタグで囲み、rendered属性で表示非表示を切り替えました。
やり方として正しいのか良く分かりませんが、divタグとかではrendered属性が使えないようで、コレしか思いつきませんでした。


これでUIのパーツは揃ったので、次回はバッキングBeanの作成です。


0 コメント:

コメントを投稿