在 JBoss EAP6.x Standalone Mode Cluster Configuration 驗證了 Standalone Mode 的 Cluster 機制,在 Domain Mode 的設定也很簡單,還記得在 JBoss EAP6 Domain Mode Setup 中 host.xml 對每台 server 作了 port-offset ,而這就是 workers.properties 檔案裡的 node。

 

JBoss_Domain_RealCase.png  

 

 

 

 

所以在 workers.properties 的設定如下:

# Define list of workers that will be used  
# for mapping requests  
worker.list=loadbalancer,status  
 
# Define Node1  
# modify the host as your host IP or DNS name.  
worker.node1.port=8009  
worker.node1.host=10.10.2.4
worker.node1.type=ajp13  
worker.node1.ping_mode=A  
worker.node1.lbfactor=1   
 
# Define Node2  
# modify the host as your host IP or DNS name.  
worker.node2.port=8109
worker.node2.host=10.10.3.118
worker.node2.type=ajp13  
worker.node2.ping_mode=A  
worker.node2.lbfactor=1  
 
# Define Node3  
# modify the host as your host IP or DNS name.  
worker.node3.port=8209
worker.node3.host=10.10.3.118
worker.node3.type=ajp13  
worker.node3.ping_mode=A  
worker.node3.lbfactor=1

# Define Node4  
# modify the host as your host IP or DNS name.  
worker.node4.port=8409
worker.node4.host=10.10.3.118
worker.node4.type=ajp13  
worker.node4.ping_mode=A  
worker.node4.lbfactor=1

 
# Load-balancing behavior  
worker.loadbalancer.type=lb  
worker.loadbalancer.balance_workers=node1,node2,node3,node4
worker.loadbalancer.sticky_session=0  
 
# Status worker for managing load balancer  
worker.status.type=status

 

啟動的順序是,先將 JBoss 開始後,再啟動 Apache 就可以了。

JBoss 的啟動指令 JBoss EAP6 Domain Mode Setup 裡的 Step04 & Step05 相同,不需修改。

 

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

JBoss EAP 6.x (Enterprise Application Platform) 提供 Cluster 的機制,但需要 apache 的 mod-jk.conf 配合,現在以 Standalone Mode 作為 HA 來測試看看。

Step 01: apache 的設定

APACHE_HOME/conf/httpd.conf

# Include mod_jk's specific configuration file  
Include conf/mod-jk.conf

<VirtualHost 192.168.2.4:80>
    JkMount /* loadbalancer  
</VirtualHost>

 

APACHE_HOME/conf/mod-jk.conf

# Load mod_jk module
# Specify the filename of the mod_jk lib 
LoadModule jk_module modules/mod_jk.so

# Where to find workers.properties
JkWorkersFile conf/workers.properties

# You can use external file for mount points.
# It will be checked for updates each 60 seconds.
# The format of the file is: /url=worker
# /examples/*=loadbalancer
JkMountFile conf/uriworkermap.properties

# Add shared memory.
# This directive is present with 1.2.10 and
# later versions of mod_jk, and is needed for
# for load balancing to work properly
JkShmFile logs/mod_jk.shm

# Where to put jk logs
JkLogFile logs/mod_jk.log

# Set the jk log level [debug/error/info]
JkLogLevel info

# Mount your applications
JkMount /* loadbalancer

<Location /jkstatus/>  
    JkMount status  
    Order deny,allow  
    Deny from all  
    Allow from all  
</Location> 

 

APACHE_HOME/conf/workers.properties

# Define list of workers that will be used  
# for mapping requests  
worker.list=loadbalancer,status  
 
# Define Node1  
# modify the host as your host IP or DNS name.  
worker.node1.port=8009  
worker.node1.host=192.168.2.4
worker.node1.type=ajp13  
worker.node1.ping_mode=A  
worker.node1.lbfactor=1   
 
# Define Node2  
# modify the host as your host IP or DNS name.  
worker.node2.port=8009
worker.node2.host=192.168.3.118
worker.node2.type=ajp13  
worker.node2.ping_mode=A  
worker.node2.lbfactor=1  
 
# Load-balancing behavior  
worker.loadbalancer.type=lb  
worker.loadbalancer.balance_workers=node1,node2
worker.loadbalancer.sticky_session=1  
 
# Status worker for managing load balancer  
worker.status.type=status

 

APACHE_HOME/conf/uriworkermap.properties

# Simple worker configuration file  
 
# Mount the Servlet context to the ajp13 worker  
/jmx-console=loadbalancer  
/jmx-console/*=loadbalancer  
/web-console=loadbalancer  
/web-console/*=loadbalancer  
#/printSession=loadbalancer  
#/printSession/*=loadbalancer

作好設定後,就可以啟動 apache Server。

 

Step 02: 設定第一個 JBoss Standalone : node1 (worker.node1.host=192.168.2.4 )

JBOSS_HOME/standalone/configuration/standalone-ha.xml

<subsystem xmlns="urn:jboss:domain:web:1.5" default-virtual-server="default-host" instance-id="node1" native="false">
    <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
    <connector name="ajp" protocol="AJP/1.3" scheme="http" socket-binding="ajp"/>
    <virtual-server name="default-host" enable-welcome-root="true">
        <alias name="localhost"/>
        <alias name="example.com"/>
    </virtual-server>
</subsystem>

 

Step 03: 設定第二個 JBoss Standalone : node2 (worker.node2.host=192.168.3.118 )

JBOSS_HOME/standalone/configuration/standalone-ha.xml

<subsystem xmlns="urn:jboss:domain:web:1.5" default-virtual-server="default-host" instance-id="node2" native="false">
    <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
    <connector name="ajp" protocol="AJP/1.3" scheme="http" socket-binding="ajp"/>
    <virtual-server name="default-host" enable-welcome-root="true">
        <alias name="localhost"/>
        <alias name="example.com"/>
    </virtual-server>
</subsystem>

 

Step 04: 分別啟動 node1 & node2

standalone.bat -c standalone-ha.xml -Djobss.node.name=node1 -b 192.168.2.4

standalone.bat -c standalone-ha.xml -Djobss.node.name=node2 -b 192.168.3.118

 

Step 05: 建立一個 example.war 檔來測試

WebContent\WEB-INF\web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>example</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
 
 <distributable/>
    <description>session test</description>  
</web-app>

 

WebContent\sessionTest.jsp

<%@page    import="java.util.*, java.lang.reflect.*, javax.servlet.http.HttpSession, java.net.*"%>
<%
    String basePath = request.getScheme() + "://"
            + request.getServerName() + ":" + request.getServerPort();
    String cPath = request.getContextPath();
    String sPath = request.getServletPath();
    String nodeId = System.getProperty("jboss.server.name");
    String nodeName = System.getProperty("jboss.node.name");
    //String hostName = System.getProperty("jboss.host.name");
    String hostName = System.getProperty("java.rmi.server.hostname");
    String variableString = (String) session
            .getAttribute("SESSION_TEST_VARIABLE");
    int count = 0;

    if (variableString != null) {
        count = Integer.parseInt(variableString);
        count++;
    }

    session.setAttribute("SESSION_TEST_VARIABLE", String.valueOf(count));
%>

<html>
<body bgcolor=white>

    Edit By Polin
    <table columns=1>
        <tr>
            <td><font color=blue>Edit By Polin</td>/
        </tr>
    </table>
    <table columns=2>
        <tr>
            <td><font color=blue>The sessionId is: </font></td>
            <td><%=session.getId()%></td>
        </tr>
        <tr>
            <td><font color=blue>The sessionObj is: </font></td>
            <td><%=session%></td>
        </tr>
        <tr>
            <td><font color=blue>The nodeId is: </font></td>
            <td><%=nodeId%></td>
        </tr>
        <tr>
            <td><font color=blue>The nodeName is: </font></td>
            <td><%=nodeName%></td>
        </tr>
        <tr>
            <td><font color=blue>The server hostName is: </font></td>
            <td><%=hostName%></td>
        </tr>
        <tr>
            <td><font color=blue># of requests placed on session: </font></td>
            <td><%=count%></td>
        </tr>
    </table>
</body>
</html>

 

這樣就可以在 https://192.168.2.4/example 作訪問驗證,apache 會自動將 Session 分配到 192.168.2.4 & 192.168.3.118

 

參考:

http://docs.jboss.org/jbossas/docs/Clustering_Guide/5/html/clustering-http-modjk.html

http://blog.c2b2.co.uk/2013/01/setting-up-jboss-eap-5-cluster-with.html

https://docs.jboss.org/jbossas/docs/Clustering_Guide/5/html_single/#d0e1257

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

JBoss EAP(Enterprise Application Platform) 提供 Domain Mode ,可以讓應用系統佈署簡單化,也可以讓應用系統不會因一台主機掛了,而導致使用者就無法登入,至於 Domain Mode 的概念在 JBoss EAP 與 JBoss AS/Community edition 及 WildFly 的差異 有提了一下,現在我們來實作,整個架構如下圖。

 

 JBoss_Domain_plan.png  

 Step 01: 設定 Domain Control 主機 Host name: dc-master / ip: 192.168.2.4

修改d:\AppServ\jboss-eap-6.2-master\domain\configuration\host.xml,host name 的值必需是唯一值

<host name="EAP-Domain-Master" xmlns="urn:jboss:domain:1.5">

    .
    .
    .
    <domain-controller>
        <local/>
    </domain-controller>

    <servers>
        <server name="server-one" group="main-server-group"/>
    </servers>

</host>

 

Step 02:在 Domain Control 主機 Host name: dc-master / ip: 192.168.2.4 建立 Domain Mode 主機間溝通用專用的帳號:domainMaster,並取得 secret key

D:\AppServ\jboss-eap-6.2\bin>add-user.bat

What type of user do you wish to add?
 a) Management User (mgmt-users.properties)
 b) Application User (application-users.properties)
(a): a

Enter the details of the new user to add.
Using realm 'ManagementRealm' as discovered from the existing property files.
Username : domainMaster
Password : xxxxx
Re-enter Password : xxxxx
What groups do you want this user to belong to? (Please enter a comma separated list, or leave blank for none)[  ]:
About to add user 'domainMaster' for realm 'ManagementRealm' Is this correct yes/no? yes
Added user 'domainMaster' to file 'D:\AppServ\jboss-eap-6.2\standalone\configuration\mgmt-users.properties'
Added user 'domainMaster' to file 'D:\AppServ\jboss-eap-6.2\domain\configuration\mgmt-users.properties'
Added user 'domainMaster' with groups  to file 'D:\AppServ\jboss-eap-6.2\standalone\configuration\mgmt-groups.properties'
Added user 'domainMaster' with groups  to file 'D:\AppServ\jboss-eap-6.2\domain\configuration\mgmt-groups.properties'
Is this new user going to be used for one AS process to connect to another AS process?
e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls. yes/no? yes
To represent the user add the following to the server-identities definition <secret value="UEBzc3cwcmQ=" />
Press any key to continue . . .

 

接下來的 Step03 & Step04 因為是在同一台主機 Host name: dc-slave / ip: 192.168.3.118 上,所以 management port 要作變動

Step03: 設定 Slave 主機 Host name: dc-slave / ip: 192.168.3.118 上的第一個EAP主機: EAP-instance-two

修改 D:\AppServ\jboss-eap-6.2-1\domain\configuration\host.xml

<host name="EAP-instance-two" xmlns="urn:jboss:domain:1.5">

    .
    .
    .
    <management>

        <security-realms>
            <security-realm name="ManagementRealm">
                <server-identities>
                    <secret value="UEBzc3cwcmQ="/>
                </server-identities>
    .
    .
    .
        <management-interfaces>
            <native-interface security-realm="ManagementRealm">
                <socket interface="management" port="${jboss.management.native.port:9998}"/>
            </native-interface>
            <http-interface security-realm="ManagementRealm">
                <socket interface="management" port="${jboss.management.http.port:9991}"/>
            </http-interface>
        </management-interfaces>
    </management>

    <domain-controller>
        <remote host="192.168.2.4"  port="9999" security-realm="ManagementRealm" username="domainMaster" />        
    </domain-controller>

        <server name="server-two" group="main-server-group" auto-start="true">
            <socket-bindings port-offset="100"/>
        </server>

</host>

 

Step04: 設定 Slave 主機 Host name: dc-slave / ip: 192.168.3.118 上的第二個EAP主機: EAP-instance-three,因為在此 EAP Instance 上有兩個 server:server-threeserver-four 所以要作 port-offset

修改 D:\AppServ\jboss-eap-6.2-1\domain\configuration\host.xml

<host name="EAP-instance-three" xmlns="urn:jboss:domain:1.5">

    .
    .
    .
    <management>

        <security-realms>
            <security-realm name="ManagementRealm">
                <server-identities>
                    <secret value="UEBzc3cwcmQ="/>
                </server-identities>
    .
    .
    .
        <management-interfaces>
            <native-interface security-realm="ManagementRealm">
                <socket interface="management" port="${jboss.management.native.port:9997}"/>
            </native-interface>
            <http-interface security-realm="ManagementRealm">
                <socket interface="management" port="${jboss.management.http.port:9992}"/>
            </http-interface>
        </management-interfaces>
    </management>

    <domain-controller>
        <remote host="192.168.2.4"  port="9999" security-realm="ManagementRealm" username="domainMaster" />        
    </domain-controller>

    <servers>
        <server name="server-three" group="main-server-group" auto-start="true">
            <socket-bindings port-offset="200"/>
        </server>
        <server name="server-four" group="main-server-group" auto-start="true">
            <socket-bindings socket-binding-group="ha-sockets" port-offset="300"/>
        </server>
    </servers>

</host>

 

Step05:啟動 Domain Control 主機 Host name: dc-master / ip: 192.168.2.4

d:/>domain.bat -b YourMasterHostName -bmanagement YourMasterHostName

例:

d:/>domain.bat -b dc-master -bmanagement dc-master

d:/>domain.bat -b 192.168.2.4  -bmanagement 192.168.2.4

 

Step06:啟動 Slave 主機 Host name: dc-slave / ip: 192.168.3.118 上的兩個EAP主機
./domain.sh -Djboss.domain.master.address=YourMasterHostName -b SlaveHostName -bmanagement SlaveHostName

D:\>AppServ\jboss-eap-6.2-1\bin\domain.bat -Djboss.domain.master.address=192.168.2.4 -b 192.168.3.118 -bmanagement 192.168.3.118

D:\>AppServ\jboss-eap-6.2-2\bin\domain.bat -Djboss.domain.master.address=192.168.2.4 -b 192.168.3.118 -bmanagement 192.168.3.118

 

Step07:進入管理介面 http://192.168.2.4:9990/console

JBoss_Domain_RealCase.png  

 

附記:

Configuring a Domain Controller 相關設定文件

Configuration

domain.xml

host.xml

<extensions>

X

 

<system-properties>

X

X

<paths>

X

X

<management>

 

X

<profiles>

X

 

<interfaces>

X

X

<domain-controller>

 

X

<jvms>

 

X

<servers>

 

X

<socket-binding-groups>

X

 

<server-groups>

X

 

<deployments>

X

 

 

 

參考

How to setup EAP6 in Domain Mode with Remote Host Controllers ?

http://wei-meilin.blogspot.tw/2012/07/jeap-6-standalone-domain-mode.html

文章標籤

MIS 發表在 痞客邦 留言(1) 人氣()

JBoss 是一套應用程式伺服器,屬於開源的企業級Java中介軟體軟體,用於實作基於SOA架構的web應用和服務。目前有分:付費有支援的版本JBoss EAP(Enterprise Application Platform) 及 Red Hat 支援社群的 Community edition 免費版本JBoss AS;與一般社群的 WildFly 版本,軟體下載位置 http://wildfly.org/downloads/

JBoss EAP (Enterprise Application Platform) 是一個支持 Java EE 6 的應用服務器,目前 EAP6 實現了兩個 Java EE 6 的配置文件:Full Profile & Web Profile。在實務作業中有 Standalone & Domain Mode 兩種模式,如下圖:

JBoss_Standalone_Domain.png  

 

環境配置的文件分別是:

Standalone Mode:standalone.xml

Domain Mode:domain.xml & host.xml

Standalone Mode 的執行是最簡單的,下載 EAP 6.2.0 GA 壓縮檔並解壓於D:\AppServ\jboss-eap-6.2,編輯 D:\AppServ\jboss-eap-6.2\bin\standalone.bat ,加上JAVA_HOME的設定,即可執行。

@echo off
rem -------------------------------------------------------------------------
rem JBoss Bootstrap Script for Windows
rem -------------------------------------------------------------------------

rem Use --debug to activate debug mode with an optional argument to specify the port
rem Usage : standalone.bat --debug
rem         standalone.bat --debug 9797


set "JAVA_HOME=D:\Progs\jdk1.7.0_45_x64"

 

啟動Jboss:

Windows: standalone.bat
Linux: ./standalone.sh

本機預設的 JBoss 網址:http://localhost:8080
本機預設的 JBoss 管理網址:http://localhost:9990

 

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

主要目的:如何在 eclipse 利用 maven 建立 struts2 並在 eclipse internal runtime Server: Tomcat 作開發環境測試

平台:

eclipse:
Version: Kepler Service Release 2
Build id: 20140224-0627

maven:Maven Integration for Eclipse (Luna and newer) 1.5

tomcat:apache-tomcat-7.0.52_x64

java:jdk1.7.0_45_x64

jboss:JBoss EAP 6.2.0.GA

 

step01:建立一個 struts2-archetype-blank 的 maven 專案

maven_struts_01.png

 

maven_struts_02.png

可以按一下 Add Archetype,建立一個空的 Struts2 專案,相關欄位資訊可以查:http://struts.apache.org/release/2.2.x/docs/struts-2-blank-archetype.html

maven_struts_03.png  

填入此專案相關的資訊

maven_struts_04.png  

目前的 Struts2 專案: guEBS 架構如下:

maven_struts_05.png

 

Step02:轉換成為 Dynamic Web project

選擇此專案 guEBS 按下滑鼠右鍵,選擇 Properties 裡的 Project Facets ,按下 Covert to faceted form...

 

maven_struts_06.png

先將 java 的版本改為 1.7 ,再將 Dynamic Web project 的 check box 打勾,此時下方會出現 "Further configuration available...",Content directory 原本是 WebContent ,修改為 src/main/webapp

maven_struts_07.png

再到 Deployment AssemblyMaven Dependencies 加入,然後按 Apply -> ok。

maven_struts_071.png  

 

Step03:Deploy to Internal runtime Server:Tomcat 測試

執行 Maven build 時, 應該在 target 目前下會產生 guEBS-1.0.0-SNAPSHOT.war,這個檔直接可以佈署在 JBoss 下執行。

maven_struts_08.png

 

也可以佈署在 eclipse 內的 runtime server,這裡 runtime server 使用的是 apache-tomcat-7.0.52_x64

maven_struts_09.png

 

執行時,會出現下列的錯誤訊息:The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory

Messages:     
Unable to compile class for JSP: An error occurred at line: [42] in the generated java file: [D:\wei_workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\guEBS\org\apache\jsp\example\HelloWorld_jsp.java] The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory Stacktrace:

maven_struts_072.png  

The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory 的異常的原因及解決辦法。

原因:這是由於工程的WEB-INF/lib下存在 jsp-api.jar、servlet-api.jar,與Tomcat自帶的jar包衝突造成的。
解決辦法:

從 pom.xml 檔中移除 jsp-api.jar、servlet-api.jar 的 dependency 設定

<!-- 本機 Tomcat 測試時, servlet-api , jsp-api 不要載入
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.4</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
-->

 在測試一次,就沒有問題了,但若是佈署在 JBoss EAP 6.2.0.GA 則不需要在 pom.xml 檔的內文中移除 jsp-api.jar、servlet-api.jar 的 dependency 設定。

maven_struts_10.png

注意:若要重新作 maven build 產生 guEBS-1.0.0-SNAPSHOT.war 檔時,jsp-api.jar、servlet-api.jar 的 dependency 設定要加回來,不然會有錯誤訊息。

maven_struts_11.png  

 

參考:

http://struts.apache.org/release/2.2.x/docs/struts-2-maven-archetypes.html

https://wiki.base22.com/display/btg/How+to+create+a+Maven+web+app+and+deploy+to+Tomcat+-+fast

http://www.avajava.com/tutorials/lessons/how-do-i-deploy-a-maven-web-application-to-tomcat.html

http://developer.51cto.com/art/201205/338496.htm

 

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

概念:

Apache Rewirte 主要的功能就是實現URL的跳轉,它的正則運算式是基於Perl 語言。可基於伺服器級的(HTTPd.conf)和目錄級的 (.htaccess)兩種方式。如果要想用到rewrite模組,必須先安裝或載入rewrite模組。

Apache mod_rewrite 規則重寫的標誌一覽

1) R[=code](force redirect) 強制外部重定向:強制在替代字串加上HTTP://thishost[:thisport]/首碼重定向到外部的URL.如果code不指定,將用缺省的302 HTTP狀態碼。

2) F(force URL to be forbidden)禁用URL,返回403HTTP狀態碼。

3) G(force URL to be gone) 強制URL為GONE,返回410HTTP狀態碼。

4) P(force proxy) 強制使用代理轉發。

5) L(last rule) 表明當前規則是最後一條規則,停止分析以後規則的重寫。

6) N(next round) 重新從第一條規則開始運行重寫過程。

7) C(chained with next rule) 與下一條規則關聯:如果規則匹配則正常處理,該標誌無效,如果不匹配,那麼下面所有關聯的規則都跳過。

8) T=MIME-type(force MIME type) 強制MIME類型

9) NS (used only if no internal sub-request) 只用于不是內部子請求

10) NC(no case) 不區分大小寫

11) QSA(query string append) 追加請求字串

12) NE(no URI escaping of output) 不在輸出轉義特殊字元

實作:

首先要讓 Apache 支援 mod_rewrite,可以在 httpd.conf 看有沒有這一行

LoadModule rewrite_module modules/mod_rewrite.so

接下來要準備設定 mod_rewrite,原則上有二種寫法,一種是直接寫在 httpd.conf 裡面,另一種是寫在 .htaccess 裡面,若要寫在 .htaccess 也要特別注意 Apache 是否有支援,以 xampp.v182 來作說明,原則上預設是開啟的,它的 httpd.conf 內容為:

LoadModule rewrite_module modules/mod_rewrite.so

<Directory />
    AllowOverride none
    Require all denied
</Directory>

DocumentRoot "D:/AppServ/xampp.v182/htdocs"
<Directory "D:/AppServ/xampp.v182/htdocs">
    Options Indexes FollowSymLinks Includes ExecCGI
    AllowOverride All
    Require all granted
</Directory>

 

虛擬主機的設定 httpd-vhosts.conf

<VirtualHost *:80>
    ServerAdmin polin.wei@localhost.bootstrap
    DocumentRoot "D:/AppServ/xampp.v182/htdocs/bootstrap"
    ServerName localhost.bootstrap
    ErrorLog "logs/bootstrap-error.log"
    CustomLog "logs/bootstrap-access.log" common
</VirtualHost>

 

在目錄 D:/AppServ/xampp.v182/htdocs/bootstrap 的 .htaccess

Options -Indexes
RewriteEngine on //開啟Rewrite功能
RewriteBase /

RewriteRule  ^about/(.*)/(.*)$ page.php?type=$1&name=$2 [NC,L]

 

這樣子,就可以將原先程式 http://localhost.bootstrap/page.php?type=polin&name=wei 變成 http://localhost.bootstrap/about/polin/wei

 

 

 

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

上篇 ADF Table : Row selection using checkboxes 覺得那樣作有點麻煩, 經過思考及整理後, 覺得下列作法較佳:

 

前置作業:

1. 使用 Table: USERS 來作示範

CREATE TABLE "USERS"(
      "USERNAME" VARCHAR2(15 BYTE) NOT NULL  PRIMARY KEY ENABLE ,
    "NAME"     VARCHAR2(255 BYTE) NOT NULL ENABLE,
    "PASSWORD" VARCHAR2(15 BYTE) NOT NULL ENABLE
  )

 

Step 01:

建立的 EO (Entity Objects): UsersEO 自行加入一個暫時記錄資料(transient attribute)的欄位 Selected , Type: Boolean, 因不需回寫 Table, 所以將屬性 Persistent 拿掉

TableCheckboxSelect_EO.png 

Step 02: 建立 VO: UsersVO,並加入三個 function 於 UsersVOImpl 中: selectAll(), deSelectAll(), deleteSelectedRows()

TableCheckbox_bestSolution_01.png

import com.wei.model.vo.common.UsersVO;

import oracle.jbo.Row;
import oracle.jbo.RowSet;
import oracle.jbo.RowSetIterator;
import oracle.jbo.server.ViewObjectImpl;
// ---------------------------------------------------------------------
// ---    File generated by Oracle ADF Business Components Design Time.
// ---    Fri Jun 13 15:21:46 CST 2014
// ---    Custom code may be added to this class.
// ---    Warning: Do not modify method signatures of generated methods.
// ---------------------------------------------------------------------
public class UsersVOImpl extends ViewObjectImpl implements UsersVO {
    /**
     * This is the default constructor (do not remove).
     */
    public UsersVOImpl() {
    }

    public void selectAll(){
        RowSetIterator row =  this.getRowSetIterator();
        row.reset();
        if (row.first() != null) {
            Row r = row.first();
            r.setAttribute("Selected", true);
        }
        while(row.hasNext()){
            Row r = row.next();
            r.setAttribute("Selected", true);
        }
        
    }
    public void deSelectAll(){
        RowSetIterator row =  this.getRowSetIterator();
        row.reset();
        if (row.first() != null) {
            Row r = row.first();
            r.setAttribute("Selected", false);
        }
        while(row.hasNext()){
            Row r = row.next();
            r.setAttribute("Selected", false);
        }
        
    }    
    public void deleteSelectedRows() {        
        Row[] selectedRowsToDelete = this.getFilteredRows("Selected",true);
        if (selectedRowsToDelete.length>0){
            for ( Row row: selectedRowsToDelete) {                
                row.remove();
            }
        }
        this.executeQuery();
        this.getDBTransaction().commit(); //直接刪除資料
    }
}

 

Step 03: 將自建的 function 註冊, 以便轉換可使用的 method

TableCheckbox_bestSolution_02.png

 

Step 04: 將註冊好的 method 拖拉至 tableCheckBoxSelect.jspx 中使用.

TableCheckbox_bestSolution_03.png

 

執行的結果如下, 這樣是不是很簡便呢?

TableCheckbox_bestSolution_04.png  

 參考文件:

http://docs.oracle.com/cd/B14099_19/web.1012/b14022/overview-summary.html
https://java.net/projects/smuenchadf/pages/ADFSamples

http://jdevadf.oracle.com/

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

From: Polin Wei

在Table的作業中, 常會有將所有筆數全選( Select All Rows)的需求, 在 ADF 的 Table 要實現這樣的效果卻有點難(好難搞的 ADF....) , Google 一下查到一些高手的作法, 整理如下.

前置作業:

1. 使用 Table: USERS 來作示範

CREATE TABLE "USERS"(
      "USERNAME" VARCHAR2(15 BYTE) NOT NULL  PRIMARY KEY ENABLE ,
    "NAME"     VARCHAR2(255 BYTE) NOT NULL ENABLE,
    "PASSWORD" VARCHAR2(15 BYTE) NOT NULL ENABLE
  )

 

2. 建立一個 JavaBean: UsersTableBean

package com.wei.bean;

import com.wei.utils.ADFUtils;

import java.util.ArrayList;

import javax.faces.event.ValueChangeEvent;

import oracle.adf.model.binding.DCIteratorBinding;
import oracle.adf.view.rich.component.rich.data.RichTable;

import oracle.adf.view.rich.context.AdfFacesContext;
import oracle.adf.view.rich.render.ClientEvent;

import oracle.jbo.Row;
import oracle.jbo.RowSetIterator;

import org.apache.myfaces.trinidad.model.CollectionModel;
import org.apache.myfaces.trinidad.model.RowKeySet;
import org.apache.myfaces.trinidad.model.RowKeySetImpl;

public class UsersTableBean {
    private RowKeySet selectedRows;
    private RichTable table;
    private static final String ITERATOR_NAME = "UsersVO1Iterator";

    public UsersTableBean() {
        super();
    }


    public void setSelectedRows(RowKeySet selectedRows) {
        this.selectedRows = selectedRows;
    }

    public RowKeySet getSelectedRows() {
        if (selectedRows == null) {
            selectedRows = new RowKeySetImpl();
            CollectionModel collectionModel =
                (CollectionModel)getTable().getValue();
            selectedRows.setCollectionModel(collectionModel);
        }

        return selectedRows;
    }

    public void setTable(RichTable table) {
        this.table = table;
    }

    public RichTable getTable() {
        return table;
    }

    public void rowSelected(ClientEvent clientEvent) {
        refreshSelectedRows();
        AdfFacesContext.getCurrentInstance().addPartialTarget(getTable());

    }

    public void selectAll(ValueChangeEvent valueChangeEvent) {
        DCIteratorBinding it = ADFUtils.findIterator(ITERATOR_NAME);
        RowSetIterator rit = it.getRowSetIterator();
        rit.reset();
        if (valueChangeEvent.getNewValue() != null) {
            Boolean selectAll =
                Boolean.parseBoolean(valueChangeEvent.getNewValue().toString());
            if (rit.first() != null) {
                Row r = rit.first();
                r.setAttribute("Selected", selectAll);
            }
            while (rit.hasNext()) {
                Row r = rit.next();
                if (r != null) {
                    r.setAttribute("Selected", selectAll);
                }
            }
        }

        refreshSelectedRows();
        it.executeQuery();
    }

    private void refreshSelectedRows() {
        getSelectedRows().clear();

        DCIteratorBinding it = ADFUtils.findIterator(ITERATOR_NAME);
        RowSetIterator rit = it.getRowSetIterator();
        rit.reset();

        if (rit.first() != null) {
            Row r = rit.first();
            if (r.getAttribute("Selected") != null) {
                makeRowSelected(r);
            }
        }
        while (rit.hasNext()) {
            Row r = rit.next();
            if (r.getAttribute("Selected") != null) {
                makeRowSelected(r);
            }
        }

    }

    private void makeRowSelected(Row r) {
        Boolean selected = (Boolean)r.getAttribute("Selected");
        if (selected) {
            ArrayList keyList = new ArrayList();
            keyList.add(r.getKey());
            getSelectedRows().add(keyList);
        }
    }

}

 

Step 01:

建立的 EO (Entity Objects): USERSEO 自行加入一個暫時記錄資料(transient attribute)的欄位 Selected , Type: Boolean, 因不需回寫 Table, 所以將屬性 Persistent 拿掉

TableCheckboxSelect_EO.png  

 

Step 02: 建立一個檔案 tableCheckBoxSelect.jspx , 將 UserVO1 拖拉進來,並選轉換為ADF Table 物件


 TableCheckboxSelect_tableProperty.png  
 

Section Attribute Value
Common Id t1
  rowSelection multiple
Behavior partialTriggers selectAll
Advanced binding #{viewScope.UsersTableBean.table}
  selectedRowKeys #{viewScope.UsersTableBean.selectedRows}

 

Step 03: 再將 Selected 欄位 Convert To CheckBox

TableCheckboxSelect_ConvertToCheckbox.png  

在作 Convert 時, 可以挑選要 Binding 的資料來源, 原則上不需變動

TableCheckboxSelect_ConvertToCheckbox_Binding.png

最後確認時, 是告知轉換成 Checkbox 時, 這兩個欄位屬性: MaximumLength、Columns會被移除

TableCheckboxSelect_ConvertToCheckbox_Confirm.png  

在 Headline 加入 SelectBooleanCheckbox 元件

TableCheckboxSelect_HeadlineAddCheckbox.png  

 

Section Attribute Value
Common Id selectAll
  Width 30
Behavior autoSubmit true
  valueChangeListener #{viewScope.UsersTableBean.selectAll}

 

這是方法之一, 但第一次選擇時 Table 裡的每一個ROW 的 checkBox 卻沒有被打勾, 這未解決......

 

 參考:

http://www.gebs.ro/blog/oracle/oracle-adf-row-selection-using-checkboxes/

http://www.oracle.com/technetwork/developer-tools/adf/learnmore/34-extra-arguments-to-javascript-169176.pdf

http://docs.oracle.com/cd/E16764_01/web.1111/b31973/af_event.htm

http://docs.oracle.com/cd/B14099_19/web.1012/b14022/overview-summary.html

http://jdevadf.oracle.com

 Section 5.3.1, "How to Return the Original Source of the Event.

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()

環境:

ADF version: 11.1.1.6.0
Oracle EBS version: R12.2.3

程式的目的在於取得 EBS 登入時的使用者相關資訊。整個程式架構如下圖:

ADF_Integrate_EBS_01.png  

 

 

ADF 的程式面:

Step 01: 在 ViewController 依序建立 Java Class:ConnectionProvider、EBizUtil、EBSWrapperFilter、以及存取使用者資訊的 Java Bean: UserInfo

資料的

ConnectionProvider.java

package com.oracle.view;

import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class ConnectionProvider {
    private static DataSource ebsDS = null;
    static{
        try {
            Context ctx = new InitialContext();
            ebsDS = (DataSource) ctx.lookup("jdbc/TEST32");
            
            // your datasource jndi name as defined during configuration
            if (ctx != null)
                ctx.close();
            
        } catch (Exception e) {
            // TODO: Add catch code
            //ne.printStackTrace(); //ideally you should log it
            throw new RuntimeException(e);
            // means jndi setup is not correct or doesn't exist
        }
    }
    
    private ConnectionProvider() {
        super();
    }
    

   public static Connection getConnection() throws SQLException{
        if (ebsDS == null)
            throw new IllegalStateException("AppsDatasource is not properly initialized or available");
        return ebsDS.getConnection();
    }
 
    
}

PS: 在 EBS 環境中是以 jdbc 的模式取得資料庫連線,可以進入 weblogic 的 Services-> Data Sources 查看,如:EBSDataSource 的 JNDI: jdbc/TEST32 ,並可以得知要佈署到那一個主機上:oacore_cluster1

ADF_Integrate_EBS_06.png  

 

EBizUtil.java

package com.oracle.view;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import oracle.apps.fnd.ext.common.EBiz;


public class EBizUtil {
    public EBizUtil() {
        super();
    }
    private static final Logger logger = Logger.getLogger(EBizUtil.class.getName());
    private static EBiz INSTANCE = null;
    static {
        Connection connection = null;
        try {
            connection = ConnectionProvider.getConnection();
            // DO NOT hard code applServerID for a real application
            // Get applServerID as CONTEXT-PARAM from web.xml or elsewhere
            INSTANCE = new EBiz(connection, "F1CB87199593E5F4E0431F030A0AD0AB31310251131793525291714692481335");
        } catch (SQLException e) {
            logger.log(Level.SEVERE, "SQLException while creating EBiz instance -->", e);
            throw new RuntimeException(e);
        } catch (Exception e) {
            logger.log(Level.SEVERE, "Exception while creating EBiz instance -->", e);
            throw new RuntimeException(e);
        } finally {
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public static EBiz getEBizInstance() {
        return INSTANCE;
    }    
    
}

PS: APPL_SERVER_ID 可以到 EBS APP Server 路徑下的 $INST_TOP/appl/fnd/12.0.0/secure/TEST32.dbc 取得
Server ID :
APPL_SERVER_ID=F1CB87199593E5F4E0431F030A0AD0AB31310251131793525291714692481335

EBSWrapperFilter.java

package com.oracle.view;

import java.io.IOException;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import oracle.apps.fnd.ext.common.AppsRequestWrapper;
import oracle.apps.fnd.ext.common.AppsRequestWrapper.WrapperException;

public class EBSWrapperFilter implements Filter {
    public EBSWrapperFilter() {
        super();
    }


    private static final Logger logger = Logger.getLogger(EBSWrapperFilter.class.getName());
    
    public void init(FilterConfig filterConfig) {
        logger.info("Filter initialized ");
    }

    public void doFilter(ServletRequest request, ServletResponse response,  FilterChain chain) throws IOException,ServletException {
        AppsRequestWrapper wrapper = null;
        logger.info("-current URI =" + ((HttpServletRequest)request).getRequestURI());

        try {
            
            wrapper = new AppsRequestWrapper((HttpServletRequest)request, (HttpServletResponse)response, ConnectionProvider.getConnection(), EBizUtil.getEBizInstance());
            
        } catch (WrapperException e2) {
            logger.log(Level.SEVERE, "WrapperException error encountered ", e2);
            throw new ServletException(e2);
        } catch (SQLException e2) {
            logger.log(Level.SEVERE, "SQLException error encountered ", e2);
            throw new ServletException(e2);
        }
        try {
            logger.info("Created AppsRequestWrapper object." + " Continuing the filter chain.");
            chain.doFilter(wrapper, response);
            logger.info("- the filter chain ends");
        } finally {
            //AppsRequestWrapper caches a connection internally.
            //AppsRequestWrapper.getConnection()--returns this connection this connection can be used in doGet()/doPost() service layer
            //whenever our application requires a connection in order to service the current request.
            //When AppsRequestWrapper instance is in use, this connection should not be closed by other code.
            //At this point, we are done using AppsRequestWrapper instance so, as good practice, we are going to close (release) this connection now.
            if (wrapper != null) {
                try {
                    logger.info("- releasing the connection attached to the" + " current AppsRequestWrapper instance ");
                    wrapper.getConnection().close();
                } catch (SQLException e3) {
                    logger.log(Level.WARNING, "SQLException error while closing connection--", e3);
                    throw new ServletException(e3);
                }
            }
            wrapper = null;
        }
    }

    public void destroy() {
        logger.info("Filter destroyed ");
    }
}

 

UserInfo.java

package com.oracle.bean;

import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import oracle.apps.fnd.ext.common.AppsRequestWrapper;
import oracle.apps.fnd.ext.common.Session;

public class UserInfo {
    private String user;
    private String userInfo;

    public UserInfo() {
        super();
    }


    public void setUser(String user) {
        this.user = user;
    }

    public String getUser() {
        return user;
    }


    public void beforePhase(PhaseEvent phaseEvent) {
        // Add event code here...
        AppsRequestWrapper wrappedRequest =
            (AppsRequestWrapper)FacesContext.getCurrentInstance().getExternalContext().getRequest();

        Session session = wrappedRequest.getAppsSession();

        setUser(session.getUserName());

        Map columns = session.getInfo();
        StringBuffer temp = new StringBuffer();
        temp.append("<table>");
        for (Object key : columns.keySet()) {
            temp.append("<tr>");
            temp.append("<td>");
            temp.append(key);
            temp.append("</td>");
            temp.append("<td>");
            temp.append(columns.get(key));
            temp.append("</td>");
            temp.append("</tr>");
        }
        temp.append("</table>");

        setUserInfo(temp.toString());

    }

    public void setUserInfo(String userInfo) {
        this.userInfo = userInfo;
    }

    public String getUserInfo() {
        return userInfo;
    }
}

 

Step 02:在 adfc-config.xml 建立 view: userInfo.jspx 及 設定 Managed Beans

userInfo.jspx

版面:PageGroupLayout :layout = vertical
      OutPutText:value="Hello #{pageFlowScope.userInfoBean.user}!!"
          inlineStyle="font-size:medium; color:Red;"
      Separator
       OutPutText:value="#User Info:<br>#{pageFlowScope.userInfoBean.userInfo}"
           escape="false"
                  inlineStyle="font-size:medium;"

  ADF_Integrate_EBS_03.png

 

Managed BeansuserInfoBean

  ADF_Integrate_EBS_02.png

 

Step 03: 設定 userInfo.jspx 的 beforePhase

ADF_Integrate_EBS_04.png  

這是在 UserInfo.java 的一段程式

    public void beforePhase(PhaseEvent phaseEvent) {
        // Add event code here...
        AppsRequestWrapper wrappedRequest =
            (AppsRequestWrapper)FacesContext.getCurrentInstance().getExternalContext().getRequest();

        Session session = wrappedRequest.getAppsSession();

        setUser(session.getUserName());

        Map columns = session.getInfo();
        StringBuffer temp = new StringBuffer();
        temp.append("<table>");
        for (Object key : columns.keySet()) {
            temp.append("<tr>");
            temp.append("<td>");
            temp.append(key);
            temp.append("</td>");
            temp.append("<td>");
            temp.append(columns.get(key));
            temp.append("</td>");
            temp.append("</tr>");
        }
        temp.append("</table>");

        setUserInfo(temp.toString());

    }

 

Step 04 : web.xml 中設定 Filters

ADF_Integrate_EBS_05.png  

 

Oracle EBS 上的設定:

Step 01: 設定 Function : Menu: Responsibiliey:

Function: WEI_ADFLAB_USERINFO

Function WEI_ADFLAB_USERINFO
Properties-Type External ADF Application
WebHTML-HTML Call GWY.jsp?targetPage=faces/userInfo
   

 ADF_Integrate_EBS_07.png  

ADF_Integrate_EBS_08.png

 

Menu:WEI_LAB_MENU

ADF_Integrate_EBS_09.png  

 

Responsibility: WEI Labs

ADF_Integrate_EBS_10.png  
  

Step 02: Responsibility: Functional Administrator 上的設定

a. Core Services → Profiles → Code: FND_EXTERNAL_ADF_URL → Go

b. 然後點選External ADF Application URL 後按 Define Profile Values

ADF_Integrate_EBS_11.png  

 

a. 點選Define Profile Values → Responsibility
b. 選擇 Responsibility & Value
c. Value:  客製程式在 weblogic 的路徑,如: http://lnxap104:7214/LAB_EBS-ViewController-context-root/ ,最後要加 /
d. 按 Update

ADF_Integrate_EBS_12.png  

一個Responsibility只能綁定一個程式的root,所以如果有多個功能,可能要放在同一包應用程式裡面。也有其它使用者在問此問題,但現在並沒有進一步的解法。例如: Oracle論壇,其他使用者提問的 >> 問題
 

Step 03: 清除 Caching Framework & Testing

ADF_Integrate_EBS_12-1.png

ADF_Integrate_EBS_13.png  

 

 

 

 

文章標籤

MIS 發表在 痞客邦 留言(1) 人氣()

這一篇文章主要是在記錄利用 JDeveloper 去部署 (Deploy) ADF 的程式到 Weblogic Server 上。

 

在 Weblogic 建立測試運作的 Server:

 Step01: 登入 weblogic 管理頁面 ( Administration Console )

一般來說預設的 port 是 7001,例:http://lnxap104:7014/console,登入後,要先 Lock & Edit ,Weblogic 主機的維護同時間只能一個人進入操作。

create_server_01.png

 

Step 02: 輸入

*Server Name : AP 要佈署的主機

Server Listen Address :DNS 能解析到的 Host Name

*Server Listen Port: 監聽的 port

create_server_02.png

 

Step 03: 建立新主機的相關資訊,按下 Finish 就建立好了

 

create_server_03.png

Step 04: 進入新建立的主機 TEST_Server 作設定

create_server_04.png

在 Machine 欄位,將此 TEST_Server 選入要放在那一台主機 HOST 上

create_server_05.png

Step 05: 啟動建好的 AP Server

create_server_06.png

記得下面的資訊:

右上角是目前 weblogic 連接的域名 ( Domain ):EBS_domain_TEST32

create_server_07.png

點選 Machines -> lnxap104 後選 Monitoring 可以得知 HOST 上安裝 Weblogic 的版本

create_server_08.png

最後記得要將這些改變保留( Activate Changes)

create_server_08_1.png

PS: JDeveloper Deploy 要連接的主機是 AdminServer(admin),要記得它的 Listen Port:7014

 

用 JDeveloper Deploy ADF 程式在 Weblogic 運作的測試 Server:TEST_Server

 

Step 01: 加入 Weblogic

create_server_09.png create_server_10.png

要選對主機的型態,上面已得知Weblogic 的版本是 10.3

create_server_11.png

輸入 Weblogic 的管理帳號/密碼,帳號預設應是 weblogic

create_server_12.png

這裡要輸入的 port 是要連接主機 AdminServer(admin),它的 Listen Port:7014

create_server_13.png

可以按 Test Connection 測試一下

create_server_14.png

 

Step 02: JDeveloper 開發工具上的環境設定

create_server_15.png

選擇 Application -> APplication Properties 的 Deployment 頁次,將 Auto Generate and Synchronize weblogic-jdbc.xml ... 選項取消

create_server_16.png

Step 03: Deploy ADF to weblogic Server:

create_server_17.png

create_server_18.png

 

選擇剛建立好的連結

create_server_19.png

 

選擇要佈署的主機

create_server_20.png

create_server_21.png

 

從 Deployment - log 視窗可看佈署是否成功

create_server_22.png

 

若是手動佈署的話,要記得作 Servicing all requests

create_server_23.png

 

 

create_server_24.png

 

 

若您撰寫的程式有需要其它的 JAR 檔,請依下列步驟加到 AP Server:TEST_Server 中

Step 01: 選擇要加入的 JAR 檔

create_server_25.png

Step 02: 加入到 AP Server: TEST_Server 主機裡

create_server_26.png

 

 

測試時,記得在網址最後要加入 /faces/程式名

create_server_27.png  

文章標籤

MIS 發表在 痞客邦 留言(0) 人氣()