目的
Sun RI 1.2 JSF でも動作する HelloWorld の簡単なプログラムでテストします。古い書き方が分からず試行錯誤が必要だったので、備忘録として残して置きます。jsf12.war は tWAS8.5の Sun RI 1.2 で動作します。
JSFプログラムの説明
EclipseでDynamic Web Projectが作成できているところからの作成手順です。
と手順としては同様です。
Bean classの作成
SessionBeanのclassを作成します。
- 右クリック > New > Class で選択
- Package: pdprof.jsf12
- Name : HelloBean
- Finish ボタンをクリック
package pdprof.jsf12;
import java.io.Serializable;
public class HelloBean implements Serializable {
private String message = "Hello World!";
public String getMessage() {
System.out.println("HelloBean.gettMessage : << " + message);
return message;
}
public void setMessage(String message) {
System.out.println("HelloBean.setMessage : >> " + message);
try {
throw new Exception("Exception to check stacktrace");
} catch (Exception e) {
e.printStackTrace();
}
this.message = message;
}
}
faces-config.xml の作成
アノテーションでは必要ありませんでしたが、使用できないのでバージョン前提で構成ファイルにbeanを指定します。あとで使う message-bundle, resource-bundle の指定もあります。
<faces-config version="1.2"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
<managed-bean>
<managed-bean-name>helloBean</managed-bean-name>
<managed-bean-class>pdprof.jsf12.HelloBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<application>
<message-bundle>pdprof.jsf12.messages</message-bundle>
<resource-bundle>
<base-name>pdprof.jsf12.resources</base-name>
<var>res</var>
</resource-bundle>
</application>
</faces-config>
JSPの作成
JSPを新規に作成します。war の index.htmlなどと同じ場所に置きます。XHTMLとは異なっています。
- bean のデータ取得 (#{helloBean.message})
- message bundle の文字取得 ( , required="true")
- resource bundle の文字種得 (res.inputMessage)
あたりが他のファイルとの関連部分です。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ page language="java" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html>
<body>
<f:view>
helloBean.message : <br />
<h:outputText value="#{helloBean.message}" /><br />
<hr />
<h:form>
<h:messages style="color:red" />
<h:outputText value="#{res.inputMessage}" /> <br />
<h:inputText id="message" value="#{helloBean.message}" required="true" /><br />
<h:commandButton id="button" value="Send" action="index.jsp" />
</h:form>
</f:view>
</body>
</html>
message bundle の作成
JSF の Validation Error のメッセージを変更しました。
messages.properties ファイルを作成します。(prprof.jsf12パッケージに置きます)
javax.faces.component.UIInput.REQUIRED=This field is required!!
このファイルを faces-config.xmlの
<application>
<message-bundle>pdprof.jsf12.messages</message-bundle>
</application>
で指定して、index.jspの
<h:messages style="color:red" />
で表示します。この指定がない場合はValidation Errorのメッセージは messages.log に出力されています。
resource bundle の作成
resources.properties ファイルを作成します。(prprof.jsf12パッケージに置きます)
inputMessage=Input Message (null is not allowed):
このファイルを faces-config.xmlの
<application>
<resource-bundle>
<base-name>pdprof.jsf12.resources</base-name>
<var>res</var>
</resource-bundle>
</application>
で指定して、res でアクセスできるようにし、 index.jspの
<h:outputText value="#{res.inputMessage}" />
で表示します。XHTML内の指定のみで使用する方法
(<f:loadBundle basename="resources" var="res" />
)もありますが。
今回は faces-config.xml での指定にしました。
web.xml の作成(更新)
Webプロジェクト作成時にweb.xmlを作成していない場合には作成をして、更新をします。
作成方法は
- 右クリック > Java EE Tools > Generate Deployment Descriptor Stub
で web.xml が作成されます。
これに、Faces Servlet の servletとservlet-mappingを追加します。マッピングは*.xhtmlとは変わっています。
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>jsf12</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
</web-app>
Libertyテスト環境
今回は tWAS でも動作するように、Java8, jsf-2.2, beanvalidation-1.1 で動かします。
server 構成は以下になります。
<server description="new server">
<!-- Enable features -->
<featureManager>
<feature>jsf-2.2</feature>
<feature>beanValidation-1.1</feature>
<feature>localConnector-1.0</feature>
</featureManager>
<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
<httpEndpoint httpPort="9080" httpsPort="9443" id="defaultHttpEndpoint"/>
<!-- Automatically expand WAR files and EAR files -->
<applicationManager autoExpand="true"/>
<!-- Default SSL configuration enables trust for default certificates from the Java runtime -->
<ssl id="defaultSSLConfig" trustDefaultCerts="true"/>
<applicationMonitor updateTrigger="mbean"/>
<webApplication id="jsf12" location="jsf12.war" name="jsf12"/>
</server>
tWAS 8.5を Sun RI 1.2 JSF に構成
Libertyでテストはしましたが、tWAS8.5でも動作します。デフォルトでは MyFacesが有効なため、Sun RI 1.2に変更します。
tWAS 8.5 では jacl がデフォルトなので今回はDocsのものを jython にはせずにそのまま使用します。
$ /opt/IBM/WebSphere/AppServer/bin/wsadmin.sh
Realm/Cell Name: <default>
Username: wsadmin
Password:
WASX7209I: Connected to process "server1" on node DefaultNode01 using SOAP connector; The type of process is: UnManagedProcess
WASX7029I: For help, enter: "$Help help"
wsadmin>set server [$AdminConfig list ApplicationServer *server1*]
(cells/DefaultCell01/nodes/DefaultNode01/servers/server1|server.xml#ApplicationServer_1183122130078)
wsadmin>$AdminConfig modify $server {{jsfProvider SunRi1.2}}
wsadmin>$AdminConfig save
wsadmin>
アプリケーションをデプロイしてテストができます。詳細は省略しますがアクセスするURLなどはつぎのセクションの説明を参考にしてください。
Libertyテスト環境の自動構築
これまでの方法で既存環境に構成は可能ですが、環境をdockerで用意する方法です。
用意したGitレポジトリをクローンします。
git clone http://github.com/pdprof/jsf.git
cd jsf/jsf-docker
Libertyのイメージをビルドして開始します。
./setup-docker.sh
./start.sh
Libertyの起動を確認します。JSF にアクセスします。
index.jsp で入力
アクセスしたindex.jspでJSFをテストします。
Input Message に入力して、Send ボタンをクリックするとページが更新されます。
Helloと入力してSendした場合は
HelloBean.gettMessage : << Hello World!
HelloBean.setMessage : >> Hello
[err] java.lang.Exception: Exception to check stacktrace
[err] at pdprof.jsf12.HelloBean.setMessage(HelloBean.java:17)
[err] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[err] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[err] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[err] at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[err] at javax.el.BeanELResolver.setValue(BeanELResolver.java:121)
[err] at javax.el.CompositeELResolver.setValue(CompositeELResolver.java:125)
[err] at org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver.setValue(FacesCompositeELResolver.java:237)
[err] at [internal classes]
[err] at javax.faces.component.UIInput.updateModel(UIInput.java:424)
[err] at javax.faces.component.UIInput.processUpdates(UIInput.java:342)
[err] at javax.faces.component.UIForm.processUpdates(UIForm.java:264)
[err] at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1505)
[err] at javax.faces.component.UIViewRoot._processUpdatesDefault(UIViewRoot.java:1694)
[err] at javax.faces.component.UIViewRoot.access$700(UIViewRoot.java:77)
[err] at javax.faces.component.UIViewRoot$UpdateModelPhaseProcessor.process(UIViewRoot.java:1832)
[err] at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1655)
[err] at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:916)
[err] at org.apache.myfaces.lifecycle.UpdateModelValuesExecutor.execute(UpdateModelValuesExecutor.java:38)
[err] at [internal classes]
[err] at javax.faces.webapp.FacesServlet.service(FacesServlet.java:198)
[err] at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1260)
[err] at [internal classes]
[err] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[err] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[err] at java.base/java.lang.Thread.run(Thread.java:839)
HelloBean.gettMessage : << Hello
HelloBean.gettMessage : << Hello
のように HelloBeanのsetter/getter が動作しているのがログから分かります。また、setterが動作したときに stacktraceを出力するようにしたので、JSFが何の実装で動作しているか確認ができます。
指定した required の Validation を動作させるのに文字を入力せずに Sendした場合は
で画面に赤い文字で出力されます。
トラブルシューティング
毎度のことですが、よくつかう dockerコマンドを書いておきます。この文書でもpodman, dockerとまとまりがないですが、Linux では dockerがpodmanを呼び出すようになっていました。
docker ps # 動作中のContainer確認
docker logs -f jsf # ログ確認
docker restart jsf # 再起動
docker inspect jsf # container 確認
docker exec -it jsf bash # Container内状況確認
まとめ
Libertyの環境 , tWAS 8.5の環境を構築して、JSF 1.2をテストしました。
参考
以下ページを参考にさせていただきました。ありがとうございます。