2015年7月31日星期五

EAP_025:为EAP配置SSO

环境:JBoss EAP 6.4.0

1. 修改standalone.xml 文件,在security-domains中增加如下内容:
<security-domain name="sso" cache-type="default">
    <authentication>
        <login-module code="UsersRoles" flag="required">
            <module-option name="usersProperties" value="${jboss.server.config.dir}/users.properties"/>
            <module-option name="rolesProperties" value="${jboss.server.config.dir}/roles.properties"/>
        </login-module>
    </authentication>
</security-domain>

2. 在[jboss_home_dir]/configuration目录下新增一个文件:users.properties
内容如下:
test=test

3. 在[jboss_home_dir]/configuration目录下新增一个文件:roles.properties
内容如下:
test=Manager

4. 修改Web应用中jboss-web.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>

<jboss-web xmlns="http://www.jboss.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.jboss.org/schema/jbossas
    http://www.jboss.org/schema/jbossas/jboss-web_7_2.xsd">
    <!-- Configure usage of the security domain "other" -->
    <security-domain>sso</security-domain>
    <valve>
        <class-name>org.apache.catalina.authenticator.SingleSignOn</class-name>
    </valve>
</jboss-web>

5. 修改Web应用中web.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>

<web-app version="3.0" 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_3_0.xsd">
   
    <display-name>example1</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>
   
    <security-constraint>
        <web-resource-collection>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>Manager</role-name>
        </auth-constraint>
    </security-constraint>
   
    <login-config>
        <auth-method>FORM</auth-method>
        <realm-name>Sample Realm</realm-name>
        <form-login-config>
            <form-login-page>/jsp/login.jsp</form-login-page>
            <form-error-page>/jsp/login-error.jsp</form-error-page>
        </form-login-config>
    </login-config>
   
    <security-role>
        <role-name>Manager</role-name>
    </security-role>
</web-app>


6. login.jsp 内容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Simple Web App</title>
</head>
<body>
<h1>Welcome to EAP 6</h1>
<p>This is a simple web app deployed as a compressed WAR file named example.war</p>
<form id="login_form" name="login_form" method="post"
            action="j_security_check" enctype="application/x-www-form-urlencoded">
            <center>
                 
                <p>Please login to proceed.</p>
            </center>

            <div style="margin-left: 15px;">
                <p>
                    <label for="username"> Username</label><br /> <input id="username"
                        type="text" name="j_username" size="20" />
                </p>
                <p>
                    <label for="password"> Password</label><br /> <input id="password"
                        type="password" name="j_password" value="" size="20" />
                </p>
                <center>
                    <input id="submit" type="submit" name="submit" value="Login"
                        class="buttonmed" />
                </center>
            </div>
        </form>
</body>
</html>

7. 启动JBoss EAP,先后部署example1.war 和 example2.war

8.  访问 http://localhost:18080/example1/ 
由于配置了安全,会提示登陆,输入用户名test,口令test,成功登陆后,直接访问
http://localhost:18080/example2/,发现不再提示登陆。说明SSO配置成功。

参考文献:
1. http://www.mastertheboss.com/jboss-server/jboss-security/configuring-single-signon-on-jboss-as-7
2. 《JBoss_Enterprise_Application_Platform-6.4-Security_Guide-en-US.pdf》

JDG_010:使用JDG外部缓存HTTP Session

环境:JBoss EAP 6.4.0 + JBoss Data Grid 6.5.0

JBoss Data Grid 6.5.0 有个新特性:可以把JDG 作为外部缓存来存储HTTP Session,这样做的好处是:
(1)减轻了应用服务器的内存压力以及集群节点间的 Session 复制。
(2)利用JDG的横向扩展能力,可以容纳更多的 Session 对象。
(3)利用JDG的数据冗余机制,可以保证 Session 对象不丢失。

本文介绍如何使用JDG外部缓存HTTP Session,其中
(1)使用两个JBoss EAP 6.4.0 组成Standalone Mode 集群
(2)使用一个JBoss Data Grid Server 作为外部缓存来存储HTTP Session(可以扩展成多个节点)

主要步骤:

1. 配置JBoss  EAP Standalone Mode 集群

1.1 安装与启动 JBoss EAP 6.4.0
(1)unzip jboss-eap-6.4.0.zip
(2)cd jboss-eap-6.4/bin
(3)./standalone.sh
(4)http://localhost:9990/,访问出错,提示创建用户
(5)./add-user.sh
(6)http://localhost:9990/,点击Try again,输入管理员账户口令
(7)停止 EAP

1.2 配置两个节点的JBoss EAP 集群
(1)mkdir node1
(2)cp -r ./jboss-eap-6.4/standalone/configuration ./jboss-eap-6.4/standalone/deployments ./jboss-eap-6.4/standalone/lib node1
(3)mkdir node2
(4)cp -r ./jboss-eap-6.4/standalone/configuration ./jboss-eap-6.4/standalone/deployments ./jboss-eap-6.4/standalone/lib node2
(5)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/node1 -c standalone-ha.xml -b 127.0.0.1 -bmanagement 127.0.0.1 -u 239.255.100.100 -Djboss.socket.binding.port-offset=100 -Djboss.node.name=node1
(6)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/node2 -c standalone-ha.xml -b 127.0.0.1 -bmanagement 127.0.0.1 -u 239.255.100.100 -Djboss.socket.binding.port-offset=200 -Djboss.node.name=node2
(7)http://localhost:10090/console/ 部署 cluster_test.war
(8)http://localhost:10190/console/ 部署 cluster_test.war
(9)http://localhost:8180/cluster_test/
(10)http://localhost:8280/cluster_test/ 
分别刷新 http://localhost:8180/cluster_test/页面和http://localhost:8280/cluster_test/ 页面,如果发现统计数字在两个页面中是持续增加的,就说明集群配置成功。

 2. 安装与启动 JBoss Data Grid 6.5.0
 (1)unzip jboss-datagrid-6.5.0-server.zip
 (2)cd jboss-datagrid-6.5.0-server/bin
 (3)./standalone.sh

 3. 配置JDG外部缓存HTTP Session

 3.1 修改node1下的standalone-ha.xml文件
 (1)把原来的cache-container name="web" 内容

<cache-container name="web" aliases="standard-session-cache" default-cache="repl" module="org.jboss.as.clustering.web.infinispan">
    <transport lock-timeout="60000"/>
    <replicated-cache name="repl" mode="ASYNC" batching="true">
        <file-store/>
    </replicated-cache>
    <replicated-cache name="sso" mode="SYNC" batching="true"/>
    <distributed-cache name="dist" mode="ASYNC" batching="true" l1-lifespan="0">
        <file-store/>
    </distributed-cache>
</cache-container>
替换为
<cache-container name="web" default-cache="default-cache" module="org.jboss.as.clustering.web.infinispan" statistics-enabled="true">
    <transport lock-timeout="60000"/>
    <replicated-cache name="default-cache" mode="SYNC" batching="true">
        <remote-store cache="default" socket-timeout="60000" preload="true" passivation="false" purge="false" shared="true">
            <remote-server outbound-socket-binding="remote-jdg-server1"/>
        </remote-store>
    </replicated-cache>
</cache-container>

(2)在socket-binding-group中增加如下内容:
<outbound-socket-binding name="remote-jdg-server1">
    <remote-destination host="localhost" port="11222"/>
</outbound-socket-binding>
 (3)重启 node1

 3.2 修改node2下的standalone-ha.xml文件
修改内容和 node1 完全一样。

4. 再次访问cluster_test应用,效果跟JBoss EAP 集群一样,但HTTP Session是存储在JBoss Data Grid Server上的。

参考文献:
1. 《Red_Hat_JBoss_Data_Grid-6.5-Administration_and_Configuration_Guide-en-US.pdf》

2015年7月30日星期四

EAP_024:EAP 6 功能演示2 :DataSource 部署

环境:JBoss EAP 6.4

1. 部署 DataSource (Derby)

1.1 部署 JDBC jar 方式
(1)cd /Users/maping/Apache/db-derby/bin
    启动 ./startNetworkServer
    停止 ./stopNetworkServer
    进入SQL交互 ./ij
    ij> Connect 'jdbc:derby:demoDB;create=true;user=demo;password=demo';
    ij> CREATE TABLE test_table(id int primary key, name varchar(20));
    ij> INSERT INTO test_table VALUES(1,'China');
    ij> SELECT * FROM test_table;
    ij> Connect 'jdbc:derby:demoDB;user=demo;password=demo';
    ij> SELECT * FROM test_table;
(2)SQuirrel SQL 连接地址:jdbc:derby://localhost:1527/demoDB
注意,使用SQuirrel SQL客户端连接时,要断开ij客户端,否则连不上,原因不明。   
(3)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -Djboss.socket.binding.port-offset=10000
(4)部署 db-derby 的JDBC jar:derbyclient.jar
(5)创建并配置 DataSource,name:DerbyDSPool,JNDI:java:jboss/datasources/DerbyDS
(6)http://localhost:19990/ 部署 dstest.war
(7)http://localhost:18080/dstest

1.2 以module方式部署 JDBC jar
(1)(2)步 与 部署JDBC jar 方式相同
(3)在 [jboss_home]/modules 目录下,创建目录:mkdir -p org/apache/derby/main,在 main 目录下创建 module.xml,内容如下:
     <?xml version="1.0" encoding="UTF-8"?>
        <module xmlns="urn:jboss:module:1.1" name="org.apache.derby">
           <resources>
              <resource-root path="derbyclient.jar"/>
           </resources>
           <dependencies>
              <module name="javax.api"/>
              <module name="javax.transaction.api"/>
           </dependencies>
     </module>
(4)复制 derbyclient.jar 到main目录下
(5)cp standalone.xml standalone-derby.xml
(6)vim standalone-derby.xml,修改datasource部分
     <subsystem xmlns="urn:jboss:domain:datasources:1.2">
            <datasources>
                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
                    <connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
                    <driver>h2</driver>
                    <security>
                        <user-name>sa</user-name>
                        <password>sa</password>
                    </security>
                </datasource>
                <datasource jndi-name="java:jboss/datasources/DemoDataSource" pool-name=“DemoDataSource" enabled="true" use-ccm="false">
                    <connection-url>jdbc:derby://localhost:1527/demoDB</connection-url>
                    <driver>org.apache.derby</driver>
                    <security>
                        <user-name>demo</user-name>
                        <password>demo</password>
                    </security>
                    <validation>
                        <validate-on-match>false</validate-on-match>
                        <background-validation>false</background-validation>
                    </validation>
                    <statement>
                        <share-prepared-statements>false</share-prepared-statements>
                    </statement>
                </datasource>
                <drivers>
                    <driver name="h2" module="com.h2database.h2">
                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                    </driver>
                    <driver name="org.apache.derby" module="org.apache.derby">
                        <xa-datasource-class>org.apache.derby.jdbc.ClientXADataSource</xa-datasource-class>
                    </driver>
                </drivers>
            </datasources>
        </subsystem>

(7)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -c standalone-derby.xml -Djboss.socket.binding.port-offset=10000
(8)http://localhost:19990/ 部署 dstest.war
(9)http://localhost:18080/dstest


2015年7月25日星期六

SpeechEnglish_003: 2015年NASA预告片《新视野号接近冥王星》 (摘录+整理)


It has been over three thousand days since we left Earth.
距离我们离开地球已经3000个日日夜夜。
We're now almost 3 billion miles away from home, out here where the sun is distant and faint is a place no one has ever seen before.
我们的位置距离地球足有48亿公里之遥,在这里太阳遥不可及,人类从未涉足过如此幽暗的地方。
Pluto and its system of moons, the farthest world ever to be explored  by humankind.
这里就是冥王星和它的卫星系统,人类探索过的最为遥远的疆界。

Half a centry ago we began to the exploration  of all the planets.
半个世纪前我们开始了太阳系行星探索之旅,
Making ever more distant journeys, each new world from Mercury to Neptune, revealed its own starting complexity character and umimagined beauty.
我们的足迹越来越远,从水星到海王星,每颗行星都令人惊讶,都是我们想象力无法企及的美丽的新世界。

1979 Saturn 土星
1986 Uranus 天王星
1989 Neptune 海王星

As we now approach the pluto system, reaching farther again, this year we are about to complete the historic first era of planetary exploration.
现在我们即将拜访冥王星系统,一个更加遥远的世界,今年我们将为人类探索行星的历史树立一个新的里程碑。

2015 14 July Pluto 冥王星

Who knows what wanders await  us at these new horizons?
谁知道遥远的新视野里将会迎来什么样的奇迹?



1. 单词
(1)Mercury
英[ˈmɜ:kjəri] 美[ˈmɜ:rkjəri]
n.    [化] 汞,水银; [天] 水星; 温度表; 精神,元气;
(2)venus 
英 ['viːnəs]  美 ['viːnəs]          
n.金星;[罗神]维纳斯
(3)Mars 
英 [mɑːz]  美 [mɑːrz]          
n.火星;[罗神]战神
(4)Jupiter
[英]['dʒu:pɪtə(r)]  [美]['dʒupətɚ] 
木星
(5)Saturn
英[ˈsætɜ:n] 美[ˈsætɜ:rn]
n.    <天>土星; [罗史] 农神; 铅; 土星运载火箭(美国的);
(6)Uranus
英[ˈjʊərənəs] 美[ˈjʊrənəs]
n.   天王星; 乌拉诺斯神(希腊神话);
(7)Neptune
英[ˈneptju:n] 美[ˈnɛpˌtun, -ˌtjun]
n.    海王星; 海神尼普顿(罗马神话);
(8)Pluto
英 [ˈplu:təʊ] 美 [ˈplu:toʊ]
n.<天>冥王星; <希腊>冥府之神,冥王
(9)historic   
英[hɪˈstɒrɪk] 美[hɪˈstɔ:rɪk]
adj.    在历史上重要的,有历史影响的; 历史的,历史上的;
(10)era 
英[ˈɪərə] 美[ˈɪrə]
n.    纪元,年代; 历史时期,时代; 重大事件;
(11) planetary  
英[ˈplænətri] 美[ˈplænəteri]
adj.  行星的; 俗世的,现世的; 流浪的,飘忽不定的; [机] 行星齿轮的

2015年7月21日星期二

Tips_026:Thinkpad T440s Fn 键上光点的作用

以F1键为说明(其它F2-F12功能键同理),默认情况下按 F1键会显示当前焦点对象的帮助信息。
但 Thinkpad T440s的F1键还有静音切换的功能,这样就和帮助信息冲突了。
为了解决这个问题,在Fn 键上光点亮着的时候,按F1键显示帮助信息;而在Fn 键上光点不亮的时候,按F1键显示静音切换信息。
当是静音状态时,F1键上的光点是亮着的 。
那么,Fn键上的光点如何在亮与不亮之间切换呢?
答案是同时按下 Crtl + Esc + Fn 组合键。

在 Fn 键亮着的情况下,Fn + F7 是连接并切换到投影仪。

PDF 在 RHEL 下全屏投影:F5


Tips_025:Thinkpad T440s Ctrl 键“失灵” 问题

笔记本借给别人使用后,回来发现 Ctrl键突然不好使了,最普通的快捷键 Crtl + C 和 Ctrl + V 都不好使了。
后来发现是在BIOS中有个设置:Fn and Ctrl Key Swap [Enabled]。
Enabled时,Ctrl键的功能由Fn键代替;Disabled时,Ctrl键恢复本来的功能。
具体位置在:Config->Keyboard/Mouse-> Fn and Ctrl Key swap



这个设置的意义是因为原来键盘都是左边的Ctrl键在最边上,现在是Fn键,这样容易按错。
但我现在已经习惯了Fn在最左边,还是改成Disable吧。

2015年7月15日星期三

EAP_023:EAP 6 功能演示1:安装、启动、部署应用

环境:JBoss EAP 6.4

1. 安装与启动
(1)unzip jboss-eap-6.4.0.zip
(2)cd jboss-eap-6.4/bin
(3)./standalone.sh
(4)http://localhost:9990/,访问出错,提示创建用户
(5)./add-user.sh,做此步时不用停 EAP Server
(6)访问 http://localhost:9990/,点击Try again,输入管理员账户口令
(7)介绍 Management Console 基本功能:
         Runtime Tab -> Overview -> SERVER
                              -> Overview -> EXTENSIONS
                              -> System Status -> Platform -> JVM ...
         Configuration Tab -> Subsystems -> Core -> Logging ...
         Configuration Tab -> Subsystems -> Core -> Logging -> LOG CATEGORIES...
           新增 org.jboss.as.clustering,DEBUG log level。
                                      -> Subsystems -> Core -> Deployment Scanners ...
         Configuration Tab -> General Configuration -> Interfaces ...
         Configuration Tab -> General Configuration -> Socket Binding ...
(8)访问 http://[IP_ADDRESS]:9990/,访问出错,提示“无法显示此页”。
(9)./standalone.sh -Djboss.bind.address.management=[IP_ADDRESS] 或 ./standalone.sh -bmanagement [IP_ADDRESS]
(10)./standalone.sh -Djboss.bind.address=[IP_ADDRESS] 或 ./standalone.sh -b [IP_ADDRESS]
注意,jboss.bind.address 可以设置 0.0.0.0,表示机器上的所有 IP 地址都可以访问。
(11)停止 EAP  Server
(12)安装后目录介绍
(13)介绍配置文件:standalone.xml
           <interfaces> 定义 IP 地址。
           <socket-binding-group > 定义端口。
           <management> 决定哪些 interface 可以使用。

2. 概念理解:Extensions,Subsystems,Profiles

2.1 Extensions
(1)EAP 6 的所有功能特性(部署、Server配置、Java EE)都是在核心功能的基础上通过 Extensions 扩展实现的(以 module 的方式)。
(2)每个 extension 提供的具体功能特性在其对应的 subsystem 中配置。
(3)一个 extension 也可以定义多个 subsystem,但大多数 extension 只定义一个 subsystem。
(4)extension 是以 module 的方式发布的,extension 扩展了 EAP 6 的核心功能,比如:Java EE,clustering,transactions,security,logging 等等。
(5)可以根据需要开启或关闭这些 extension 功能,可以删除 extension 及其对应的subsystem,或者使用 CLI 将其 disable。
(6)extension 部署在 EAP 6 的 modules 目录下,并且有一个 jar 文件以及对应的 XML 配置文件:module.xml。

2.2 Subsystems
(1)subsystem 不可以具体配置 在 extension 中没有的定义。
(2)extension 只是说具有了某个功能特性,但这个功能到底如何使用还是要看该 extension 对应的subsystem中的具体配置。

2. 3 Profiles
(1)一个 profile 就是多个 subsystem 的集合。
(2)EAP 6 开箱提供4个 profile:default,ha,full,full-ha。
(3)可以定制自己的 profile。
(4)Standalone Mode 只能有一个 profile,所以无需命名,Domain Mode 可以有多个 profile。

2. 创建定制的 Standalone EAP
(1)mkdir myeap
(2)cp -r ./jboss-eap-6.4/standalone/configuration ./jboss-eap-6.4/standalone/deployments ./jboss-eap-6.4/standalone/lib myeap
(3)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -Djboss.socket.binding.port-offset=10000
注意,如果原来部署过应用,需要在standalone.xml中删除,并且在deployments目录下删除相关应用文件。
注意,只有端口不同的两个EAP 是共用一个配置文件,这样会导致互相覆盖,因此应该以 jboss.server.base.dir 来区分不同的 EAP Server。
(4)访问 http://localhost:19990/
         Runtime Tab -> System Status -> Platform -> Enviroment ...
         观察 jboss.home.dir = /Users/maping/Redhat/eap/demo/jboss-eap-6.4
                 jboss.server.base.dir = /Users/maping/Redhat/eap/demo/myeap
                 java.home = /Library/Java/JavaVirtualMachines/jdk1.7.0_80.jdk/Contents/Home/jre
                 jboss.server.log.dir = /Users/maping/Redhat/eap/demo/myeap/log
(5)访问 http://localhost:18080/
(6)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -b [IP_ADDRESS] -Djboss.socket.binding.port-offset=10000
(7)访问 http://[IP_ADDRESS]:18080/
(8)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -b [IP_ADDRESS] -bmanagement [IP_ADDRESS] -Djboss.socket.binding.port-offset=10000

3. 部署应用

3.1 通过控制台部署 example.war 
(1)访问 http://localhost:18080/example/

3.2. 设置 example 为默认的Web应用。
(1)cp standalone.xml standalone-root-web.xml
(2)修改 standalone-root-web.xml,注意修改前,要停止 EAP Server
(3)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -c standalone-root-web.xml -Djboss.socket.binding.port-offset=10000
(4)如果没有部署 example.war,现在通过控制台部署 example.war
(5)访问 http://localhost:18080/,注意这次不是访问 http://localhost:18080/example/
注意:一旦把 example 设置为 Root Web Application 后,就不能用原来的 context path 访问 example 了。

4. 按目录方式部署应用 version.war 目录,注意这是个目录
(1)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -Djboss.socket.binding.port-offset=10000
(2)cp -r version.war ../myeap/deployments/
(3)cp version.war.dodeploy ../myeap/deployments/
(4)访问 http://localhost:18080/version/
这里可以学习,如何获取并显示JBoss EAP Server 版本信息
(5)直接修改 index.jsp 文件,1.0 改为 2.0
(6)touch version.war.dodeploy
(7)http://localhost:18080/version/
(8)卸载 version.war,只需执行 rm version.war.deployed,过一会会自动生成一个文件:version.war.undeployed
(9)访问 http://localhost:18080/version/ 会报告404错误

5. 禁止自动部署 example.war 文件,注意这是个文件
(1)如果已经部署了 example.war,请先卸载。
(2)./standalone.sh -Djboss.server.base.dir=/Users/maping/Redhat/eap/demo/myeap -Djboss.socket.binding.port-offset=10000
(3)cp example.war ../myeap/deployments/,会自动部署成功,并且生成 example.war.deployed 文件
(4)http://localhost:18080/example/
(5)rm example.war,会自动卸载掉 example 应用,过一会会自动生成一个文件:example.war.undeployed
(6)rm example.war.undeployed
(7)touch example.war.skipdeploy
(8)cp example.war ../myeap/deployments/,这次不会自动部署
(9)mv example.war.skipdeploy example.war.dodeploy,再次部署

2015年7月14日星期二

SpeechEnglish_002: 2010年黄西在美国白宫记者年会上的演讲(摘录+整理)

Good evening, everyone.My name is Joe Wong.
各位晚上好,我是Joe Wong(黄西)。
But to most people, I am known as "Who?".
但是对很多人来说,听到我的名字,会问“谁”?
"Hu" is actually my mother's maiden name,  and the answer to my credit card security question.
Hu(同音“Who”)恰恰是我妈的娘家姓,也是我信用卡安全问题的答案。

But joking aside, I just want to reassure everybody that I am invited here tonight.
但是玩笑归玩笑,我想让大家放心我今晚的确是受到邀请来的。(这里是隐指Salah夫妇闯入白宫欢迎晚宴的新闻)

I grew up in China.
Who wouldn't?
我在中国长大。
谁不是呢?(这是用自己的自大讽刺美国人的自大)

As my childhood memories are totally ruined by my childhood. 
而我童年的所有记忆都被我的童年给毁了。
When I was in elementary school, as part of the curriculum, I have to worked at a rice paddy, right next to a quarry where they use explosives to break rocks.
读小学的时候,作为课程的一部分,我要去稻田里劳动,稻田的旁边是一个采石场,他们用炸药炸石头。
And that is where I learned that light travels faster than sound,  which is almost as slow as a flying rock.
也就是在那里,我知道了光的传播速度要比声音快,而声音的速度就和石头飞的速度差不多慢。

My dad was a grumpy guy, but occasionally he would tried to cheer me up with jokes.
我爸爸是个脾气很怪的人,但偶尔他也想用笑话来逗我玩儿。
But he doesn't do it right.
可是他又做不好。
When I was seven, one day he said to me, "Hi, son, why is tofu better than centralized socialist economy?" 
我七岁的时候,有一天他问我,“嘿,儿子,你说为什么豆腐比社会主义计划经济要好?”(风马牛不相及)
So, five minutes later, I said, "Why?"  He said, "Because I said so!"
我想了五分钟,然后问他“为什么呢?”,他说“因为我说好就是好!”
(笑点在于:豆腐,计划经济以及极端的父权。豆腐和经济放在一起本来就没有可比性,就好像这种“我说了算”的父权也根本不可理喻,让人又好气又好笑)

I came to the United States when I was 24, to study at Rice University in Texas. 
我24岁的时候来到美国,在Texas的Rice University求学。
That wasn't a joke,  until now.
这不是个笑话,不过现在是了。

And I was driving that a used car with a lot of bumper stickers that are impossible to peel off.
我当时开了辆二手车,保险杠上贴了好多贴纸(就类似我们的“熊出没注意”那种),贴的很牢,就根本不可能撕下来。
And one of them said, "If you don't speak English, go home!”.
其中一张写着“如果你不说英文,就滚回家去”。(这句话有歧视外来移民的意味)
And I didn't notice it for two years.
而我两年后才看到它。

And like many other immigrants, we wanted our son to become the president of this country.
和很多其他的移民一样,我们都希望自己的儿子能成为这个国家的总统。
And we try to make him bilingual, you know, Chinese at home and English in the public.
于是我们努力让他们说两种语言,在家说中文,在外说英文。
Which is really a tough to do, because many times  I had to say to him in public, "Hi, listen, if you don't speak English, go home!"
但操作起来其实挺困难,很多时候我不得不在公共场合对他说:“嘿,听着,如果你不说英文,就滚回家去。”(这里说明了该句子是一种教训儿子的口气)

And he was said to me, "Hi, Dad, Why do I have to learn two languages?"
然后他问我:“爸爸,为什么我要学两个语言呢?”
I said, "Son, once you become the president of the Unite States, you will have to sign legislative bills in English, and talk to debt collectors in Chinese!"
我就跟他说:“儿子,一旦有一天你成了美国总统,你就必须要用英文来签署法案,还要用中文跟讨债的对话。”(中国当前是美国的最大债主。)

When I graduated from Rice, I decided to stay in the Unite States, because in China I can't do the thing I do best here, being ethnic.
从Rice毕业后,我决定留在美国。因为回中国的话,我有一件事情完全没有办法做的比这里更好,那就是我散发出的异域风情(成为少数族裔)。

And in order for me to become a US citizen, I had to take those American history lessons, where they ask questions like: Who's Benjamin Franklin?
我为了成为一名美国公民,必须要上美国历史课,会被问到诸如“谁是本杰明 富兰克林?”
We were like, "Ahh.., the reason our convenient store gets robbed?"
我就想:“呃,莫非就是我们便利店遭到抢劫的原因?”(百元美钞上印着 本杰明 富兰克林的头像。)

What's the second Amendment?
“什么是第二修正案?”
We were like, "Ahh.., the reason our convenient store gets robbed?"
我就想:“呃,莫非就是我们便利店遭到抢劫的原因?”(第二修正案保障了人民的持枪权利)

What is Roe vs Wade?
“Roe vs. Wade是什么?”
We were like, "Ahh& , two ways of coming to the Unite States?"
“呃!两种来美国的途径?”(Roe vs.Wade是美最高法院关于堕胎的经典案例。他在这里则是说那些偷渡到美国的人,要不就是通过row a boat(划船,和人名Roe同音),要不就是靠游到河对岸(wade是跋涉的意思))
Later on, I read so much about American history that I started to harbor white guilt.
后来我读了很多的美国历史,以至于我都开始充满了白人罪恶感。(white guilt是指白人因为奴役黑人的历史而产生的负罪感。)

And in America, they say that all men are created equal, but after birth, it kind of depends on their parents' income for early education and healthcare.
在美国,大家都说人人生而平等。但是出生后,或多或少要取决于父母收入,才能提供你的早期教育和医疗保障。
I read in the Men's Health magazine that president Obama every week has two cardio days and 4 weight lifting days. You see, I don't have to exercise because I have health insurance.
我在男人健康杂志里看到,奥巴马总统每周有两次有氧锻炼,四次举重锻炼。你们看,我根本不需要锻炼,因为我有健康保险。(这里说医保体系给人慵懒意识)

I live in Massachusetts now, where we had universal healthcare then we elected Scott Brown. 
我现在住在麻省,我们有全面的医疗保险。然后我们选了Scott Brown当州长。
Talk about mixed messages!
哦,有歧义。
I think there was a movie about him. It's called "Kill Bill”.
我想有一部电影是关于他的,那就是《杀死比尔》(Kill Bill)。(bill在英文里有议案的意思,这里讽刺这名州长极力反对Obama的医保改革方案。)

I'm honored to eh.. meet vice president Joe Biden here tonight.
我很荣幸今晚能见到副总统Joe Biden。
em, I actually read autobiography of you, and today I see you. I think the book is much better. 
事实上,我曾经读过你的自传。今天见到你了,我觉得书(比本人)要好的多(然后镜头就给了副总统,副总统笑得很开心)。
They should have cast Brad Pitt, you know, or even Angelina Jolie.
他们应该请布拉德·皮特来演,或者是安吉丽娜·茱莉。

So, I, to be honest, was really honored to be here tonight, and I have prepared for months eh, for tonight show, and I showed the White House my jokes about President Obama, and that is why he decided not to come. 
坦率的说,我真的非常荣幸今天能应邀来到这里,为了今晚的节目我也准备了好几个月了。我还把关于奥巴马总统的笑话给白宫看,于是奥巴马总统就决定不出席今天的晚会了。
And he decide to talk about immigration reforms.
他还决定要讨论移民政策改革了。
Take that Stephen Colbert!
Stephen Colbert, 给他记上。(Steve是专攻政治人物的政治评论家、主持人,总统总是拿他没办法)

And President Obama has always been accused of being too soft, but he was conducting two wars, and they still gave him the Nobel Peace Prize. and he accepted it.
奥巴马总统经常被指责为过于软弱。但是他正指挥着两场战争,并且他们还是授予他诺贝尔和平奖。而他也竟然接受了。
You can't be more badass than that.
怎么可能有比这更操蛋的事情。
Well, actually, I'm thinking, the only way you can more badass than that, is if you take the Nobel Peace Prize money and give it to the military.
嗯,其实,我想,唯一可能比这个更操蛋的,就是你接受了诺贝尔和平奖的奖金,然后把它们送给军队。

We have many distinguished journalists here tonight, whom I consider as my peers. Because I used to write for the campus newspaper.
我们这里坐着很多杰出的新闻记者,我把你们看作是我的同行(也有贵族的意思)。因为我曾经也给学校的报纸写过文章。
I think journalism is the last refuge for puns.  Only on a newspaper can you see just like, "I was born in the year of the horse, and that's why I'm a neigh-sayer(nay-sayer)." 
我觉得新闻业是双关语最后的阵地了。因为只有在报纸上你才能看到类似于“我是属马的,所以你知道为什么我总是像马一样叫(唱反调)。”(美国人形容马叫的象声词是neigh,发音和nay一样,nay-sayer是总要唱反调的人)
My point exactly.
我表达的很准确。

And tonight is my first time on C-SPAN, which is a channel I obvious always watch when I couldn't stand the sensationalism and demagoguery of PBS and QVC. 
今晚是我第一次出现在C-span频道,通常当我无法忍受PBS和QVC的鼓吹与煽动时我就会看这个频道(PBS的节目以主观著称,QVC则是购物频道)。
If I can't still fall asleep after watching C-SPAN,  there are C-SPAN2 and C-SPAN3.
如果我看了C-span还是睡不着,那还有C-span 2套和3套(C-span频道是国会辩论转播频道)。
Thank you very much!
非常感谢!
So, I became a US citizen in 2008, eh, which I am really happy about. oh, Thank you very much!
2008年,我正式成为了美国公民,为此我感到很高兴。谢谢。
eh. America is number one!  That's true! cause we won the World Series every year!
嗯,美国是最牛的。这是真的,因为我们每年会赢世界职业棒球大赛(只有美国、加拿大的球队参加。)

After becoming a US citizen, and I immediately registered to vote for Obama and Biden. You are welcome.
成为美国公民之后,我立刻就登记了大选,并投给了奥巴马和拜登。(他回头看着拜登,对拜登说)不用谢。
You had me at "Guess we can".  That was their slogan.

你们的口号“猜想我们可以”征服了我。这是他们的口号。(此处故意将“Yes We Can”混淆成了“Guess We Can”。)
So, after getting Obama-Biden elected, I felt this power trip. and I started to think maybe I should run for president myself.
所以,当奥巴马成为总统的时候,我感觉到了一股力量,我自己在想,我是不是也应该去竞选总统!

Well, I have to take a step back and explain a little bit.
好吧,我多解释一下。
Because I had always been a morose and pessimistic guy.
我其实一直是一个忧郁并且悲观的人。
I feel that life is a kind of like pee into the snow in a dark winter night. You probably made a difference, but it's really hard to tell.
我觉得生活就像是在漆黑的冬夜里往雪地上撒尿。你可能确实做得不一样,但你真的很难说出来。

But now we have a president who is half black half white.
但是现在我们有了一位半黑半白的总统。
That just gives me a lot of hope, because I am half not black half not white. 
这给了我很大的希望。因为我一半不黑一半也不白。
Two negatives make a positive.
双重否定更加肯定。(Obama母亲是白人,父亲是黑人移民)

You may be saying, hi, what would be your campaign slogan?
你或许会问:“嘿,那你的竞选口号是什么?”
You see, I spent 10 years in the past decade.  Oh, you too? ok. 
你看,过去的10年里我度过了10年。什么,你也是?好吧。
So, I understand that American people are suffering.
所以我很理解美国人所经历的痛苦。
So, my campaign slogan will be, "Who cares?" (Hu Cares)

所以,我的竞选口号将会是“Hu Cares”(此处又是Who-Hu的谐音,Hu Cares:“胡关心你”Who Cares:“谁在乎你”。)

If elected, I will make same sex marriage not only legal, but required!
如果我当选,我不但会让同性恋结婚合法,还会让它必须。

That will give me the youth vote. 
这会帮助我赢得年轻人的选票。
You see I'm married now, but I used to be really scared about marriage.
你看我已经结婚了。但我过去对婚姻是非常恐惧的。
I was like, "Wow! 50% of all marriages end up lasting forever!"

我想:“哇,50%的婚姻结局是大家要在一起一辈子。”

And I will eliminate unemployment in this country by reducing the productivity of the American workforce. 
我也会通过降低美国工人的生产率来消灭这个国家的失业。
So, two people will have to do the work of one, just like the president and the vice president, or the Olson twins.
所以必须让两个人做一个人能做的事,就好像总统与副总统,又或者是Olsen姐妹(她们是双胞胎,一起演真人秀,一起设计服装)。

And despite heart diseases and cancer, most Americans die of natural causes.
除去心脏病和癌症的因素,大多数美国人是自然死亡的。
So if elected, I will find a cure for natural causes. 
所以如果我当选,我会找出一种治愈自然死亡的疗法。
You seem to like that one. 
你们看上去很喜欢这个。
But you won't be covered by health insurance, you know. because of pre-existing conditions.
但是你们将不可能享受医疗保险,因为先前条款。

And I have a quick solution for global warming.
我还有解决全球变暖的特效措施。
I will switch from Fahrenheit to Celsius. 
如果我当选了,我就把华氏改成摄氏。
It was 100 degrees, now it's 40!  You are very welcome!
这样以前的100度就会瞬间变成40度。

And I'm great with foreign policy because I am from China and I can see Russia from my backyard.
我也很擅长外交政策,因为我来自中国。我从我家后院就看得到俄罗斯!(这里也隐指Sarah Palin曾经说的“我从我家门廊就看得到俄罗斯”)。

I believe that, you know, unilateralism is too expensive, and open dialog is too slow.
我认为,单边主义代价太高,公开对话又效率太低。
So if elected, I will go with text messaging. 
如果我当选,我会选择“发短信”。
I'll text our allies just to say "hi",  and text our enemies when they are driving. 
我会发给我的盟友,仅仅打着招呼。我会在敌人开车的时侯给他们发短信。
"OMG you are building a nuclear weapon?  but you're doing it wrong, LOL!"
“天呐!听说你在造核武器?但是你们的做法是不对的!哈哈哈哈。OMG和LOL都是短信流行用语, OMG是Oh My God, LOL是Laugh Out Loud)。

I would like to thank Radio and TV Correspondents’ Association for giving such an incredible honor!
我要感谢美国记者协会今天对我的邀请和给予的殊荣!
This is the first time I wish my 3 year old son knew what I was doing.
这是我第一次希望我3岁的儿子能知道他的父亲在做什么。
Thank you very much, and have a good night.
谢谢大家,祝你们度过一个愉快的夜晚!

1. 单词
(1)elementary
英[ˌelɪˈmentri] 美[ˌɛləˈmɛntəri, -tri]
adj.  初等; 基本的; 初级的; [化] 元素的;
(2)curriculum
英[kəˈrɪkjələm] 美[kəˈrɪkjələm]
n.    全部课程,课程;
(3)paddy
英[ˈpædi] 美[ˈpædi]
n. 稻; 谷; <俚>爱尔兰人; 警察;
(4)quarry   
英[ˈkwɒri] 美[ˈkwɔ:ri]
n. 采石场; 猎物; 正方形,菱形; 来源;
vt. 挖出; 努力挖掘;
vi. 费力地找;
(5)explosive   
英[ɪkˈspləʊsɪv] 美[ɪkˈsploʊsɪv]
adj. 爆炸的; 易爆炸的; 突增的; 暴躁的;
n. 爆炸物,炸药; [语言学] 爆破音;
(6)grumpy   
英[ˈgrʌmpi] 美[ˈɡrʌmpi]
adj. 脾气暴躁的; 脾气坏的; 性情粗暴的; 性情乖戾的;
(7)bumper   
英[ˈbʌmpə(r)] 美[ˈbʌmpɚ]
n.  保险杠; 减震器; 干杯中的满杯; 〈口〉巨物;
adj.  特大的,丰盛的;
vt.  装满; 为…祝酒;
(8)sticker   
英[ˈstɪkə(r)] 美[ˈstɪkɚ]
n.  张贴物; 固执的人,坚持不懈的人; 难题,使人为难的东西; 踌躇不决的人;
vt. 给…贴上标签价;
adj. 汽车价目标签的; 汽车标签价的;
(9)immigrant   
英[ˈɪmɪgrənt] 美[ˈɪmɪɡrənt]
n.  移民,侨民; 从异地移入的动物[植物];
adj.  移民的,移来的; 侨民的;
(10)bilingual   
英[ˌbaɪˈlɪŋgwəl] 美[baɪˈlɪŋɡwəl]
adj.  双语的,两种语言的,能说两种语言的;
n.  能说两种语言的人;
(11)legislative   
英[ˈledʒɪslətɪv] 美[ˈledʒɪsleɪtɪv]
adj. 立法的(关于); 立法决定的; 有权立法的,用以立法的; 立法机构的;
n.  立法机关; 立法权;
(12)ethnic   
英[ˈeθnɪk] 美[ˈɛθnɪk]
adj.  种族的,部落的; 某文化群体的;
n.  少数民族的成员;
(13)amendment
英[əˈmendmənt] 美[əˈmɛndmənt]
n.  修正案; 修改,修订;
(14)harbor   
英['hɑ:bə] 美[ˈhɑrbɚ]
n. 海港; 海湾; 避难所; 躲藏处;
vt.& vi. 心怀; 庇护; 避入安全地; 入港停泊(船);
(15)cardio   
英['kɑ:dɪəʊ] 美['kɑ:rdɪoʊ]
n. 有氧运动;
pref. 表示心
(16)autobiography
英[ˌɔ:təbaɪˈɒgrəfi] 美[ˌɔ:təbaɪˈɑ:grəfi]
n.    自传; 自传文学;

(17)cast
英[kɑ:st] 美[kæst]
vt. 铸造; 投射; 投掷; 脱落,脱皮;
n. 铸型; 演员表; 轻微的斜视; 投,掷骰;
vi. 掷,投; 计算,加;
(18)conduct   
英[kənˈdʌkt] 美[kənˈdʌkt]
vt.& vi. 传导; 引导; 带领; 控制;
vt.  实施; 执行; 组织; 安排;
adj. 指挥,带领,护送;
(19)badass
英[ˈbædæs] 美[ˈbædˌæs]
n.    寻衅闹事的人; 不合作的人; 惯犯; 劣性牲口;
adj.    无法无天的; 坏的; 不值钱的; 不好对付的;
(20)refuge   
英[ˈrefju:dʒ] 美[ˈrɛfjudʒ]
n.    避难; 避难所; 庇护者; [医] 救急疗法;
vt.    给予…庇护; 接纳…避难;
vi.    避难; 躲避;
(21)pun
英[pʌn] 美[pʌn]
n.    双关语; 俏皮话;
vi.    说双关语;
vt.    捣结实;
(22)naysayer   
英['neɪˌseɪə] 美['neɪˌseɪə]
[释义]    反对者,否认者,老爱唱反调的人;
(23)sensationalism
英[senˈseɪʃənəlɪzəm] 美[sɛnˈseʃənəˌlɪzəm]
n.    煽情主义; <贬>(指行文或报道)耸人听闻,哗众取宠;
(24)demagoguery
英['deməˌgɔ:gərɪ] 美[ˈdɛməˌɡɔɡəri, -ˌɡɑɡə-]
n.    群众煽动,散布谣言,煽动行为;
(25)slogan   
英[ˈsləʊgən] 美[ˈsloʊgən]
n.    标语,口号; 呐喊声; 短语(商业广告上用的);
(26)morose   
英[məˈrəʊs] 美[məˈroʊs]
adj. 闷闷不乐的,阴郁的;
(27)pessimistic   
英[ˌpesɪˈmɪstɪk] 美[ˌpesɪˈmɪstɪk]
adj.  悲观主义的; 悲观的,厌世的;
(28)pee
英[pi:] 美[pi]
vi.  小便,撒尿;
n.   小便,尿;
(29)Fahrenheit   
英[ˈfærənhaɪt] 美[ˈfærənˌhaɪt]
adj. 华氏的; 华氏温度计的;
n.  飞轮海;
(30)Celsius   
英[ˈselsiəs] 美[ˈsɛlsiəs]
n.  摄氏;
adj. 摄氏的;

2.短语
(1)centralized socialist economy 集体制社会主义经济
(2)peel off 剥落; 去皮,离群
(3)debt collector 收债人
(4)universal healthcare 全民医疗

参考文献:
1. http://www.en8848.com.cn/tingli/speech/famous-yj/187679.html
2. http://wenku.baidu.com/link?url=W9PZMJMUjMzRJxCB2omRtlUk6fKPETDJTg-2vjW67SynsEQreshmZRwp1OIk7D_SuWF93sSwykJuo57jleuds644I3-94SLxYYxeh-Fnxu7

2015年7月13日星期一

Fuse_019:基础入门之八:fabric profile

环境:JBoss Fuse 6.2.0 + Maven 3.2.2

本实验跟上一个实验有关。



1. 学习重点
(1)创建 fabric
(2)创建 container
(3)创建 profile

2. 创建 fabric
简单的创建命令:fabric:create --wait-for-provisioning
创建 fabric 时,只有一个 fabric server,其中安装了 registry service,它也是 fabric 中的第一个 container,默认名称 root。其它 container 是 root container 的子 container。
如果想修改第一个 container 的名字,修改 InstallDir/etc/system.properties 文件内容。
对于 fabric 中的第一个 container,不必修改名字;但是如果想加入其它 fabric 中的 root container,就要修改相关信息,防止冲突。
所有的 containers 存储在 InstallDir/instances 目录下。

复杂的创建命令:
fabric:create --new-user AdminUser
--new-user-password AdminPass
--new-user-role Administrator
--resolver manualip
--manual-ip 127.0.0.1
--zookeeper-password ZooPass
--wait-for-provisioning

--new-user, --new-user-password, 和 --new-user-role 用于指定新管理员。
--zookeeper-password  用于连接由 ZooKeeper 实现的 Fabric registry service。
所有的Fabric registry service 节点位于 InstallDir/fabric 目录下。
大多数情况下,访问 fabric registry service 时,不需要输入 Zookeeper 口令,因为它保存在当前 session 中。但是当加入一个 container 到一个 fabric 中时,需要提供 Zookeeper 口令。
建议生产环境中,为 fabric server 配置静态 IP 地址,并使用 --resolver 指定端口,使用 --manual-ip 指定 IP。

3. 创建 child container
(1)简单的创建命令:fabric:container-create-child root child 2
输出如下:
Creating new instance on SSH port 8102 and RMI ports 1100/44445 at: /Users/maping/Redhat/fuse/jboss-fuse-6.2.0.redhat-133/instances/child
Creating new instance on SSH port 8103 and RMI ports 1101/44446 at: /Users/maping/Redhat/fuse/jboss-fuse-6.2.0.redhat-133/instances/child2
The following containers have been created successfully:
    Container: child2.
    Container: child.

这里假定你的 root container 名字就是 root。
子 containers 也存储在 InstallDir/instances 目录下。
可以看出,创建成功了两个子 container,每个 container 都使用了默认的 default profile。

完整命令语法:
fabric:container-create-child [--help] [--ensemble-server] [--profile profileID] [--version version] [--jvm-opts jvmOpts] [--resolver policy] {parent} {name} [number]

// TODO 如何在创建时指定子 container 的名字?

(2)查看 container 列表:fabric:container-list
[id]      [version]  [type]  [connected]  [profiles]              [provision status]
root*     1.0        karaf   yes          fabric                  success          
                                          fabric-ensemble-0000-1                   
                                          jboss-fuse-full                          
  child   1.0        karaf   yes          default                 success          
  child2  1.0        karaf   yes          default                 success     

// TODO 如何修改 container 名称?

(3)停止 container
每个子 containers 运行在它自己的 JVM 中,因此即使 root container 被停掉,子 container 还会保持运行。因此要停止整个 fabric,要先停止子 container,然后再执行 shutdown 命令。
fabric:container-stop child
fabric:container-stop child2
shutdown
而启动子 container 时,要先启动 root container,再启动子 container。
startup
fabric:container-start child
fabric:container-start child2

4. 创建 profile
一个 profile 是一个 fabric 中的基本部署单元。可以发布一个或多个 profiles 到一个 container 中。

fabric profile 可以包含如下信息:
  • features repositories的URL
  • 需要安装的 features 列表
  • 需要安装的 bundles 列表(打成 JAR 包,可以是 OSGi bundle/Fuse Application Bundles/WAR)
  • OSGi Config Admin service 的配置
  • 影响 Apache Karaf 的 Java 环境变量(etc/config.properties)
  • 影响安装后的 bundles 的 Java 环境变量(etc/system.properties)
(1)创建 base profile
fabric:profile-create --parent feature-cxf gs-cxf-base
profile 支持继承,比如当部署到集群中多个 server 时,除了 IP 地址和端口之外,其它部署内容都一样。这时,可以先创建一个 base profile。
每个 server 可以继承该 base profile,然后加上自己的特别的设置。

(2)为 gs-cxf-base 添加 get-started features repository
profile-edit -r mvn:org.fusesource.example/get-started/1.0-SNAPSHOT/xml/features gs-cxf-base

(3)为 gs-cxf-base 添加 cxf-http-jetty feature 和 get-started-cxf feature
profile-edit --feature cxf-http-jetty gs-cxf-base
profile-edit --feature get-started-cxf gs-cxf-base

(4)创建 child profile gs-cxf-01 和 gs-cxf-02
profile-create --parent gs-cxf-base gs-cxf-01
profile-create --parent gs-cxf-base gs-cxf-02
 (5)修改 profile gs-cxf-01 和 gs-cxf-02 的属性
profile-edit -p org.fusesource.example.get.started/portNumber=8185 gs-cxf-01
profile-edit -p org.fusesource.example.get.started/portNumber=8186 gs-cxf-02

5. 发布 profile
(1)发布 gs-cxf-01 profile 到 child  container:fabric:container-change-profile child gs-cxf-01
(2)发布 gs-cxf-02 profile 到 child2  container:fabric:container-change-profile child2 gs-cxf-02
(3)启动子 container:container-start child
(4)查看 container:watch container-list
(5)连接到子 container:container-connect child
(6)列出 CXF  Endpoint:cxf:list-endpoints
Name                      State      Address                                                      BusID                                  
[FabricResource         ] [Started ] [/fabric8                                                  ] [io.fabric8.fabric-rest-cxf140787777   ]
[HelloWorldImplPort     ] [Started ] [http://0.0.0.0:8185/cxf/HelloWorld                        ] [org.fusesource.example.cxf-basic-cxf531356605]

6. 修改 profile 
默认情况下,修改一个已经发布到 container 的 profile 会立即生效,这是因为 container 中的 fabric agent 会实时监控 container 的变化,然后把变化告知 fabric server。
实际情况下,修改立即生效可能不是一个好主意,更多是灰度升级,比如先升级一个 container 看看有没有问题,没有问题再升级其它 container。
为了保证原子级事务提交所有的改动,fabric 提供了 profile 版本化功能。
比如一开始,container 指向的是某个 profile 的 1.0 版本。
接着创建了该 profile 的 2.0 版本,这个新版本在应用到 container 之前,其中的改动对 container 没有生效。
最后你可以升级 container 使用新版本的 profile。

(1)创建 profile 新版本
fabric:version-create
该命令会把所有的 profile 都拷贝一份作为升级的版本。
也就是说,所有的 profile 必须是同一个版本,不能有的 profile 使用 1.0 版本,有的 profile 使用 1.1 版本。

(2)查看 profile 版本
fabric:version-list

(3)修改 profile gs-cxf-01 1.1 版本,把端口改为 8087:
fabric:profile-edit -p org.fusesource.example.get.started/portNumber=8187 gs-cxf-01 1.1
注意这里指定了 profile 以及版本号,说明改的是哪个 profile 的哪个版本。

(4)升级 container child2 到版本 1.1:fabric:container-upgrade 1.1 child2

(5)回滚 container child2 到版本 1.0:fabric:container-rollback 1.0 child2

参考文献:
1. Red_Hat_JBoss_Fuse-6.2-Getting_Started-en-US.pdf

Fuse_018:基础入门之七:fabric 及相关概念

环境:JBoss Fuse 6.2.0 + Maven 3.2.2


1. Fabric
一个 fabric 是 container 的集合,这些 container 共享一个 fabric registry。 fabric registry 由多个彼此之间复制关系的数据库组成,其中保存了所有与 container 相关的信息。fabric 用来管理分布式网络环境下的 container,这些 container 可能部署在多台机器上。

2. Fabric Ensemble
一个 Fabric Ensemble 是一组 Fabric Server 的集合,用来维持 fabric registry 的状态。Fabric Ensemble 由多个彼此之间复制关系的数据库实现,并且使用投票选举机制保证 fabric registry 中的数据在所有 container 上保持一致。为防止“网裂”,Fabric Ensemble中的Fabric Server 数量必须是单数。在生产环境中,一般至少有3~5个 Fabric Server,并且这些 Fabric Server 要在不同的机器上,用于容错。

3. Fabric Server
Fabric Server 是组成 fabric 的基石,用来保持 fabric registry 的副本。每个 Fabric Server 中都安装了一个 registry service。registry service 基于 Apache ZooKeeper,维护一个 registry 数据库副本,并且提供了一个 ZooKeeper server,fabric agent 将和 ZooKeeper 连接,用来获取 registry data。

4. Fabric Container
一个 Fabric Container 知道所有 Fabric Server 的位置,它可以从 Fabric Ensemble 中的任意一个 Fabric Server 获取 registry 数据。每个 Fabric Container 都安装了一个 Fabric Agent。Fabric Agent 实时监控 fabric registry,当 registry 中有变化时,Fabric Agent 将立即更新 container,与 registry 设置保持一致。

5. Profile
一个 Fabric profile 是一个抽象的部署单元,包括发布应用到一个 Fabric Container 需要的所有数据。Profile 只适用于 fabric 上下文。Features 或 bundles 适合直接发布到 Fabric Container 中,但其生命周期较短。

说明:container 中的 Fabric Agent 完全改变了部署模型,只能使用 profile 作为部署单元。虽然,仍可以部署 bundle 或 feature,但这些部署不是永久性的。只要重新启动 container,Fabric Agent 将会用原来的 profile 配置替代已有的部署内容。

参考文献:
1. Red_Hat_JBoss_Fuse-6.2-Getting_Started-en-US.pdf

Fuse_017:基础入门之六:故障诊断

环境:JBoss Fuse 6.2.0 + Maven 3.2.2

本实验跟上一个实验有关。

1. 使用 osgi:list 查看 bundle 服务
[ 232] [Active     ] [            ] [Started] [   60]
    Apache ServiceMix :: CXF Code First OSGi Bundle (1.0.0.SNAPSHOT)

(1)第1列是 bundle id
(2)第2列是 bundle 的状态(Installed、Resolved、Active),只有安装并启动成功的bundle的状态才是Active。
(3)第3列 如果bundle包含blueprint xml,此列表示 Blueprint Context 是否 Created 成功。
(4)第4列 如果bundle包含spirng xml,此列表示 Spring Context 是否 Started 成功。

2. 查看日志
(1)log:display
(2)log:tail
(3)log:set DEBUG

3. 使用 dev:watch 重新发布 bundle 服务
(1)dev:watch <id>
(2)mvn clean install
此时,不用执行 osgi:install,会发现 bundle 已经被自动部署更新了。

参考文献:
1. Red_Hat_JBoss_Fuse-6.2-Getting_Started-en-US.pdf

Fuse_016:基础入门之五:使用OSGi Config Admin service配置应用

环境:JBoss Fuse 6.2.0 + Maven 3.2.2

本实验跟上一个实验有关。

1. 学习重点
(1)动态配置服务的IP地址和端口

2. 修改 cxf-basic/src/main/resources/OSGI-INF/blueprint/blueprint.xml
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws"
           xmlns:cxf="http://cxf.apache.org/blueprint/core"
           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
           xsi:schemaLocation="
      http://cxf.apache.org/blueprint/core http://cxf.apache.org/schemas/blueprint/core.xsd
      http://cxf.apache.org/blueprint/jaxws http://cxf.apache.org/schemas/blueprint/jaxws.xsd">

    <cxf:bus>
        <!--
           In this example, we're enabling the logging feature.  This will ensure that both the inbound and outbound
           XML message are being logged for every web service invocation.
        -->
        <cxf:features>
            <cxf:logging/>
        </cxf:features>
    </cxf:bus>

    <!-- osgi blueprint property placeholder -->
    <cm:property-placeholder id="placeholder"
                             persistent-id="org.fusesource.example.get.started">
        <cm:default-properties>
            <cm:property name="portNumber" value="8181"/>
        </cm:default-properties>
    </cm:property-placeholder>

    <jaxws:endpoint id="helloWorld"
                    implementor="org.fusesource.example.HelloWorldImpl"
                    address="http://0.0.0.0:${portNumber}/cxf/HelloWorld">
    </jaxws:endpoint>

</blueprint>

3. 创建文件 etc/org.fusesource.example.get.started.cfg,内容如下:
portNumber=8182

4.  构建、部署、测试、卸载
(1)在 cxf-basic 目录下执行 mvn clean install
(2)如果原来安装了 get-started-basic feature,要将其卸载:features:uninstall get-started-basic
(3)features:install get-started-cxf
(4)cxf:list-endpoints
应该能看到 [HelloWorldImplPort     ] [Started ] [http://0.0.0.0:8182/cxf/HelloWorld                        ]
(5)修改  cxf-basic/src/test/java/org/fusesource/example/SoapTest.java
URLConnection connection = new URL("http://localhost:8182/cxf/HelloWorld").openConnection();
(6)在 cxf-basic 目录下执行 mvn -Ptest
(7)features:uninstall get-started-cxf

参考文献:
1. Red_Hat_JBoss_Fuse-6.2-Getting_Started-en-US.pdf

Fuse_015:基础入门之四:按 feature 部署

环境:JBoss Fuse 6.2.0 + Maven 3.2.2

本实验跟上一个实验有关。

1. 学习重点
(1)如何按 feature 部署

2. 使用 Maven 构建
(1)cd get-started
(2)mkdir -p features/src/main/resources/
(3)cd features/src/main/resources/
(4)在 features/src/main/resources/ 目录下创建 get-started.xml
<?xml version="1.0" encoding="UTF-8"?>
<features name="get-started">
    <feature name="get-started-basic">
        <bundle>mvn:org.fusesource.example/cxf-basic/1.0-SNAPSHOT</bundle>
        <bundle>mvn:org.fusesource.example/camel-basic/1.0-SNAPSHOT</bundle>
    </feature>
    <feature name="get-started-cxf">
        <bundle>mvn:org.fusesource.example/cxf-basic/1.0-SNAPSHOT</bundle>
    </feature>
</features>
(5)cd features
(6)在 features 目录下创建 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="
      http://maven.apache.org/POM/4.0.0
        http://maven.apache.org/xsd/maven-4.0.0.xsd">
   
    <modelVersion>4.0.0</modelVersion>
   
    <groupId>org.fusesource.example</groupId>
    <artifactId>get-started</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
   
    <name>Getting Started Feature Repository</name>

    <build>
        <plugins>
            <!-- Attach the generated features file as an artifact,
            and publish to the maven repository -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>1.5</version>
                <executions>
                    <execution>
                        <id>attach-artifacts</id>
                        <phase>package</phase>
                        <goals>
                            <goal>attach-artifact</goal>
                        </goals>
                        <configuration>
                            <artifacts>
                                <artifact>
                                    <file>target/classes/get-started.xml</file>
                                    <type>xml</type>
                                    <classifier>features</classifier>
                                </artifact>
                            </artifacts>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

(7)在 features 目录下执行 mvn clean install

3. 部署 feature
(1)如果 cxf-basic 和 camel-basic 已经作为 bundles 发布了,需要先将它们卸载。
(2)features:addurl mvn:org.fusesource.example/get-started/1.0-SNAPSHOT/xml/features
(3)features:list
(4)features:refreshurl
(5)features:install get-started-basic
(6)在 cxf-basic 目录下执行 mvn -Ptest
(7)features:uninstall get-started-basic

参考文献:
1. Red_Hat_JBoss_Fuse-6.2-Getting_Started-en-US.pdf

Fuse_014:基础入门之三:aggregate POM

环境:JBoss Fuse 6.2.0 + Maven 3.2.2

本实验跟上一个实验有关。

1. 学习重点
(1)定义 aggregate POM

2. 在 get-started目录下,新增文件:pom.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <groupId>org.fusesource.example</groupId>
    <artifactId>get-started</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modelVersion>4.0.0</modelVersion>
    <name>Getting Started :: Aggregate POM</name>
    <description>Getting Started example</description>
    <modules>
        <module>cxf-basic</module>
        <module>camel-basic</module>
    </modules>
</project>

3. 使用 Maven 构建
(1)cd get-started
(2)mvn clean install

好,接下來就可以把这两个bundle 作为一个 feature 发布了。

参考文献:
1. Red_Hat_JBoss_Fuse-6.2-Getting_Started-en-US.pdf

Fuse_013:基础入门之二:camel-basic

环境:JBoss Fuse 6.2.0 + Maven 3.2.2

本实验跟上一个实验有关。

1. 学习重点
(1)从零开始构建 camel route。

2. 修改 settings.xml,内容如下:
参见《Fuse_012:基础入门之一:cxf-basic 》。

3. 使用 Maven 构建
(1)mvn archetype:generate -DarchetypeGroupId=io.fabric8.archetypes -DarchetypeArtifactId=karaf-camel-cbr-archetype -DarchetypeVersion=1.2.0.redhat-133 -DgroupId=org.fusesource.example -DartifactId=camel-basic -Dversion=1.0-SNAPSHOT -Dfabric8-profile=camel-basic-profile
(2)修改 camel-basic/pom.xml,增加 camel-jetty artifact
<dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-jetty</artifactId>
</dependency>
(3)修改 camel-basic/src/main/resources/OSGI-INF/blueprint/cbr.xml
<?xml version="1.0"?>
<!-- JBoss, Home of Professional Open Source Copyright 2014, Red Hat, Inc.
    and/or its affiliates, and individual contributors by the @authors tag. See
    the copyright.txt in the distribution for a full listing of individual contributors.
    Licensed under the Apache License, Version 2.0 (the "License"); you may not
    use this file except in compliance with the License. You may obtain a copy
    of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
    by applicable law or agreed to in writing, software distributed under the
    License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
    OF ANY KIND, either express or implied. See the License for the specific
    language governing permissions and limitations under the License. -->
<!-- This is the OSGi Blueprint XML file defining the Camel context and routes.
    Because the file is in the OSGI-INF/blueprint directory inside our JAR, it
    will be automatically activated as soon as the bundle is installed. The root
    element for any OSGi Blueprint file is 'blueprint' - you also see the namespace
    definitions for both the Blueprint and the Camel namespaces. -->
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
             http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
             http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">

    <!-- The namespace for the camelContext element in Blueprint is 'http://camel.apache.org/schema/blueprint'.
        Additionally, we can also define namespace prefixes we want to use them in
        the XPath expressions in our CBR. While it is not required to assign id's
        to the <camelContext/> and <route/> elements, it is a good idea to set those
        for runtime management purposes (logging, JMX MBeans, ...) -->
    <camelContext id="blueprintContext" trace="false"
        xmlns="http://camel.apache.org/schema/blueprint">
        <route id="httpBridge">
            <from uri="jetty:http://0.0.0.0:8282/cxf/HelloWorld?matchOnUriPrefix=true" />
            <delay>
                <constant>5000 </constant>
            </delay>
            <to    uri="jetty:http://localhost:8181/cxf/HelloWorld?bridgeEndpoint=true&throwExceptionOnFailure=false" />
        </route>
    </camelContext>

</blueprint>

(4)mvn clean install

4. 修改 cxf-basic/src/test/java/org/fusesource/example/SoapTest.java 
把8181端口改成8282端口,修改如下:
URLConnection connection = new URL("http://localhost:8282/cxf/HelloWorld").openConnection();
 
5. 部署 、卸载
(1)./fuse
(2)osgi:install -s mvn:org.fusesource.example/camel-basic/1.0-SNAPSHOT
(3)osgi:list
(4)cd ../cxf-basic
(5)mvn -Ptest
(6)http://localhost:8181/cxf
(7)http://localhost:8181/cxf/HelloWorld?wsdl
(8)osgi:uninstall <id>
 
参考文献:
1. Red_Hat_JBoss_Fuse-6.2-Getting_Started-en-US.pdf

Fuse_012:基础入门之一:cxf-basic

环境:JBoss Fuse 6.2.0 + Maven 3.2.2

1. 学习重点
(1)从零开始构建 cxf JAX-WS Web Service。

2. 修改 settings.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd" xmlns="http://maven.apache.org/SETTINGS/1.1.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   
    <profiles>
       
        <profile>
            <id>fusesource-repository</id>
            <repositories>
                <repository>
                    <id>fusesource</id>
                    <url>http://repo.fusesource.com/nexus/content/groups/public/</url>                               
                    <releases>
                        <enabled>true</enabled>
                    </releases>                    
                    <snapshots>
                        <enabled>false</enabled>
                    </snapshots>
                </repository>
                <repository>
                    <id>apache-public</id>
                    <url>https://repository.apache.org/content/groups/public/</url>
                    <releases>
                        <enabled>true</enabled>
                    </releases>                    
                    <snapshots>
                        <enabled>false</enabled>
                    </snapshots>                   
                </repository>
            </repositories>
            <pluginRepositories>
                <pluginRepository>
                    <releases />
                    <snapshots>
                        <enabled>false</enabled>
                    </snapshots>
                    <id>fusesource-plugin-repository</id>
                    <url>http://repo.fusesource.com/nexus/content/groups/public/</url>
                </pluginRepository>
            </pluginRepositories>
        </profile>      
       
    </profiles>
   
    <activeProfiles>
        <activeProfile>fusesource-repository</activeProfile>      
    </activeProfiles>
   
</settings>

注意,必须增加 pluginRepositories 部分,并指向 http://repo.fusesource.com/nexus/content/groups/public/,否则运行 mvn clean install 时会报告如下错误:
(1)[ERROR] Failed to execute goal org.apache.cxf:cxf-java2ws-plugin:3.0.4.redhat-620133:java2ws (process-classes) on project cxf-basic: Execution process-classes of goal org.apache.cxf:cxf-java2ws-plugin:3.0.4.redhat-620133:java2ws failed: A required class was missing while executing org.apache.cxf:cxf-java2ws-plugin:3.0.4.redhat-620133:java2ws: org/apache/cxf/helpers/CastUtils
(2)[ERROR] Plugin org.apache.cxf:cxf-java2ws-plugin:3.0.4.redhat-620133 or one of its dependencies could not be resolved: Failure to find org.apache.cxf:cxf-java2ws-plugin:jar:3.0.4.redhat-620133 in http://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced -> [Help 1]

错误(1)是由错误(2)引起的,根本原因是 org.apache.cxf:cxf-java2ws-plugin:jar:3.0.4.redhat-620133 无法下载,该文件实际在 http://repo.fusesource.com/nexus/content/groups/public/org/apache/cxf/cxf-java2ws-plugin/ 中,不在  http://repo.maven.apache.org/maven2 中,因此下载不了。增加 pluginRepositories 部分,并指向 http://repo.fusesource.com/nexus/content/groups/public/ 后,问题消失。

3. 使用 Maven 构建
(1)mvn archetype:generate -DarchetypeGroupId=io.fabric8.archetypes -DarchetypeArtifactId=karaf-soap-archetype -DarchetypeVersion=1.2.0.redhat-133 -DgroupId=org.fusesource.example -DartifactId=cxf-basic -Dversion=1.0-SNAPSHOT -Dfabric8-profile=cxf-basic-profile
(2)修改 cxf-basic/src/test/resources/request.xml,修改后内容如下:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <ns2:sayHi xmlns:ns2="http://example.fusesource.org/">      
            <arg0>John Doe</arg0>
        </ns2:sayHi>
    </soap:Body>
</soap:Envelope>
注意,必须修改,否则 mvn -Ptest 会报如下错误:
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.293 sec <<< FAILURE! - in org.fusesource.example.SoapTest
sendRequest(org.fusesource.example.SoapTest)  Time elapsed: 0.167 sec  <<< ERROR!
java.io.IOException: Server returned HTTP response code: 500 for URL: http://localhost:8181/cxf/HelloWorld
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1627)
    at org.fusesource.example.SoapTest.sendRequest(SoapTest.java:83)

(3)cd cxf-basic
(4)mvn clean install

4. 部署 、卸载
(1)./fuse
(2)osgi:install -s mvn:org.fusesource.example/cxf-basic/1.0-SNAPSHOT
(3)osgi:list
(4)mvn -Ptest
(5)http://localhost:8181/cxf
(6)http://localhost:8181/cxf/HelloWorld?wsdl
(7)osgi:uninstall <id>
 
参考文献:
1. Red_Hat_JBoss_Fuse-6.2-Getting_Started-en-US.pdf

2015年7月11日星期六

Fuse_011:Fuse 快速上手之十一:camel-amq

环境:JBoss Fuse 6.2.0

1. 学习重点
(1)学习使用 camel-amq 组件连接本地的 A-MQ broker。
(2)在 Camel route 中使用 JMS。

2. camel-context.xml 
(1)设计图

(2)源码

<?xml version="1.0" encoding="UTF-8"?>
<!--
    JBoss, Home of Professional Open Source
    Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual
    contributors by the @authors tag. See the copyright.txt in the
    distribution for a full listing of individual contributors.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<!--
   This is the OSGi Blueprint XML file defining the Camel context and routes.  Because the file is in the
   OSGI-INF/blueprint directory inside our JAR, it will be automatically activated as soon as the bundle is installed.

   The root element for any OSGi Blueprint file is 'blueprint' - you also see the namespace definitions for both the Blueprint
   and the Camel namespaces.
-->
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
             http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
             http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">

    <!--
      The namespace for the camelContext element in Blueprint is 'http://camel.apache.org/schema/blueprint'. Additionally,
      we can also define namespace prefixes we want to use them in the XPath expressions in our CBR.

      While it is not required to assign id's to the <camelContext/> and <route/> elements, it is a good idea
      to set those for runtime management purposes (logging, JMX MBeans, ...)
    -->
    <camelContext id="jms-example-context" xmlns="http://camel.apache.org/schema/blueprint" xmlns:order="http://fabric8.com/examples/order/v7">
  <route id="file-to-jms-route">
    <from uri="file:work/jms/input"/>
    <log message="Receiving order ${file:name}"/>
    <to uri="amq:incomingOrders"/>
  </route>
  <route id="jms-cbr-route">
    <from uri="amq:incomingOrders"/>
    <choice>
      <when>
        <xpath>/order:order/order:customer/order:country = 'UK'</xpath>
        <log message="Sending order ${file:name} to the UK"/>
        <to uri="file:work/jms/output/uk"/>
        <log message="Done processing ${file:name}"/>
      </when>
      <when>
        <xpath>/order:order/order:customer/order:country = 'US'</xpath>
        <log message="Sending order ${file:name} to the US"/>
        <to uri="file:work/jms/output/us"/>
      </when>
      <otherwise>
        <log message="Sending order ${file:name} to another country"/>
        <to uri="file:work/jms/output/others"/>
      </otherwise>
    </choice>
  </route>
</camelContext>

</blueprint>

3. 编译、部署到 fabric、卸载
(1)cd /Users/maping/Redhat/fuse/jboss-fuse-6.2.0.redhat-133/quickstarts/camel-amq
(2)mvn clean install
(3)./fuse
(4)fabric:create --wait-for-provisioning
(5)mvn fabric8:deploy
(6)mq-create --kind StandAlone --group mygroup mybroker
(7)container-create-child --profile mq-broker-mygroup.mybroker root mybroker
(8)fabric:container-create-child --profile quickstarts-camel.amq --profile mq-client-mygroup root mychild
(9)fabric:container-list
(10)cp /Users/maping/Redhat/fuse/jboss-fuse-6.2.0.redhat-133/quickstarts/camel-amq/src/main/fabric8/data/* /Users/maping/Redhat/fuse/jboss-fuse-6.2.0.redhat-133/instances/mychild/work/jms/input
(11)cd /Users/maping/Redhat/fuse/jboss-fuse-6.2.0.redhat-133/instances/mychild/work/jms/output
(12)fabric:container-connect mychild
(13)log:display | grep order1
(14)与 child container 断开连接:control + D
(15)fabric:container-stop mychild
(16)fabric:container-delete mychild
(17)fabric:container-stop mybroker
(18)fabric:container-delete mybroker
 
4.  mvn fabric8:deploy 执行失败问题
执行 mvn fabric8:deploy 时,会抛出如下异常:
[ERROR] Failed to execute goal io.fabric8:fabric8-maven-plugin:1.2.0.redhat-133:deploy (default-cli) on project beginner-camel-log: Execution default-cli of goal io.fabric8:fabric8-maven-plugin:1.2.0.redhat-133:deploy failed: An API incompatibility was encountered while executing io.fabric8:fabric8-maven-plugin:1.2.0.redhat-133:deploy: java.lang.NoSuchMethodError: org.eclipse.aether.spi.connector.Transfer.setState(Lorg/eclipse/aether/spi/connector/Transfer$State;)Lorg/eclipse/aether/spi/connector/Transfer;
 经查,这是因为 fabric8:deploy 不支持 maven 3.2.5 以上版本,换成 maven 3.2.1后,异常消失。

Fuse_010:Fuse 快速上手之十:secure-soap

环境:JBoss Fuse 6.2.0

1. 学习重点
(1)开发 JAX-WS Web Service。
(2)使用 CXF 的 JaxWsProxyFactoryBean 创建 Client 端 proxy,调用远程 Web Service。
(3)在配置文件中为 CXF JAX-WS Web service 设置 WS-Security。

2. blueprint.xml 
<?xml version="1.0" encoding="UTF-8"?>
<!--
    JBoss, Home of Professional Open Source
    Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual
    contributors by the @authors tag. See the copyright.txt in the
    distribution for a full listing of individual contributors.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<!--
   This is the OSGi Blueprint XML file defining the CXF JAX-WS beans.  Because the file is in the
   OSGI-INF/blueprint directory inside our JAR, it will be automatically activated as soon as the artifact is installed.

   The root element for any OSGi Blueprint file is 'blueprint' - you also see the namespace definitions for both the Blueprint
   and the CXF JAX-WS namespaces.
-->
<blueprint
        xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws"
        xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
                        http://cxf.apache.org/blueprint/jaxws http://cxf.apache.org/schemas/blueprint/jaxws.xsd">

    <!--
      Using the <jaxws:endpoint/>, we're configuring the actual JAX-WS endpoint, referring to our web service implementation class
      and the URI address we want to assign to our service.  The address is relative to the CXF servlet URI,
      with the default configuration in place, this endpoint will be available at 'http://localhost:8181/cxf/HelloWorld'.
    -->
    <jaxws:endpoint id="helloWorld"
                    implementor="io.fabric8.quickstarts.soap.secure.HelloWorldImpl"
                    address="/HelloWorldSecurity">


        <!--
          We will be adding two interceptors to the inbound interceptor chain:
          - the CXF WSS4J interceptor to support WS-Security for passing along the credentials
          - a reference to the the JAAS authentication interceptor defined as a separate bean later on
            this will ensure that the credentials are being authenticated in the JAAS realm defined there ('karaf')
        -->
        <jaxws:inInterceptors>

            <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
                <property name="properties">
                    <map>
                        <entry key="action" value="UsernameToken"/>
                        <entry key="passwordType" value="PasswordText"/>
                    </map>
                </property>
            </bean>
            <ref component-id="authenticationInterceptor"/>
        </jaxws:inInterceptors>
        <jaxws:outInterceptors>
            <bean class="io.fabric8.quickstarts.soap.secure.EnableCORSInterceptor"/>
        </jaxws:outInterceptors>

        <!--
          Disable the WSS4JInInterceptor validation check fo the password callback, as we don't provide it here.
        -->
        <jaxws:properties>
            <entry key="ws-security.validate.token" value="false"/>
        </jaxws:properties>
    </jaxws:endpoint>

    <!--
      We are using the OSGi Blueprint XML syntax to define a bean that we referred to in our JAX-WS endpoint setup.
      This bean is a CXF interceptor that ensures that a request has been authenticated before allowing it to pass. For
      performing the authentication, this interceptor will delegate to JAAS, using the realm name 'karaf'.  This will allow
      it to reuse the same authentication mechanism that is being used to secure other ESB facilities, such as the remote
      SSH shell and the webconsole.
    -->
    <bean id="authenticationInterceptor" class="org.apache.cxf.interceptor.security.JAASLoginInterceptor">
        <property name="contextName" value="karaf"/>
    </bean>

</blueprint>

3. EnableCORSInterceptor.java
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual
 * contributors by the @authors tag. See the copyright.txt in the
 * distribution for a full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.fabric8.quickstarts.soap.secure;

import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.transport.http.Headers;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class EnableCORSInterceptor extends AbstractPhaseInterceptor {

    public EnableCORSInterceptor() {
        super(Phase.PRE_PROTOCOL);
    }

    @Override
    public void handleMessage(Message message) throws Fault {
        Map> headers = Headers.getSetProtocolHeaders(message);
        try {
            //Access-Control-Allow-Origin:* Access-Control-Allow-Methods:POST,GET
            headers.put("Access-Control-Allow-Origin", Arrays.asList("*"));
            headers.put("Access-Control-Allow-Methods", Arrays.asList("POST", "GET"));
        } catch (Exception ce) {
            throw new Fault(ce);
        }
    }
}


4. SecureSoapTest.java
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual
 * contributors by the @authors tag. See the copyright.txt in the
 * distribution for a full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.fabric8.quickstarts.soap.secure;

import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.*;

/**
 * A Java client application that uses CXF's JaxWsProxyFactoryBean to create a web service client proxy to invoke
 * the remote web service.
 */
public class SecureSoapTest {

    private static final Logger LOG = LoggerFactory.getLogger(SecureSoapTest.class);

    public static void main(String[] args) {
        try {
            new SecureSoapTest().sendRequest();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void sendRequest() throws Exception {
        /*
         * Set up the JaxWsFactoryBean to access our client:
         * - the Java interface defining the service
         * - the HTTP address for the service
         */
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(HelloWorld.class);
        factory.setAddress("http://localhost:8181/cxf/HelloWorldSecurity");

        /*
         * Obtain a proxy, implementing the service interface, to access the remote interface.
         * It will allow you to easily perform the HTTP SOAP request from Java code.
         */
        HelloWorld client = (HelloWorld) factory.create();

        /*
         * Add the extra configuration and interceptors required for the authentication
         */
        Map outProps = new HashMap();
        outProps.put("action", "UsernameToken");
        ClientProxy.getClient(client).getOutInterceptors().add(new CustomSecurityInterceptor());
        ClientProxy.getClient(client).getOutInterceptors().add(new WSS4JOutInterceptor());

        /*
         * Calling sayHi() on on the client object will actually perform an HTTP SOAP request instead behind the scenes
         * and returns the resulting response.
         */
        String ret = client.sayHi("World");
        LOG.info("result: " + ret);

        assertEquals("Hello World", ret);
    }

}


5. CustomSecurityInterceptor.java
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual
 * contributors by the @authors tag. See the copyright.txt in the
 * distribution for a full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.fabric8.quickstarts.soap.secure;

import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;

import java.util.HashMap;
import java.util.Map;

/**
 * CXF Interceptors are a very powerful and flexible mechanism to add custom logic to the default CXF processing,
 * both when using CXF on the client side and on the server side.
 *
 * With this custom security interceptor, we will configure the default WSS4J interceptor in the client to provide the required
 * credentials to perform our web service invocation.
 */
public class CustomSecurityInterceptor extends AbstractPhaseInterceptor {

    /**
     * Configuring the interceptor to be used in the 'setup' phase.
     */
    public CustomSecurityInterceptor() {
        super(Phase.SETUP);
    }

    /**
     * This is the actual implementation for our interceptor - we define the necessary properties for doing the authentication
     * and then iterate over the rest of the interceptor chain to find the WSS4J interceptor and configure it properly.
     */
    public void handleMessage(Message message) throws Fault {
        /*
         * Define the configuration properties
         */
        Map outProps = new HashMap();
        outProps.put("action", "UsernameToken");
        outProps.put("passwordType", "PasswordText");

        /*
         * The username ('admin') is provided as a literal, the corresponding password will be determined by the client
         * password callback object.
         */
        outProps.put("user", "admin");
        outProps.put("passwordCallbackClass", ClientPasswordCallback.class.getName());

        /*
         * Find the WSS4J interceptor in the interceptor chain and set the configuration properties
         */
        for (Interceptor interceptor : message.getInterceptorChain()) {
            //set properties for WSS4JOutInterceptor
            if (interceptor.getClass().getName().equals("org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor")) {
                ((WSS4JOutInterceptor) interceptor).setProperties(outProps);
            }
        }
    }

}


6. ClientPasswordCallback.java
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2014, Red Hat, Inc. and/or its affiliates, and individual
 * contributors by the @authors tag. See the copyright.txt in the
 * distribution for a full listing of individual contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.fabric8.quickstarts.soap.secure;

import org.apache.wss4j.common.ext.WSPasswordCallback;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;

/**
 * This is a JAAS CallbackHandler implementation that will provide the password for our custom security interceptor.
 */
public class ClientPasswordCallback implements CallbackHandler {

    /*
     * Handle the authentication callback by checking the identifier and just hard-coded returning the correct password.
     */
    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];

        /*
         * User is 'admin', password is 'admin'
         */
        if (pc.getIdentifier().equals("admin")) {
            pc.setPassword("admin");
        }
    }

}

7. 编译、部署、卸载
(1)cd /Users/maping/Redhat/fuse/jboss-fuse-6.2.0.redhat-133/quickstarts/cxf/secure-soap
(2)mvn clean install
(3)./fuse (确认 etc/user.properties 文件中 admin 用户已经打开注释)
(4)features:install cxf-ws-security
(5)osgi:install -s mvn:org.jboss.quickstarts.fuse/cxf-secure-soap/6.2.0.redhat-133
(6)osgi:list
(7)http://localhost:8181/cxf/ 
(8)http://localhost:8181/cxf/HelloWorldSecurity?wsdl
(9)cxf:list-endpoints
(10)mvn -Ptest
(11)osgi:uninstall <id>