2008년 3월 4일 화요일

Apache Axis2 User's Guide - Creating Clients

수작업으로 Web service client를 생성할수 있다(참조 Building Services), 그러나 대부분의 경우 당신은 클라이언트가 보내고 받기를 기대하는 메세지를 명세한 Web Service Description Language (WSDL) definition을 가지고 있을것이다. Axis2는 자동으로 클라이언트를 생성하기위한 이 정의를 사용하는 몇몇의 방법을 제공한다.

Choosing a Client Generation Method

------------------------------------------------------------------------------------------------------------------
Axis2는 클라이언트를 생성하면서 WSDL을 객체에 맵핑할때 몇몇의 옵션을 제공한다. 이 3개의 옵션은 Axis2 DataBinding Framework, XMLBeans, 그리고 JiBX databinding 이다. 이 모든 방법은 서비스에서 사용되는 XML 구조를 벗어나 자바 객체를 생성하기위해 데이터바인딩을 이용한다, 그리고 그들 각각은 그들의 pros와 cons를 가지고 있다. 또한 당신은 데이터 바인딩에 기반을 두지 않은 XML in-out stubs를 생성할 수 있다.


Axis2 Databinding Framework (ADB): 아마도 Axis2 클라이언트를 생성하는 가장 간단한 방법은 ADB일 것이다. 대부분의 경우, 관련된 모든 클래스들은 메인 스텁 클래스의 내부 클래스(inner classes)로 생성된다. ADB는 사용하기 매우 쉽지만 제한이 없다. 이것이 full schema binding 어플리케이션이라는 의미는 아니다, 그리고 XML Schema element extensions과 restrictions 처럼 구조화 하기 어렵다.


XMLBeans: ADB와 달리, XMLBeans는 fully functional 스키마 컴파일러 이다, 그래서 ADB처럼 동일한 제한들을 운반하지 않는다. 그럼에도 불구하고 이것은 ADB보다 사용하기에 약간더 복잡하다. 이것은 거대한 양의 파일을 생성한다, 그리고 프로그래밍 모델이 매우 유용하지만 ADB 처럼 직관적이지 못하다.


JiBX: JiBX는 full 데이터바인딩 프레임웍 이며 WSDL-to-Java conversion(이 문서에서 설명할 것이다) 뿐만아니라 Java-to-XML conversion도 제공한다. 어떤 방법을 이용해 JiBX는 최고의 두개의 세계모두를 제공한다.  JiBX는 매우 유연(당신의 엔티티들을 표현하는 클래스를 선택가능하다) 하지만 셋업 하기가 복잡하다. 다르게 말하면, 일단 셋업되고 나면 생성된 코드를 실제로 이용할때는 ADB를 사용하는 것 처럼 쉽다.


마지막으로, 간단한 구조를 위해서는 ADB만으로도 충분하다. 다르게 말하면, 만약 당신이 더 많은 파워 또는 유연성을 얻으려면 얼마나 많은 파워 또는 유연성이 필요한지와 복잡성을 감수하는가에 따라 XMLBeans 또는 JiBX 중 하나를 선택하면 된다.

Generating Clients

------------------------------------------------------------------------------------------------------------------

클라이언트를 생성하고 사용하는 과정은 당신이 선택한 생성 방법에 따라 약간씩 다르다. 이 문서에 있는 3개의 경우 모두 클라이언트는 동일한 WSDL 파일을 이용해 생성된 것이다 (참조 Code Listing 5).


Code Listing 5 - Generating clients from the WSDL file

---------------------------------------------------------------------------------------------------------

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
   xmlns:apachesoap="
http://xml.apache.org/xml-soap"
   xmlns:impl="
http://apache.org/axis2/Axis2UserGuide"
   xmlns:intf="
http://apache.org/axis2/Axis2UserGuide"
   xmlns:wsdl="
http://schemas.xmlsoap.org/wsdl/"
   xmlns:wsdlsoap="
http://schemas.xmlsoap.org/wsdl/soap/"
   xmlns:xsd="
http://www.w3.org/2001/XMLSchema"
   targetNamespace="
http://apache.org/axis2/Axis2UserGuide">

  <wsdl:types>
    <schema
       elementFormDefault="qualified"
       targetNamespace="
http://apache.org/axis2/Axis2UserGuide"
       xmlns="
http://www.w3.org/2001/XMLSchema">
     
      <!-- ELEMENTS -->
     
      <element name="DoInOnlyRequest">
        <complexType>
          <sequence>
            <element name="messageString" type="xsd:string"/>
          </sequence>
        </complexType>
      </element>
element name="TwoWayOneParameterEchoRequest">
        <complexType>
          <sequence>
            <element name="echoString" type="xsd:string"/>
          </sequence>
        </complexType>
      </element>
      <element name="TwoWayOneParameterEchoResponse">
        <complexType>
          <sequence>
            <element name="echoString" type="xsd:string"/>
          </sequence>
        </complexType>
      </element>
     
      <element name="NoParametersRequest">
        <complexType/>
      </element>
      <element name="NoParametersResponse">
        <complexType/>
      </element>
     
      <element name="MultipleParametersAddItemRequest">
        <complexType>
          <sequence>
            <element name="itemId" type="xsd:int"/>
            <element name="itemName" type="xsd:string"/>
            <element name="price" type="xsd:float"/>
            <element name="description" type="xsd:string"/>
          </sequence>
        </complexType>
      </element>

      <element name="MultipleParametersAddItemResponse">
        <complexType>
          <sequence>
          <element name="itemId" type="xsd:int"/>
          <element name="successfulAdd" type="xsd:boolean"/>
          </sequence>
        </complexType>
      </element>

    </schema>
  </wsdl:types>

<!-- MESSAGES -->

  <wsdl:message name="DoInOnlyRequestMessage">
    <wsdl:part name="input" element="impl:DoInOnlyRequest"/>
  </wsdl:message>

  <wsdl:message name="TwoWayOneParameterEchoRequestMessage">
    <wsdl:part name="input" element="impl:TwoWayOneParameterEchoRequest"/>
  </wsdl:message>
  <wsdl:message name="TwoWayOneParameterEchoResponseMessage">
    <wsdl:part name="output" element="impl:TwoWayOneParameterEchoResponse"/>
  </wsdl:message>

  <wsdl:message name="NoParametersRequestMessage">
    <wsdl:part name="input" element="impl:NoParametersRequest"/>
  </wsdl:message>
  <wsdl:message name="NoParametersResponseMessage">
    <wsdl:part name="output" element="impl:NoParametersResponse"/>
  </wsdl:message>

  <wsdl:message name="MultipleParametersAddItemRequestMessage">
    <wsdl:part name="input" element="impl:MultipleParametersAddItemRequest"/>
  </wsdl:message>
  <wsdl:message name="MultipleParametersAddItemResponseMessage">
    <wsdl:part name="output" element="impl:MultipleParametersAddItemResponse"/>
  </wsdl:message>

<!-- Port type (operations) -->

  <wsdl:portType name="Axis2UserGuidePortType">

    <wsdl:operation name="DoInOnly" parameterOrder="input">
      <wsdl:input name="DoInOnlyRequestMessage"
                  message="impl:DoInOnlyRequestMessage"/>
    </wsdl:operation>

    <wsdl:operation name="TwoWayOneParameterEcho" parameterOrder="input">
      <wsdl:input name="TwoWayOneParameterEchoRequestMessage"
                  message="impl:TwoWayOneParameterEchoRequestMessage"/>
      <wsdl:output name="TwoWayOneParameterEchoResponseMessage"
                  message="impl:TwoWayOneParameterEchoResponseMessage"/>
    </wsdl:operation>

    <wsdl:operation name="NoParameters" parameterOrder="input">
      <wsdl:input name="NoParametersRequestMessage"
                  message="impl:NoParametersRequestMessage"/>
      <wsdl:output name="NoParametersResponseMessage"
                   message="impl:NoParametersResponseMessage"/>
    </wsdl:operation>

    <wsdl:operation name="MultipleParametersAddItem" parameterOrder="input">
      <wsdl:input name="MultipleParametersAddItemRequestMessage"
                  message="impl:MultipleParametersAddItemRequestMessage"/>
      <wsdl:output name="MultipleParametersAddItemResponseMessage"
                  message="impl:MultipleParametersAddItemResponseMessage"/>
    </wsdl:operation>

  </wsdl:portType>

<!-- BINDING (bind operations) -->
  <wsdl:binding
     name="Axis2UserGuideSoapBinding"
     type="impl:Axis2UserGuidePortType">
    <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>

    <wsdl:operation name="DoInOnly">
      <wsdlsoap:operation soapAction="DoInOnly"/>
      <wsdl:input>
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
    </wsdl:operation>

    <wsdl:operation name="TwoWayOneParameterEcho">
      <wsdlsoap:operation soapAction="TwoWayOneParameterEcho"/>
      <wsdl:input>
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>

    <wsdl:operation name="NoParameters">
      <wsdlsoap:operation soapAction="NoParameters"/>
      <wsdl:input>
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>

    <wsdl:operation name="MultipleParametersAddItem">
      <wsdlsoap:operation soapAction="MultipleParametersAddItem"/>
      <wsdl:input>
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>

<!-- SERVICE -->

  <wsdl:service name="Axis2UserGuideService">
    <wsdl:port binding="impl:Axis2UserGuideSoapBinding"
               name="Axis2UserGuide">
      <wsdlsoap:address location="
http://localhost:8080/axis2/services/Axis2UserGuide"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>
---------------------------------------------------------------------------------------------------------


여기서는 4개의 operation을 정의한다, DoInOnly, NoParameters, TwoWayOneParameterEcho, 그리고 MultipleParametersAddItem 이다. 각각의 클라이언트는 각각의 이 operation들을 호출하기 위한 함수를 가지고 있을 것이다.


(WSDL에 대한 더많은 정보를 원하면 http://www.w3.org/2002/ws/desc/ 를 방문하라.)

Axis Data Binding (ADB)

------------------------------------------------------------------------------------------------------------------

ADB를 이용하는 클라이언트를 생성하기 위해서는 다음의 단계를 실행하라:


The short story:


    1. 이것을 이전에 하지 않았으면 Apache Axis2 Standard Distribution을 다운로드하고 압축을 풀어라.


    2. 다음의 명령어를 이용해 클라이언트 stub을 생성하라:


        %AXIS2_HOME%\bin\wsdl2java -uri Axis2UserGuide.wsdl -p org.apache.axis2.axis2userguide -d adb -s


    3. 생성된 stub을 이용하는 자바 어플리케이션인 클라이언트(예: Client.java)를 생성하라,

       그리고 org/apache/axis2/axis2userguide 디렉토리에 이것을 저장하라.


    4. ant jar.client 명령어로 클라이언트를 빌드하라.


    5. 상응하는 서비스가 있다고 가정하고 build/lib 폴더안에 생성된 Axis2UserGuideService-test-client.jar 파일을

       클래스패스에 추가한다음 아래의 명령어를 실행해 클라이언트를 실행하라:


       java org.apache.axis2.axis2userguide.Client


The long story:


이것을 이전에 하지 않았으면 Apache Axis2 Standard Distribution을 다운로드하고 압축을 풀어라. Axis2 War Distribution은 WSDL2Java와 같은 코드를 생성하기위해 필요한 유틸리티들을 포함하고 있지 않다.


클라이언트를 생성할때 ADB 방법을 사용하면 서비스를 위한 모든 기능들은 stub 이라 불리는 하나의 클래스에 들어가게 된다.

stub은 WSDL 파일에 정의되어 있는 필요한 모든 객체에 해당하는 inner 클래스를 포함한다. 이 WSDL의 경우는 DoInOnlyRequestMessage를 예를 들수 있다. stub을 이용해 이런 클래스들과 그들의 함수들을 참조하여 쉽게 클라이언트를 생성할 수 있다. 클라이언트를 생성하기 위해서 Code Listing 6 의 명령을 따라라.

Code Listing 6 - Generating the Client
------------------------------------------------------------------------------------------------------------------


%AXIS2_HOME%\bin\wsdl2java -uri Axis2UserGuide.wsdl -p org.apache.axis2.axis2userguide -d adb -s


이 명령은 WSDL 파일을 분석하고 org.apache.axis2.axis2userguide 패키지에 stub을 생성한다. -d 옵션은 ADB data binding 방식을 사용한다는 의미이고, -s 옵션은 synchronous 또는 blocking 방식을 사용한다는 의미이다. 다르게 말하면, 클라이언트가 서버에 In-Out 호출을 하고나서 계속 진행하지 않고 response를 기다린다는 의미이다.


당신이 이 명령을 실행하고 나면 디렉토리 안에 새로운 두개의 아이템이 보일 것이다. 첫번째는 Ant가 클래스를 컴파일하고 생성하기위한 지시를 포함하고 있는 build.xml 파일이다. 두번째는 실제 Axis2UserGuideServiceStub.java 파일을 가지고 있는 src 디렉토리이다. 이 파일을 열어보면 wsdl 파일에서 명세한 각각의 아이템들을 위한 inner 클래스의 collection을 볼수 있다. 또한 몇개의 Axis2 client API 호출을 볼것이다. Axis2 client API는 들어오거나 나가는 메세지들을 빌드하고 분석하기위해 axiom을 이용한다.


이제 이 코드를 이용하기 위한 클라이언트가 필요하다. 클라이언트를 생성하기 위해 org/apache/axis2/axis2userguide 디렉토리에 Client.java 라는 새로운 클래스를 만들어라. 이것은 아래의 Code Listing 7 에 있는 코드를 포함하고 있다.


Code Listing 7- Client.java

---------------------------------------------------------------------------------------------------------

package org.apache.axis2.axis2userguide;


import org.apache.axis2.axis2userguide.Axis2UserGuideServiceStub.DoInOnlyRequest;
import org.apache.axis2.axis2userguide.Axis2UserGuideServiceStub.TwoWayOneParameterEchoRequest;
import org.apache.axis2.axis2userguide.Axis2UserGuideServiceStub.NoParametersRequest;
import org.apache.axis2.axis2userguide.Axis2UserGuideServiceStub.MultipleParametersAddItemRequest;

import org.apache.axis2.axis2userguide.Axis2UserGuideServiceStub.TwoWayOneParameterEchoResponse;
import org.apache.axis2.axis2userguide.Axis2UserGuideServiceStub.NoParametersResponse;
import org.apache.axis2.axis2userguide.Axis2UserGuideServiceStub.MultipleParametersAddItemResponse;


public class Client{

    public static void main(java.lang.String args[]){
        try{
            Axis2UserGuideServiceStub stub = new Axis2UserGuideServiceStub

                                                                      ("http://localhost:8080/axis2/services/Axis2UserGuideService");

            doInOnly(stub);
            twoWayOneParameterEcho(stub);
            noParameters(stub);
            multipleParameters(stub);

        } catch(Exception e){
            e.printStackTrace();
            System.out.println("\n\n\n");
        }
    }

/* do in only */
    public static void doInOnly(Axis2UserGuideServiceStub stub){
        try{
            DoInOnlyRequest req = new DoInOnlyRequest();

            req.setMessageString("An in only request");

            stub.DoInOnly(req);
            System.out.println("done");
        } catch(Exception e){
            e.printStackTrace();
            System.out.println("\n\n\n");
        }
    }


    /* two way call/receive */
    public static void twoWayOneParameterEcho(Axis2UserGuideServiceStub stub){
        try{
            TwoWayOneParameterEchoRequest req = new TwoWayOneParameterEchoRequest();

            req.setEchoString("echo! ... echo!");

            TwoWayOneParameterEchoResponse res = stub.TwoWayOneParameterEcho(req);

            System.out.println(res.getEchoString());
        } catch(Exception e){
            e.printStackTrace();
            System.out.println("\n\n\n");
        }
    }


    /* No parameters */
    public static void noParameters(Axis2UserGuideServiceStub stub){
        try{
            NoParametersRequest req = new NoParametersRequest();

            System.out.println(stub.NoParameters(req));
        } catch(Exception e){
            e.printStackTrace();
            System.out.println("\n\n\n");
        }
    }

/* multiple parameters */
    public static void multipleParameters(Axis2UserGuideServiceStub stub){
        try{
            MultipleParametersAddItemRequest req = new MultipleParametersAddItemRequest();

            req.setPrice((float)1.99);
            req.setItemId((int)23872983);
            req.setDescription("Must have for cooking");
            req.setItemName("flour");

            MultipleParametersAddItemResponse res = stub.MultipleParametersAddItem(req);

            System.out.println(res.getSuccessfulAdd());
            System.out.println(res.getItemId());
        } catch(Exception e){
            e.printStackTrace();
            System.out.println("\n\n\n");
        }
    }
}

---------------------------------------------------------------------------------------------------------

WSDL 파일에 정의된 이름들을 이용하는 적당한 request 타입을 생성하고 populating 하고난후 stub을 이용해 적당한 함수에 실제로 request를 보내는 방식으로 서비스를 사용하는것이 간단하다는 것을 인지하시오. 예를들면, DoInOnly operation을 호출하기위해 당신은 DoInOnlyRequest를 생성하고 setMessageString() 함수를 이용해 이것의 messageString element의 컨텐츠를 셋팅한 다음 이것을 stub.DoInOnly() 함수에 알규먼트로 넘긴다.


클라이언트를 생성하기위해 ant jar.client 명령을 사용하라.


이렇게 하면 두개의 새로운 디렉토리(build와 test)를 생성할 것 이다. test 디렉토리는 비어있지만 build 디렉토리는 2개의 클라이언트 버젼을 포함하고 있다. 첫번째 버젼은 lib 디렉토리에 있으며 클라이언트 클래스와 stub을 포함하는 하나의 jar 파일이다. 두번째는 classes 디렉토리에 있으며 classes 파일들 만을 포함하고 있다.


Axis2 lib directory 안의 모든 jar 파일들이 클래스패스에 잡여있는지 확인하라.


만약 당신이 이 클라이언트에 상응하는 서비스를 가지고 있으면 -- 만약 없으면 Building services 문서를 확인하라 -- 당신은 jar 파일을 당신의 클래스패스에 추가하고 java org.apache.axis2.axis2userguide.Client 명령어를 이용해 클라이언트를 실행할 수 있다.


당신의 서블릿 컨테이너의 콘솔창에서 response를 볼 수 있다. 이것은 아래와 같을 것이다:


사용자 삽입 이미지

ADB만이 웹 서비스 클라이언트를 생성하는 유일한 옵션이 아니다. XmlBeans, JiBX, JAXME 그리고 JAXBRI 와 같은 다른 옵션들도 있다.


 

댓글 없음:

댓글 쓰기