펌: http://daddycat.blogspot.kr/2011/05/chapter-3-wsdlweb-service-description.html

 

 

Chapter 3 WSDL(Web Service Description Language)


SOAP은 원격 프로시저 호출을 할 수 있는 구조만 제공할 뿐이고, 실제로 호출하는 원격 프로시저명과 필요한 인자, 그리고 반환형이 무엇인지 모른다면 원격 프로시저를 호출하는 내용을 작성 할 수가 없다. 또한 SOAP 메시지를 전송하는 전송 프로토콜의 종류 및 웹 서비스 시스템의 URL(endpoint) 정보도 알고 있어야 한다. 그래서 웹 서비스 제공자는 웹 서비스의 기능을 명세화하여, UDDI 레지스트리에 공개를 해야 한다. WSDL로 XML 문서를 작성하여 웹 서비스에 대한 내용을 명세화 한다. WSDL 문서 사용의 장점은 다음과 같다.
· 서비스 공용 저장소(UDDI)를 이용할 경우 실제 Web Service의 위치와 상관 없이 자신이 원하는 서비스를 찾아서 이용할 수 있다.
· WSDL은 누구나 참조가 가능하기 때문에 이를 통해 쉽게 Web Service 사용에 필요한 정보를 얻을 수 있다.
1. WSDL 문서의 구조

· types는 교환된 메시지를 설명하는 데 사용된 데이터 형식 정의를 제공합니다.
· message는 전송되는 데이터의 추상 정의를 나타냅니다. 메시지는 논리적인 부분으로 이루어져 있으며 각 부분은 특정 형식 시스템 내의 정의와 연관되어 있습니다.
· portType은 추상 작업의 집합이며 각 작업은 입력 메시지 및 출력 메시지를 참조합니다.
· binding은 특정 portType에 의해 정의된 메시지 및 작업에 대해 구체적인 프로토콜과 데이터 형식을 지정합니다.
· port는 바인딩에 대해 주소를 지정하기 때문에 단일 통신 종점을 정의합니다.
· service는 관련된 포트의 집합을 집계하는 데 사용됩니다.
<definition>
WSDL 문서의 루트 엘리먼트이다. 일반적으로 WDSL 문서 내에서 사용되는 대부분의 네임스페이스들을 선언한다. tarrgetNamespace는 현재 WSDL 문서에서 작성될 내용에 대한 네임스페이스 이름을 기술해 준다. WSDL 문서에서 정의되는 원격 프로시저는 이 네임스페이스 이름을 갖는다. 그리고 웹 서비스 클라이언트는 원격 프로시저를 호출할 때 반드시 이 네임스페이스 이름을 이용해서 QName 형태로 원격 프로시저명을 기술해야 한다.
<definitions name="StockQuote"
targetNamespace="http://example.com/stockquote.wsdl"
xmlns:tns="http://example.com/stockquote.wsdl"
xmlns:xsd1="http://example.com/stockquote.xsd"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
</definitions>


WSDL 문서에서 관례적으로 많이 사용되는 네임스페이스 선언
접두사
이름 공간 URI
정의
wsdl
http://schemas.xmlsoap.org/wsdl/ WSDL 프레임워크에 대한 WSDL 이름 공간.
soap
http://schemas.xmlsoap.org/wsdl/soap/ WSDL SOAP 바인딩에 대한 WSDL 이름 공간.
http
http://schemas.xmlsoap.org/wsdl/http/ HTTP GET & POST 바인딩에 대한 WSDL 이름 공간.
mime
http://schemas.xmlsoap.org/wsdl/mime/ MIME 바인딩에 대한 WSDL 이름 공간.
soapenc
http://schemas.xmlsoap.org/soap/encoding/ SOAP 1.1에 의해 정의된 인스턴스 이름 공간.
soapenv
http://schemas.xmlsoap.org/soap/envelope/ SOAP 1.1에 의해 정의된 인스턴스 이름 공간.
xsi
http://www.w3.org/1999/XMLSchema-instance XSD에 의해 정의된 인스턴스 이름 공간.
xsd
http://www.w3.org/1999/XMLSchema XSD에 의해 정의된 스키마 이름 공간.
tns
(다양함) “this namespace”를 의미하는 (tns) 접두사는 현재 문서를 참조하는 규칙으로 사용됩니다.
(기타)
(다양함) 다른 모든 이름 공간 접두사는 단지 예제일 뿐입니다. 특히, “http://example.com”으로 시작하는 URI는 어느 정도 응용 프로그램 종속적이거나 컨텍스트 종속적인 URI[4]를 나타냅니다.


<message>
원격 프로시저의 인자에 대한 정보와 리턴값에 대한 정보를 기술하는 엘리먼트이다. 인자에 대한 정보로는 인자의 수 및 인자의 데이터 타입을 말하고, 리턴값에 대한 정보는 리턴값에 대한 데이터 타입을 말한다. 원격 프로시저의 인자 하나는 하나의 message 엘리먼트로 작성된다.
String addBook1(String title, int price);
이 메서드를 message로 표현
<message name="addBookRequest">
<part name="title" type="xsd:string"/>
<part name="price" type="xsd:int"/>
</message>
<message name="addBook1Response">
<part name="result" type="xsd:string"/>
</message>


<type>
원격 프로시저의 인자 및 리턴값의 데이터 타입으로 사용될 복합 타입을 기술하기 위한 엘리먼트이다. 만약 인자 및 리턴값의 데이터 타입에 복합 타입을 사용하지 않는다면 WSDL 문서에서 이 엘리먼트는 생략될 것이다.
일반적인 분산 컴퓨팅 응용프로그램에서 인자형 및 리턴형이 객체 타입이라면 전송되기 전에 직렬화를 거쳐 이진 포맷으로 변환해야 한다. 그리고 받는 쪽에서는 역직열화르 ㄹ거쳐 객체로 다시 생성하는 작업을 해야 한다. 웹 서비스의 경우에도 웹 서비스 클라이언트 스텁 객체를 통해서 인자를 요청 SOAP 메시지로 마샬링하고, 웹 서비스 시스템은 타이 객체를 통해 SOAP 메시지를 언마샬링하여 원래의 인자 데이터형으로 복원한다.
WDSL 문서의<message> 엘리먼트에 기술되는 인자 및 리턴값의 데이터 타입이 XML Schema의 빌트인 심플타입으로 표현될 수있다면 XML Schema 타입을 직접 사용하지만 배열 및 구조체와 같은 XML Schema에 없는 데이터 타입이 인자 및 리턴값의 데이터 타입으로 사용된다면, 반드시 <types> 엘리먼트에 배열 및 구조체에 해당하는 복합 타입을 정의 해야 한다.
<types>
<schema
targetNamespace="복합 타입 네임스페이스명"
xmlns:tns=”복합 타입 네임스페이스명”
xmlns=”http://www.w3.org/2001/XMLSchema”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:wsdl=”http://schemas.xmlsoap.org/wdsl/”
xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/">
<complexType name="복합 타입명">

</complexType>
</schema>
</types>


배열정의
<complexType name="배열의 이름">
<complexContent>
<restriction base=”soap-enc:Array”>
<attribute ref=”soap-enc:arrayType” wsdl:arrayType=”데이터 타입[]”/>
</restriction>
</complexContent>
</complexType>


구조체 정의
<complexType name="클래스명">
<sequence>
<element name=”멤버변수(Field)명” type=”데이터 타입”/>
<element name=”멤버변수(Field)명” type=”데이터 타입”/>

</sequence>
</complexType>


<portType>, <operation>
Web Service의 interface를 정의하는 부분 interface를 정의 한다는 의미는 <message>에서 정의한 메시지를 이용하여 어떻게 Web Service의 Method를 호출할 지에 대해 기술한다는 것을 의미 한다. <portType>은 하나 이상의 <operation>을 포함한다.
Java 메서드
public String say(String name) {
return name+"님 안녕하세요 Apache WSDL 입니다.";
}


WSDL문서 정의
<message name="say0Request">
<part name="name" type="xsd:string"/>
</message>
<message name="say0Response">
<part name="return" type="xsd:string"/>
</message>
<portType name="sayerPortType">
<operation name="say">
<input name="say0Request" message="tns:say0Request"/>
<output name="say0Response" message="tns:say0Response"/>
</operation>
</portType>


<binding>
앞에서 정의된 각 요소들을 실제 메시지 전달에 사용되는 프로토콜과 binding 하는 부분이다.
특정 프로토콜로 웹 서비스 시스템에 접속하는 것을 바인딩이라고 한다. 바인딩하는 방법을 모른다면 웹 서비스 클라이언트는 원격 프로시저에 대한 호출 방법을 비록 안다고 하더라도 호출 행위는 할 수 없다. 웹 서비스 클라이언트가 사용해야할 전송용 프로토콜에 대해서는 WDSL 문서상의 이 엘리먼트에 기술해주면 된다. 이 엘리먼트는 웹 서비스 시스템과 웹 서비스 소비자인 클라이언트 응용프로그램 간의 통신 방법을 기술하는 엘리먼트이다.
바인딩의 종류
· SOAP 바인딩 : 웹 서비스 시스템의 원격 프로시저를 호출할 때 SOAP를 통해서 호출 요청하는 방식을 말한다.
· HTTP 바인딩 : HTTP는 주로 SOAP메시지의 전송 프로토콜로 많이 사용되지만, 원격 프로시저 호출용 프로토콜로 직접 사용될 수 있다. HTTP만 해석하고, 전송할 수 있는 클라이언트 응용프로그램에서 웹 서비스의 원격 프로시저를 호출할 때 유용하다. 이러한 클라이언트 종류로 는 웹 브라우저, 휴대폰, PDA등이 있다.
· MIME 바인딩 : MIME는 SOAP과 HTTP에서 함께 사용하여 문자 데이터와 바이너리 데이터를 함께 전송할 때 사용할 수 있는 방식이다.
가장 흔히 사용되는 SOAP 바인딩
<binding name="sayerBinding" type="tns:sayerPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="say">
<soap:operation soapAction="" style="rpc"/>
<input name="say0Request">
<soap:body use="encoded" namespace="ApacheWSDL" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output name="say0Response">
<soap:body use="encoded" namespace="ApacheWSDL" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>


<service>, <port>
수신자와 웹 서비스 시스템의 URL(종점 : endpoint)정보를 기술한다.
<service name="ApacheWSDL">
<port name="sayerPort" binding="tns:sayerBinding">
<soap:address location="http://localhost:8080/soap/servlet/rpcrouter"/>
</port>
</service>


자동 생성된WSDL
일반적으로 WSDL은 개발 IDE툴이나, JAX-RPC에서 제공하는 wsdeploy.bat, wscompile.bat을 이용하여 자동 생성한다. 다음은 oracle Jdeveloper을 이용한 자동생성 문서의 예이다.
<?xml version = '1.0' encoding = 'UTF-8'?>
<!--Generated by the Oracle9i JDeveloper Web Services WSDL Generator-->
<!--Date Created: Thu Jan 15 16:26:34 KST 2004-->
<definitions
name="TypeMappingWS"
targetNamespace="http://model/UserInfo.wsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://model/UserInfo.wsdl"
xmlns:ns1="http://model/ITypeMappingWS.xsd">
<types>
<schema
targetNamespace="http://model/ITypeMappingWS.xsd"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
<complexType name="model_user" jdev:packageName="model" xmlns:jdev="http://xmlns.oracle.com/jdeveloper/webservices">
<all>
<element name="name" type="string"/>
<element name="age" type="int"/>
</all>
</complexType>
</schema>
</types>
<message name="getUser0Request">
<part name="name" type="xsd:string"/>
<part name="age" type="xsd:int"/>
</message>
<message name="getUser0Response">
<part name="return" type="ns1:model_user"/>
</message>
<portType name="UserInfoPortType">
<operation name="getUser">
<input name="getUser0Request" message="tns:getUser0Request"/>
<output name="getUser0Response" message="tns:getUser0Response"/>
</operation>
</portType>
<binding name="UserInfoBinding" type="tns:UserInfoPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getUser">
<soap:operation soapAction="" style="rpc"/>
<input name="getUser0Request">
<soap:body use="encoded" namespace="TypeMappingWS" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output name="getUser0Response">
<soap:body use="encoded" namespace="TypeMappingWS" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="TypeMappingWS">
<port name="UserInfoPort" binding="tns:UserInfoBinding">
<soap:address location="http://localhost:8080/soap/servlet/rpcrouter"/>
</port>
</service>
</definitions>

 

'WebService' 카테고리의 다른 글

WSDL  (0) 2015.12.31
WS security  (0) 2014.01.29

WS-Security (Web Services Security, short WSS) is an extension to SOAP to apply security to web services. It is a member of the WS-* family of web service specifications and was published by OASIS.

The protocol specifies how integrity and confidentiality can be enforced on messages and allows the communication of various security token formats, such as SAML, Kerberos, and X.509. Its main focus is the use of XML Signature and XML Encryption to provide end-to-end security.



[추가필요한 lib]


<!-- WS-Security -->

<dependency>

<groupId>org.apache.ws.security</groupId>

<artifactId>wss4j</artifactId>

<version>1.6.4</version>

</dependency>

<dependency>

<groupId>org.apache.cxf</groupId>

<artifactId>cxf-rt-ws-security</artifactId>

<version>2.4.1</version>

</dependency>

<dependency>

<groupId>com.sun.xml.ws</groupId>

<artifactId>jaxws-rt</artifactId>

<version>2.2.9-b14002</version>

</dependency>

[ClientPasswordCallback.java 추가생성]


import java.io.IOException;


import javax.security.auth.callback.Callback;

import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.ws.security.WSPasswordCallback;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Component;


@Component

public class ClientPasswordCallback implements CallbackHandler

{

@Value("${webservice.wssecurity.accept.passwd}")

private String wssecurityAcceptId;

   public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException

   {

      WSPasswordCallback pc = (WSPasswordCallback)callbacks[0];

         pc.setPassword(wssecurityAcceptId);

   }

}



[consumer에 추가할 코드]


xxxxxClass {

@Value("${webservice.wssecurity.accept.id}")

private String wssecurityAcceptId;


try{

       JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

       factory.setServiceClass(PSFmsTOneossGetOrgCarPort.class);


       factory.setAddress("http://osb/ABCD/GetsdtddodoDfc");


       PSFmsTOneossGetOrgCarPort port = (PSFmsTOneossGetOrgCarPort)factory.create();


       Client client = ClientProxy.getClient(port);

       Endpoint cxfEndpoint = client.getEndpoint();

       Map<String, Object> outProps = new HashMap<String, Object>();

       

       outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);       

       outProps.put(WSHandlerConstants.USER, wssecurityAcceptId);

       outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);       

       outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName());


       WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);

       cxfEndpoint.getOutInterceptors().add(wssOut);

       

       위 코드 추가 후....

       위에서 생성된 port로 웹서비스 호출하면 끝

       

   }

   


   

   

ps. 물론 provider에도 인증 계정정보 셋팅 필요


       

          

'WebService' 카테고리의 다른 글

WSDL  (0) 2015.12.31
WS security  (0) 2014.01.29

+ Recent posts