...

All | Personal | Sun
20060725 2006年 7月 25日 火曜日

why document/literal why document/literal

为什么转用document/literal而不是rpc/encoded

遵循document/literal符合WS-I的规定,在制作Web Services,JAX-WS 2.0VS.NET 2003在默认的情况下,都是生成document/literal服务.那么和rpc/encoded服务相比, document/literal有哪些优点呢.

 

-          document/literal符合XML Schema的形式,可以用XML validator对传递的信息进行校对.

-          rpc/encoded时的信息中,含有数据类型的记述.如果数据增加,所传递的数据量会增加,这样会影响性能.documeht/literal使用了在服务端和客户端共享的WSDL中的信息,从而可以省略数据类型的传递.

Posted by xiaojun ( 7月 25日 2006年, 01:36:04 午後 JST ) Permalink 投稿されたコメント [0]

20060614 2006年 6月 14日 水曜日

Accessing JAX-WS 2.0 with SSL in Glassfish Accessing JAX-WS 2.0 with SSL in Glassfish

   SSLを使い、GlassfishでのWeb Serviceと相互認証を通してアクセスしてみました、以下はそのメモです。 プログラム自体は単純でサーバーサイドにメッセージを送り、レスが返って出力します。

   作業ディレクトリは、図1になります。

working_directory

図 1.

1.サーバー側

package endpoint;

import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.annotation.Resource;
import javax.xml.ws.WebServiceContext;

@WebService(
    name="MyHelloWorld",
    serviceName="MyHelloWorldService",
    targetNamespace="http://javaee5.com/jaxws/helloworld"
)
public class HelloWorld{
    
    //the implementation class must have a default public constructor
    public HelloWorld() {};

    //
    @Resource WebServiceContext wsContext;

    @WebMethod(operationName="mySayHello", action="urn:mySayHello")
    public String sayHello(String name){
	return name + "'s user principal is " 
                   + wsContext.getUserPrincipal();
    }
}
                                                           List 1.

JAX-WS 2.0からJSR 181のannotationを使って、直接にサービスクラスを実装するだけで、開発はとてもシンプルとなってます。 List 1.をコンパイルして、 Glassfishから提供されているユーティリティwsgenを用いて、対応したWSDLファイルを生成できます。

~/ssl> javac -classpath %GLASSFISH_HOME%/lib/javaee.jar -d ./build/classes/service -g endpoint/HelloWorld.java

~/ssl> wsgen.bat -cp ./build/classes/service -keep -d ./build/classes/service -r ./build/generated -wsdl endpoint.HelloWorld

warファイルをパッケージするには、List 2.のweb.xmlを使います。相互認証を行うため、<auth-method>ではCLIENT-CERTと設定します。サービスクラスはWebServiceContext.getUserPrincipal()を読んでるため、その設定はList 3.のsun-web.xmlの<security-role-mapping>で行います。

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:j2ee="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  

      <description>WebTier for the HelloWorld Service</description>
        <display-name>HelloWorldWAR</display-name>  <servlet>
        <description>Endpoint for HelloWorld Web Service</description>
        <display-name>HelloWorldWebService</display-name>
        <servlet-name>MyHelloWorld</servlet-name>
        <servlet-class>endpoint.HelloWorld</servlet-class>
        <load-on-startup>0</load-on-startup>
      </servlet>  <servlet-mapping>
        <servlet-name>MyHelloWorld</servlet-name>
        <url-pattern>/HelloWorldService</url-pattern>
      </servlet-mapping>  <security-constraint>
        <web-resource-collection>
        <web-resource-name>Secure Area</web-resource-name>
        <url-pattern>/HelloWorldService</url-pattern>
        <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
        <role-name>ENGINEER</role-name>
        </auth-constraint>
        <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
      </security-constraint>
      <login-config>
        <auth-method>CLIENT-CERT</auth-method>
        <realm-name>certificate</realm-name>
      </login-config>
      <security-role>
        <role-name>ENGINEER</role-name>
      </security-role>
</web-app>
                                                         List 2.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app 
  PUBLIC "-//Sun Microsystems, 
  Inc.//DTD Application Server 9.0 Servlet 2.5//EN"
  "http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">  
<sun-web-app>
     <context-root>/HelloWorldService</context-root>
     <security-role-mapping>
        <role-name>ENGINEER</role-name>
        <principal-name>
          CN=zerra, OU=JPE, O=Sun, L=HaiDian, S=Beijing, C=China
        </principal-name>
     </security-role-mapping>
</sun-web-app>
                                                           List 3.

asadminコマンドツールを使ってデプロイします。

~/ssl/archive> jar cvf helloworld-webservice.war WEB-INF/

~/ssl/archive> asadmin.bat deploy --user admin --passwordfile s1as_password.txt --host localhost --port 4848 --contextroot helloworld-webservice --upload=true --target server helloworld-webservice.war

2.クライアント側

サーバーで公開されているサービス(WSDL)から、Glassfishのユーティリティwsimportを使い、アクセスするためのクラスを生成します。

~/ssl> wsimport.bat -keep -d ./build/classes/client https://zerra:8181/helloworld-webservice/HelloWorldService?WSDL

生成されたクラスをimportして、クライアントのクラス(List 4.)を作ります。WebServiceRefのwsdlLocationでhttpsの指定にご注目。そしてクラスパスを指定し、クラスをコンパイルします。

package client;
   
import javax.xml.ws.WebServiceRef;
import com.javaee5.jaxws.helloworld.MyHelloWorldService;
import com.javaee5.jaxws.helloworld.MyHelloWorld;
   
public class WSClient{
   
  @WebServiceRef(wsdlLocation=
  "https://zerra:8181/helloworld-webservice/HelloWorldService?WSDL")
   static MyHelloWorldService service;
	   
   public static void main(String[] args){
	   try{
		   WSClient client = new WSClient();
		   client.callEndpoint(args[0]);
	   }catch(Exception e){
		   e.printStackTrace();
	   }
   }
	   
   public void callEndpoint(String name){
	   try{
		   MyHelloWorld port = service.getMyHelloWorldPort();
		   System.out.println(port.mySayHello(name));
	   }catch(Exception e){
		   e.printStackTrace();
	   }
   }
   
}
                                                            List 4.

~/ssl> javac -d ./build/classes/client -classpath %GLASSFISH_HOME%/lib/javaee.jar\;$GLASSFISH_HOME/lib/appserv-ws.jar\;./build/classes/client client/WSClient.java

サーバーと相互認証を行うには、クライアントが自分のキーを生成する必要があり、それをサーバーにあるトラストストーアに導入します。具体的な手順はImport Client's cert into Glassfishに書いてあります。

準備が整ったら、サーバーのトラストストーアとクライアントのキーストーアをVMARGSという環境変数に設定し、実行します。

~/ssl/build/classes/client> set VMARGS=-Djavax.net.ssl.trustStore=%GLASSFISH_HOME%/domains/domain1/config/cacerts.jks -Djavax.net.ssl.trustStorePassword=changeit -Djavax.net.ssl.keyStore=E:\ssl\clientCertificate\xiaojunkeystore.jks -Djavax.net.ssl.keyStorePassword=changeit

~/ssl/build/classes/client> appclient.bat client.WSClient Duke
Duke's user principal is CN=zerra, OU=JPE, O=Sun, L=HaiDian, S=Beijing, C=China

 

Posted by xiaojun ( 6月 14日 2006年, 04:26:02 午後 JST ) Permalink 投稿されたコメント [0]

20060607 2006年 6月 07日 水曜日

Import Client's cert into Glassfish Import Client's cert into Glassfish

 

    Glassfishと双方向認証を行うには、クライアントが自分のkeyを生成し、それをGlassfishサーバーサイドにあるトラストストーアに導入する必要があります。 以下その手順を示します。

1.クライアント側のkeyの生成

JDK 5.0で提供されているkeytoolを使い、簡単にkeyを生成できます。

keytool -genkey -validity 10000 -alias clientkey -dname "CN=zerra, OU=JPE, O=Sun, L=HaiDian, S=Beijing, C=China" -keypass changeit -storepass changeit

2.クライアントの証明書の導出

keytool -export -alias clientkey -storepass changeit -file client.cer -keystore clientstore.jks

このコマンドにより、キー情報が中間ファイルclient.cerに保存されます。

3.クライアントの証明書の導入

keytool -import -noprompt -v -trustcacerts -alias clientkey -file client.cer -keystore ${GLASSFISH_HOME}/domains/domain1/config/cacerts.jks -storepass changeit

${GLASSFISH_HOME}が実際のインストールパスをあらわします。これで、クライアントの証明書がサーバーにあるトラストストーアに保存されました。

下のコマンドを発行し、clientkeyをgrepして確認できます。

keytool -list -v -keystore cacerts.jks -storepass changeit

別名: clientkey
作成日: 2006/06/05
エントリのタイプ: trustedCertEntry

所有者: CN=zerra, OU=JPE, O=Sun, L=HaiDian, ST=Beijing, C=China
実行者: CN=zerra, OU=JPE, O=Sun, L=HaiDian, ST=Beijing, C=China
シリアル番号: 4483a90a
有効日: Mon Jun 05 12:46:18 JST 2006 有効期限: Fri Oct 21 12:46:18 JST 2033
証明書のフィンガープリント:
MD5: 2B:A2:0C:5C:0D:D6:4C:00:09:A3:84:B0:A6:60:53:4D
SHA1: A4:CE:41:4E:12:F3:EB:29:5A:8A:A0:76:87:08:C8:0D:C5:1D:A7:E3

また、証明書をトラストストーアから削除するには、下のコマンドで消せます。

keytool -delete -alias clientkey -keystore ${GLASSFISH_HOME}/domains/domain1/config/cacerts.jks -storepass changeit

 

 

 

 

Posted by xiaojun ( 6月 07日 2006年, 11:01:34 午前 JST ) Permalink 投稿されたコメント [0]

20060224 2006年 2月 24日 金曜日

JAX-WS 2.0 Java<===>WSDL1.1 mappings (written in Japanese) JAX-WS 2.0 Java<===>WSDL1.1 mappings (written in Japanese)

別のスレッドで書いたサンプルをいじって(文章が中国語となってますが、クラスやコマンドが化けないと思うが)、Java<===>WSDL1.1のマッピングをみていきたいと思います。

まず、List1を使って、annotationsのWebServiceとWebMethodの属性のデフォルト値を確認します。Glassfishに提供されているwsgenを使って、WSDLファイル(List2)を生成します。

List 1 (HelloWorld.java)
@WebService()   
public class HelloWorld{
    
    //the implementation class must have a default public constructor
    public HelloWorld() {};

    @WebMethod()
    public String sayHello(String name){
  	return "Hello "+ name + "!";
    }
}

List 2 (HelloWorldService.wsdl)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions targetNamespace="http://endpoint/" name="HelloWorldService" xmlns:tns="http://endpoint/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<xsd:schema>
<xsd:import namespace="http://endpoint/" schemaLocation="HelloWorldService_schema1.xsd"/>
</xsd:schema>
</types>
<message name="sayHello">
<part name="parameters" element="tns:sayHello"/>
</message>
<message name="sayHelloResponse">
<part name="parameters" element="tns:sayHelloResponse"/>
</message>
<portType name="HelloWorld">
<operation name="sayHello">
<input message="tns:sayHello"/>
<output message="tns:sayHelloResponse"/>
</operation>
</portType>
<binding name="HelloWorldPortBinding" type="tns:HelloWorld">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
<operation name="sayHello">
<soap:operation soapAction=""/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="HelloWorldService">
<port name="HelloWorldPort" binding="tns:HelloWorldPortBinding">
<soap:address location="REPLACE_WITH_ACTUAL_URL"/>
</port>
</service>
</definitions>

クラスHelloWorldがportTypeのnameに、メソッド名sayHelloがportTypeの子要素operationの名前にそれぞれとマッピングされているのが分かります。

ここで、annotationsのWebService、WebMethodの属性を指定して(List 3)、List 4のWSDLが生成されます。


List 3 (HelloWorld.java 修正バージョン)
@WebService(
    name="MyHelloWorld",
    serviceName="MyHelloWorldService",
    targetNamespace="http://javaee5.com/jaxws/helloworld"
)   
public class HelloWorld{
    
    //the implementation class must have a default public constructor
    public HelloWorld() {};

    @WebMethod(operationName="mySayHello", action="urn:mySayHello")
    public String sayHello(String name){
	return "Hello "+ name + "!";
    }
}

List 4 (MyHelloWorldService.wsdl)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions
targetNamespace="http://javaee5.com/jaxws/helloworld"
name="MyHelloWorldService"
xmlns:tns="http://javaee5.com/jaxws/helloworld"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">

<types>
<xsd:schema>
<xsd:import namespace="http://javaee5.com/jaxws/helloworld" schemaLocation="MyHelloWorldService_schema1.xsd"/>
</xsd:schema>
</types>
<message name="mySayHello">
<part name="parameters" element="tns:mySayHello"/>
</message>
<message name="mySayHelloResponse">
<part name="parameters" element="tns:mySayHelloResponse"/>
</message>
<portType name="MyHelloWorld">
<operation name="mySayHello">
<input message="tns:mySayHello"/>
<output message="tns:mySayHelloResponse"/>
</operation>
</portType>
<binding name="MyHelloWorldPortBinding" type="tns:MyHelloWorld">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document"/>
<operation name="mySayHello">
<soap:operation soapAction="urn:mySayHello"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="MyHelloWorldService">
<port name="MyHelloWorldPort" binding="tns:MyHelloWorldPortBinding">
<soap:address location="REPLACE_WITH_ACTUAL_URL"/>
</port>
</service>
</definitions>

グラフ1にマッピング関係を示しています。

グラフ 1

ここで見た例はstyle/useに関して暗黙でDocument/Literalが使用されますが、

List 5 (SOAPBindingの指定)
@WebService
@SOAPBinding(style=SOAPBinding.Style.RPC, use=SOAPBinding.Use.ENCODED)
public class HelloWorld{
//the implementation class must have a default public constructor
public HelloWorld() {};     @WebMethod(operationName="mySayHello",          action="urn:mySayHello")
public String sayHello(String name){
return "Hello "+ name + "!";
}
}

List 5のようにSOAPBinding属性の指定を通して、RPC/Encodedに変えられます。

他にも、Oneway、WebParamなどがありますので、用途に応じてカスタマイズできます。

 

Posted by xiaojun ( 2月 24日 2006年, 09:18:16 午後 JST ) Permalink 投稿されたコメント [1]

20060220 2006年 2月 20日 月曜日

JAX-WS 2.0, an HelloWorld例子 (written in Chinese) JAX-WS 2.0 API, an example

     JAX-RPC 1.1,开发人员需要写一个接口类Service Endpoint Interface(SEI),JAX-WS 2.0,开发人员一上来就可以直接写自己的实现类. 通过使用annotations,自动生成SEI和其他一些文件.这样有助于开发人员专注于自己想开发的部分,而不必要地分散精力去维护其他的一些附属文件.

下面通过一个HelloWorld的例子来看看,JAX-WS 2.0 API的应用过程.程序是客户端传给服务端一个名字,经过服务端处理后,返回到客户端并打印出来.

 

一.   环境配置.

1.      JDK 5.0  下载: http://java.sun.com/j2se/1.5.0/download.jsp

2.      Java EE 5.0 App Server.

   https://glassfish.dev.java.net/public/downloadsindex.html

   本例中测试用了Build 37

下载完毕后请设置一下Path.还有例子中使用的命令对应于Cygwin,如果用DosLinux的话,请适当更改相应的形式.

 

例子中执行中的命令行以E:\jaxws20为基准,在其下面创造相对应的文件夹.

 

.编写建立服务端

1.      实现类.

 

package endpoint;

 

import javax.jws.WebService;

import javax.jws.WebMethod;

 

@WebService()  

public class HelloWorld{

   

    //the implementation class must have a default public constructor

    public HelloWorld() {};

 

    @WebMethod(operationName="sayHello", action="urn:SayHello")

    public String sayHello(String name){

              return "Hello "+ name + "!";

    }

}

请注意实现类必须标注WebService(),还必须包括一个default public constructor.

 

2.      编译实现类.

编译前,创造相应文件夹build/classes/service来保存class文件.还请注意命令在同一行.

 

javac -classpath $GLASSFISH_HOME/lib/javaee.jar -d ./build/classes/service endpoint/HelloWorld.java

 

3.      生成相应文件

E:\jaxws20,执行下面的命令,注意事先生成/build/generated.

$GLASSFISH_HOME/bin/wsgen.bat-cp ./build/classes/service -keep -d ./build/classes/service -r ./build/generated -wsdl endpoint.HelloWorld

 

通过这个命令,会生成相对应的WSDL文件.

 

4.      打包

4.1   WEB-INF`结构准备

    WEB-INF/classes/

    WEB-INF/wsdl/

 

4.2  Web.xml

WEB-INF/,编写下面的文件.

     <?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"

              xmlns:j2ee="http://java.sun.com/xml/ns/javaee"

              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.5"

              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

                                          http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

 

              <description>HelloWorld Service</description>

              <display-name>HelloWorldWAR</display-name>

 

              <servlet>

                            <description>Endpoint for HelloWorld Web Service</description>

                            <display-name>HelloWorldWebService</display-name>

                            <servlet-name>HelloWorldPort</servlet-name>

                            <servlet-class>endpoint.HelloWorld</servlet-class>

                            <load-on-startup>0</load-on-startup>

              </servlet>

 

              <servlet-mapping>

                            <servlet-name>HelloWorldPort</servlet-name>

                            <url-pattern>/HelloWorldService</url-pattern>

              </servlet-mapping>

              <session-config>

                            <session-timeout>60</session-timeout>

              </session-config>

</web-app>

 

4.3 拷贝文件

cp -r build/classes/service/endpoint ./WEB-INF/classes/

cp build/generated/* archive/WEB-INF/wsdl/

 

4.4打包

 jar cvf helloworld-webservice.war WEB-INF/

 

5.      配置

  先启动服务器,

asadmin.bat start-domain domain1

  配置到服务器中,

asadmin.bat deploy --user admin --password adminadmin --host localhost --port 4848 --contextroot helloworld-webservice --upload=true --target server helloworld-webservice.war

 

三.   客户端

1.      客户端类.

client/,

package client;

 

import javax.xml.ws.WebServiceRef;

import endpoint.HelloWorldService;

import endpoint.HelloWorld;

 

public class WSClient{

 

       @WebServiceRef(wsdlLocation=

       "http://localhost:8080/helloworld-webservice/HelloWorldService?WSDL")

      

       static HelloWorldService service;

      

       public static void main(String[] args){

              try{

                     WSClient client = new WSClient();

                     client.callEndpoint(args[0]);

              }catch(Exception e){

                     e.printStackTrace();

              }

       }

      

       public void callEndpoint(String name){

              try{

                     HelloWorld port = service.getHelloWorldPort();

                     System.out.println(port.sayHello(name));

              }catch(Exception e){

                     e.printStackTrace();

              }

       }

}

 

2.      生成相关文件

  在编译客户端类之前, 需要从服务端公开中的WSDL生成相关的文件.

wsimport.bat -keep -d ./build/classes/client http://localhost:8080/helloworld-webservice/HelloWorldService?WSDL

 

3.      编译客户端类

javac-d ./build/classes/client -classpath $GLASSFISH_HOME/lib/javaee.jar\;$GLASSFISH_HOME/lib/appserv-ws.jar\;./build/classes/client client/WSClient.java 

 

四.   执行

build/classes/client/,

appclient.bat -mainclass  client.WSClient Duke

 

你会看到如下反馈

Hello Duke!

 

追加: 通过下面的命令,可以卸掉装配好的war文件.

 

asadmin.bat undeploy --user admin --password adminadmin helloworld-webservice

 

 

 

Posted by xiaojun ( 2月 20日 2006年, 05:16:09 午後 JST ) Permalink 投稿されたコメント [2]

Calendar

RSS Feeds

Search

Links

Navigation

Referers