기초에서 실무까지 XML 웹 서비스
책 정보
- 출판사 : 프리렉
- 출판사 책 사이트 : https://freelec.co.kr/book/catalogue_view.asp?page=2&UID=60#review
- 동영상 강의 사이트 : 동영상 강좌는 쓰레기 임.
- 출판년도(초판) : 2003-10-02
관련 사이트
저자 정보
- 신민철
용어 정리
- OMG : Object Management Group
- CORBA : Common Object Request Broker Architecture
- DCOM : Distributed Component Object Model
- RMI : Remote Method Invocation
- SOAP : Simple Object Access Protocol
- UDDI : Universal Description, Discovery and Integration
- WDSL : Web Service Description Language
- JWSDP : Java Web Service Developer Pack
- WS : Web Service
- DOM : Document Object Model
- SAX : Simple API for XML
- JAXP : Java API for XML Processing
- XSLT : XML Stylesheet Language Transformation
- JAX-RPC : Java API for XML-based RPC
- RPC : Remote Procedure Call
- WAR : Web Application Archives
- Marshalling : Java -> XML
- Unmarshalling : XML -> Java
- JAX-WS : Java API for XML Web Service
- PI : Processing Instruction, 프로세싱 지시자
- xsd : XML Schema Definition , xml 스키마 정의 파일 확장자
- xsi : XML Schema Instance
- URN : Uniform Resource Name (링크)
추가적인 용어
- Jabber : 관련 사이트#1
- WS-I :
약어
- ns : NameSpace
- tns : TargetNameSpace
- xs : xml schema
1장 . 웹서비스 개요
웹서비스 구성 하는 3가지 요소
- 웹 서비스 제공자 : Provider
- Publish : 서비스 공개
- 웹 서비스 중계자 : Broker
- Find : 서비스 검색
- 웹 서비스 소비자 : Consumer
- Bind : 특정 프로토콜을 이용해서 웹 서비스 시스템에 접속하는 것을 의미
UDDI : 공개 및 검색
- 웹 서비스의 공개(publish) 와 검색(find)를 위한 XML 저장소(registory)의 구현과 사용 방법을 표준화 한것
WDSL : 웹 서비스 기술 언어
- 표준화된 방식으로 웹 서비스의 인터페이스를 기술하는 XML 기술
SOAP : 단순 객체 접근 프로토콜
- 정보 교환을 위해 필요한 구조를 표준화 한 것
2장 . 웹 서비스 개발 S/W
JWSDP 소개
JWSDP란
- 자바에서 WS를 쉽게 구현 하기 위한 통합 개발 툴킷
JWSDP에 포함된 기술
- JAXP : Java API for XML Processing
- DOM , SAX 파서를 생성, XML 문서를 해석하기 위한 API를 제공
- 디폴트 파서 : Apache의 Xerces2를 사용
- XSLT : XSL 문서를 사용하여 XML 문서를 변환
- XSLT 엔진 : Apache의 Xalan 사용
- JAX-RPC : Java API for XML-base RPC
- SOAP 메시지에 근거한 RPC 방식의 WS C/S 개발위한 API
- 서버 개발 시
- WSDL 문서 자동 생성 기능
- WAR 파일 생성
- 클라이언트 개발 시
- WSDL 기반으로 stub 코드 생성
- 실행 시 내부적으로 JAXP 와 SAAJ를 이용하여 SOAP 메시지 생성, 전송, 해석하는 
 역할을 함.
- 현재는 JAX-WS 라고 함 (Java API for XML Web Services)
- JAXB : Java Architecture for XML Binding
- Java object <-> XML 문서 (마샬링 , 언마샬링)
- XML과 자바 코드 사이를 매핑하는 표준 방법을 제공
- JAXR : Java API for XML Registries
- 여러 가지 종류의 XML 저장소에 일관 되게 접근하여 정보를 저장하거나 검색할 수 있는
 표준 API를 제공
- XML 저장소 종류 의 예 : ebXML , UDDI 레지스트리
- SAAJ : SOAP with Attachments API for Java
- SOAP 메시지를 생성하고 , 전송하는 API
- JAXM : Java API for XML Messaging
- 비동기적인 웹 서비스 형태를 구현하기 위한 API 제공
- Tomact : 아파치 JSP 엔진
- Java WSDP Registry Server : 테스트용 UDDI 레지스트리 임.
3장 . XML 기초 문법
XML문서의 종류
- Well-Formed Document
- Valid Document
EBNF 표기법
- Exteneded Backus-Nar Form
- 예) XML 및 ASN.1 등을 정의 할때 사용함.
- 문법 형태
- Symbol ::= Expression
- Pattern 결합
- A? : 옵션, A 표현이 올 수도 있고 안 올 수도 있음
- A B : 순차, A 다음에 B
- A|B : 선택, A 혹은 B
- A-B : A는 오지만 B는 오지 말아야
- A+ : 한개 이상
- A* : 0 이거나 한개 이상
XML 문서 구조 및 선언
- 문서 : 서두 + 엘리멘트
- 서두 : PI
- <? ?> : 형식
- 엘리멘트 : 1개의 root 엘리멘트
- 문서 선언
- <?xml version="1.0" encoding="utf-8" standalone="yes"?>
- 이 선언 이전에 어떤 문자열도 올 수 없다. 주석도
- 그리고 <?xml 와 같이 받드시 <?xml 빈공백 올수 없다.
- 속성들
- version : 필수 1.0 , 생략 불가
- encoding : 문서의 인코딩 , 생략 가능 , 기본값 utf-8
- standalone : DTD나 schema 참조 여부 기본값, yes
5장 . XML 스키마
요약
- 스키마 선언 관련 (참조링크)
- xsi:noNamespaceSchemaLocation 속성 : 스키마 문서의 URI 경로를 명시 한다.
- xsi:noNamespaceSchemaLocation="http://www.example.com/MyData.xsd"
- xsi:schemaLocation 속성 : 네임스페이스와 스카마문서를 명시
- xsi:schemaLocation="urn:MyData http://www.example.com/MyData.xsd"
- URN : 독립적인 이름을 제공 부여 하기 위한 방법
- NID(Namespace ID) 와 NSS(Namespace Specific String) 으로 구성되어 있음
- 각 구분은 콜론(:)으로 함.
- 예)
- urn:한국-시민:000000-0000000
- urn:xmlgo:registory1
- Qname : qualified name , 적합한 이름
- namespace_part + local_part
- 예) <xsd:element>
스키마(Schema) 파일 구조
- 확장자 : xsd
- 형식
| 
<?xml version="1.0"?> 
  <!-- 외부 XML schema 문서의 참조에 관련된 엘리멘트 --> 
  <!-- 새로운 엘리멘트 및 속성을 선언하는 엘리멘트 -->  
</xsd:schema> | 
- 관련 엘리멘트들
- 외부 스키마 문서 참조용 엘리멘트들
- <include>
- <import>
- <redefine>
- <annotation>
- 새로운 엘리멘트 / 속성 선언관련 엘리멘트들
- <element>
- <attribute>
- <simpleType>
- <complexType>
- <group>
- <attributeGroup>
- <notation>
- <annotation>
- 주석 관련
- <!-- 기본 주석 -->
- <annoation>
| 
<annotation> 
(appinfo | documentation) * 
</annotation> 
<appinfo source="외부 참조 문서 경로">주석 내용</appinfo> 
<documentation source="외부 참조 문서 경로" xml:lang="사용된 언어"></documentation> | 
엘리멘트 선언
- <xsd:element> 요소를 사용
- 데이터만 갖는 엘리멘트 선언
- 형식 : <xsd:element name="엘리멘트 이름"
 minOccurs="최소횟수" maxOccurs="최대횟수" type="테이타 타입"/>
- 내용 : <title>책 제목</title>
- 자식을 갖는 엘리멘트
- 자식 과 속성을 갖는 엘리멘트
- 속성만 갖는 빈 엘리멘트
- 테이터 과 속성을 갖는 엘리멘트
- 글로벌 엘리멘트 참조
- null 값을 가지는 엘리멘트
- 테이터가 0 아니라 null 상태를 인것을 의미함
- nillable 속성값이 true 임
- 엘리먼트의 다형성
- substitutionGroup 속성을 값 지정하여 같은 것으로 취급하게 함.
엘리멘트 범위
- 글로벌 엘리멘트
- <xsd:schema> 하위에 선언
- 다른 곳에 참조(ref) 가능 함.
- 로컬 엘리멘트
- 다른 엘리멘트 하위에 선언
- 다른 곳에서 참조 불가능 함.
속성 선언
- 형식
| 
<attribute name="속성명" 
  use="optional|required" // 생략 가능 (기본값: optional) 
  default="기본값" // 속성 생략 기본 값 (use가 optional일 경우) 
  ref="참조할 전역 속성명" 
  type="테이타 타입" // build in 속성과 사용자 정의 속성 유형 모두 가능 
/> | 
- 속성도 선언위치에 따라 엘리멘트와 같이 글로벌과 로컬 속성을 구분되어 짐.
Data Type
- 분류 : 사용 용도에 따라
- Built-in Simple Type
- 스키마 언어에 미리 정의 되어 있음
- xsd:심플타입명 과 같은 형식
- User define Simple Type
- 사용자가 새로 정의하는 심플 타입
- Complex Type
- 사용자가 정의 복잡 타입
- 자식 엘리멘트 과 속성을 가지는 엘리멘트 선언시 사용
사용자 정의 Simple Type
공백으로 분리된 여러 데이터를 가지는 심플 타입 정의
- 형식 : <list itemType="심플 타입 이름">
- 문법
| 
<!-- 저자들 --> 
<xs:simpleType name="authors"> 
  <xs:list itemType="xsd:string"/> 
</xs:simpleType> 
<!-- 타입 사용 --> 
<xs:element name="authors" type="authors"/> | 
- 문서 사용예
| 
<authors>김하나 이두명 삼세기</authors> | 
여러 개의 심플 타입을 결합한 심플 타입 정의
- 설명 : <union> 하나 이상의 심플 타입을 결합하여 새로운 심플 타입을 정의
- 문법
| 
<union memberTypes="심플타입#1 심플타입#2"/> | 
- 사용예
| 
<!-- 스키마 파일 정의 --> 
<xs:simpleType name="OldPost"> 
  <xs:restriction base="xsd:int"> 
    <xs:length value="6"> 
  </xs:restriction> 
</xs:simpleType> 
<xs:simpleType name="NewPost"> 
  <xs:restriction base="xsd:int"> 
    <xs:length value="5"> 
  </xs:restriction> 
</xs:simpleType> 
<xs:simpleType name="post"> 
  <union memberTypes="OldPost NewPort"> 
</xs:simpleType> 
<!-- 타입 정의 --> 
<xs:element name="post" type="post"/> 
<!-- 사용예 --> 
<post>15171</post> | 
Wild Card
- 임의의 엘리멘트나 속성을 사용할 수 있도록 해주는 기능
<any>
- 엘리멘트 wild card
- 속성 설명
- namespace : 엘리멘트의 ns를 지정함. anyURI 혹은 아래 값이 올 수 있음.
- maxOccurs :
- minOccurs :
- processContents : 유효성 검사 여부. [ skip | strict | lax ]
- skip : 유효성 검사 하지 않음
- strict : 반드시 유효성 검사를 함.
- lax : 스키마 정보를 얻을 수 있을 경유만 유효성 검사
- namespace 의 anyURI 대신 올 수 있는 값들
| 
값 | 
설명 | 
| 
##any | 
어떤 ns에 속하는 엘리멘트든지 다 올 수 있다. | 
| 
##other | 
Target ns를 제외한 다른 ns에 속하는 엘리멘트만 올 수 있음. | 
| 
##targetNamespace | 
Target ns에 속하는 엘리멘트만 올 수 있음 | 
| 
##local | 
ns에 속하지 않는 엘리멘트만 올 수 있음. | 
<anyAttribute>
- 속성 wild card
- 속성 설명
- namespace : 사용 가능한 속성의 네임스페이스
- processContents : 유효성 검사 여부
- namespace 의 anyURI 대신 올 수 있는 값들
| 
값 | 
설명 | 
| 
##any | 
어떤 ns에 속하는 속성이든지 다 올 수 있다. | 
| 
##other | 
Target ns를 제외한 다른 ns에 속하는 속성만 올 수 있음. | 
| 
##targetNamespace | 
Target ns에 속하는 속성만 올 수 있음 | 
| 
##local | 
ns에 속하지 않는 속성만 올 수 있음. | 
스키마 문서의 결합
- <include> : 같은 ns를 가지는 문서의 결합
- <import> : 다른 ns를 가지는 문서의 결합
- <redefine> : 같은 ns나 ns가 없는 스키마 문서를 결합할 때 문서의 일부를 재 정의 할 때 사용
<include> 사용
- 문법
| 
<xs:include schemaLocation="$포함될_스키마_문서"/> | 
<import> 사용
- 문법
| 
<xs:import  
 namespace="$포함할_스키마_문서의_네임스페이스"  
 schemaLocation="$포함될_스키마_문서"/> | 
<redefine> 사용
- 문법
| 
<xs:redefine schemaLocation="$포함될_스키마_문서"/> 
<!-- 재정의할 내용 --> 
</xs:redefine> | 
Namespace 가지는 Schema
- 문법
| 
<?xml version="1.0"?> 
<xs:schema 
  targetNamespace="$네임스페이스_이름" 
  elementFormDefault="$엘리멘트의 네임스페이스_포함여부" 
  attributeFormDefault="$속성의 네임스페이스_포함여부" 
  xmlns="$네임스페이스_이름"> 
… 
</xs:schema> | 
- 속성들
- targetNamespace : 스키마 문서에서 정의되는 새로운 마크업 언어가 가질 네임스페이스를 
 지정해 주면 된다.
- elementFormDefault : 스키마 문서에 정의된 element들이 주어진 tns에 속할 것인지를 결정
- qualified : tns에 속함 (기본값)
- unqualified : tns에 속하지 않음
- attributeFormDefault : 스키마 문서에 정의된 속성들이 주어진 tns에 속할 것인지를 결정
- qualified : tns에 속함
- unqualified : tns에 속하지 않음(기본값)
- xmlns : 글로벌 선언을 로컬 엘리멘트 선언에 접두사(ns) 없이 참조 가능하도록 디폴트 ns 선언 해두는 것이다.
스키마 인스턴스 지정 방법
- 속성
- xsi:noNamespaceSchemaLocation : ns 없는 스키마 문서 URI를 지정함
- xsi:schemaLocation : ns가 있는 스키마 문서를 지정함
- 값 유형#1: “ns ~.xsd”
- 값 유형#1: “ns#1 ~.xsd ns#2 ~.xsd”
6장. SOAP 이해
SOAP 장점
- SOAP는 경량 프로토콜
- CORBA , RMI , DCOM에 비해
- 텍스트 기반 프로토콜
- OS 중립적
- HTTP 사용 가능
- 방화벽에 통과 가능
- 보안에 취약할 수 있음
SOAP 스펙
- 책의 버젼은 1.1
- 현재 버젼은 1.2
- 관련 사이트
- SOAP 메시지 구조(1.1) xml schema 문서 URL
- namespace : http://schemas.xmlsoap.org/soap/envelope
- SOAP 메시지 구조(1.2) xml schema 문서 URL
- namespace : https://www.w3.org/2003/05/soap-envelope/
SOAP 메시지 교환 모델
- 발신자과 수신자 모델
- sender , receiver : endpoint(종점)
- 단방향 이동
- Message Chain
- 단방향 메시지를 여러 개를 병합해서 더 복잡한 동작을 만들어 낼 수 있음.
- 중개자(intermdiary) 또는 Actor : 메시지를 발신하는 역할을 하는 종점
SOAP 메시지 구조
- Envolpe : 필수적
- 관련 엘리멘트 <Envolpe>
- Header : 선택적임
- 메시지 내용에 대한 추가적인 기능
- 트랙잭션 관리
- 발신자 인증
- 관련 엘리멘트 <Header>
- 자식 엔리멘트를 Header Entry라고 함.
- Header Entry의 Root 엘리멘트는 접두어 붙은 QName으로 기술 되어야 한다.
- 속성들 (1.1) 기준
- actor : 중개자(액터) 중 누가 헤더 엔트리를 처리할 것인가 지정
- 값 : actor URI
- mustUnderstand : 반드시 처리해야 됨을 지정
- 0 | 1 , 1 -> 반드시 처리 해야 함.
- 기본값은 0
- Body : 필수적
- 메시지 내용을 기술
- 관련 엘리멘트 : <Body>
- Root 엔리멘트는 QName으로 기술 되어야 함.
- <Fault> 엘리멘트
- Body 하위 엘리멘트
- 자식 엘리멘트 목록
- <faultcode> : 오류 코드 (1.1)
 네임스페이스 접두를 사용해야 함.
| 
오류 코드 | 
설명 | 
| 
env:VersionMismatch | 
요청 SOAP 메시지의 <Envelope> 엘리멘트의 네임스페이스 명이 잘못 되었음을 발경한 경우 | 
| 
env:MustUnderstand | 
mustUnderstand 속성값이 1인 헤더 엔트리를 중계자(액터)또는 최종 수신자가 처리하지 못한 경우 | 
| 
env:Client | 
클라이언트의 요청 SOAP 메시지 정보가 불충분하여 처리할 수 없는 경우 | 
| 
env:Server | 
서버에서 SOAP메시지를 처리하는 도중 오류가 발생하는 경우 | 
- <faultstring> : 오류에 대한 설명
- <faultactor> : 오류가 발생한 액터
- 중계자에서 오류가 발생한 경우 반드시 기술 되어야 함.
- <detail> : 오류에 대한 추가적인 정보 기술
SOAP 인코딩
- 특정 프로그래밍 언어로 작성된 프로그램에서 SOAP 메시지를 생성할 때 프로그램 언어의 테이터형을
 SOAP 메시지에서 표기하는 방법의미 한다.
- encodingStyle 속성
| 
// version 1.1 
// version 1.2 
<!-- 사용자 정의 속성 추가 --> | 
- 단순 타입 표기법
| 
<엘리멘트 xsi:type="xsd:$데이터_형">데이터</엘리멘트> | 
자바의 기본 형 과 xml schema 빌트인 형
| 
Java | 
XML Schema | 
| 
boolean | 
xsd:boolean | 
| 
byte | 
xsd:byte | 
| 
short | 
xsd:short | 
| 
int | 
xsd:int         | 
| 
long | 
xsd:long | 
| 
float | 
xsd:float | 
| 
double | 
xsd:double | 
| 
String | 
xsd:string | 
- 배열 표기법
| 
<!-- 문법 --> 
<접두사:메소드명> 
  <배열참조변수명 href="#배열식별자"/> 
</접두사:메소드명> 
<array id="배열식별자" xsd:type="enc:Array" enc:arrayType="데이터형[n]"> 
  <item>순번 0의 값</item> 
  <item>순번 1의 값</item> 
</array> | 
| 
<!-- 실제 사용예 --> 
<ns0:addBooks> 
  <arrayOfString_1 href="#bookarray"/> 
</ns0:addBooks> 
<array id="bookarray" xsi:type="enc:Array" enc:arrayType="xsd:string[3]"> 
  <item>book1</item> 
  <item>book2</item> 
  <item>book3</item> 
</array> | 
- 구조체 표기법 : class 형을 의미
| 
<!-- 문법 --> 
<env:Envelope 
   xmlns:구조체접두사=”구조체에_대한_네임스페이스_이름”> 
<접두사:메소드명> 
  <구조체인자명 href="#식별자"/> 
</접두사:메소드명> 
<구조체_엘리멘트명 id="식별자" xsd:type="구조체접두사:구조체명"> 
  <멤버변수명1 xsi:type=”테이터형”>값</멤버변수명1> 
  <멤버변수명2 xsi:type=”테이터형”>값</멤버변수명2> 
</구조체_엘리멘트명> | 
| 
<!-- 실제 사용예 --> 
<env:Envelope xmlns:ns1=”http://cosmoslight/struct”> 
<ns0:addBook> 
  <Book_1 href="#bookId01"/> 
</ns0:addBook> 
<book id="bookId01" xsi:type="ns1:Book"> 
  <title xsi:type=”xsd:string”>Hello WebService</title> 
  <price xsi:type=”xsd:int”>29000</price> 
</book> | 
SOAP 메시지를 전송하는 프로토콜
- SOAP과 전송 프로토콜을 접목시키는 작업을 binding이라고 함.
- HTTP 특징
- 연결 지향
- 무 상태
첨부 파일을 포함한 SOAP
- SOAP Messages with Attachments
- SOAP 메시지
- SOAP Part
- Attachment Part
8장. 웹서비스 시스템 개발
개발 순서
- 원격 프로시저를 정의하는 인터페이스 정의
- 패키지를 선언 해야 함.
- java.rmi.Remote 인터페이스를 상속 받아야 함.
- 반환형과 인자형은 JAX-RPC에서 지원하는 타입이어야 함.
- 원격 프로시저는 java.rmi.RemoteException을 반드시 thorws 해야 함.
| 
package hello; 
import java.rmi.*; 
public inteface HelloIF extends Remote{ 
   public String sayHello(String s) throws RemoteException; 
} | 
- 원격 인터페이스를 구현한 클래스 작성
- 구현 클래스의 접근 제어자는 public
- 인자가 없는 default 생성자가 꼭 있어야 함.
| 
package hello; 
public class HelloImpl implements HelloIF{ 
   public String sayHello(String s) throws RemoteException{ 
      return “hello “+s+” !”; 
   } 
} | 
- 배치 기술(DD) 작성
- web.xml 배치 기술자를 작성 : servlet 컨테이너에 배포시
- web.xml 기술되는 내용
- 세션에 대한 정보
- URL 매핑에 대한 정보
- 초기화에 대한 내용
- welcome file에 대한 정보
- web.xml 반드시 이어야 하는가 ?
- RMI interface 배치 기술자 작성 : jaxrpc-ri.xml 문서를 작성
| 
<?xml version="1.0"?> 
  version="1.0" 
  targetNamespaceBase="$원격_프로시저의_네임스페이스명" 
  typeNamespaceBase="$구조체에_대한_네임스페이스명"> 
  <endport  
     name="$웝서비스_시스템_이름"  
     interfae="$원격_인터페이스명" 
     implmentation="$구현_클래스명"/> 
  <endpointMapping 
     endpointName="$웝서비스_시스템_종정명" 
     urlPatter="$URL_경로"/> 
</webService>  | 
- targetNamespaceBase : 원격프로시저에 대한 네임스페이스명
- typeNamespaceBase : 구조체에 대한 네임스페이스명
- <endpoint> : 웹서비스 시스템의 원격 인터페이스와 구현 클래스 이름 기술
 웹 서비스 시스템 이름 기술
- name : 웹서비스 시스템 이름
- <endpointMapping>
- endpointName : endpoint의 name 참조
- war 파일 생성 : 임시용
- Tie 클래스 와 WSDL 문서 생성
- wsdeploy.bat :
- 파일 위치 : jaxrpc 의 bin 디렉토리 위치
- 역할
- tie 클래스 생성
- WSDL 문서 자동 생성하여 WAR파일에 추가함.
- 명령어 : wsdeploy -o 결과.war 임시용.war
- WAR 패키징 및 배치
JAX-RPC에서 지원하는 Data Type
- 자바 기본 데이터 타입(Primitives Type)
- boolean
- byte
- short
- int
- long
- float
- double
- j2se sdk 클래스
- java.lang
- Boolean
- Byte
- Short
- Integer
- Long
- Float
- Double
- String
- java.math
- BigDecimal
- BigInteger
- java.util
- Calender
- Date
- Collection 타입의 클래스
- java.util.List
- ArrayList
- LinkedList
- Stack
- Vector
- java.util.Map
- HashMap
- Hashtable
- Properties
- TreeMap
- java.util.Set
- HashSet
- TreeSet
- Arrays
- 1차원 배열 뿐만 아니라 다차원 배열도 지원함.
- 사용자 정의 클래스 조건
- public 디폴트 생성자를 반드시 가져야 함
- java.rmi.Remote 인터페이스를 직접 또는 간접적으로 구현해서는 안됨.
- 모든 필드의 테이터 형은 JAX-RPC가 지원하는 타입으로 구성되어야 함
- 필드는 final 또는 transient로 선언되면 안됨
- 필드는 private 또는 protected 접근 지정자를 가져야 함
- 필드에 대한 public getter/setter 메소드를 가져야 한다.
9장. 웹 서비스의 명세화
목적
- 웹 서비스 제공자는 웹 서비스의 기능 WSDL로 문서로 작성해서 웹 서비스 소비자가 다운로드 받을 수 있도록 웹 서버에 저장 하고 WSDL 문서의 다운로드 URL을 UDDI 레지스트리에 공개 해야 함.
- WSDL 문서는 웹 서비스 코드로 부터 자동 생성하는 도구를 사용하여 작성됨.
WSDL 소개
- CORBA의 IDL와 비슷함.
WDSL 문서의 구조
- 도식
| 
<definitions> 
  <types> 
  인자 및 리턴값에서 사용될 복합 타입 기술, [ 0 or 1 ] 
  </types> 
  <message> 
  인자 및 리턴값을 기술, [ 1 or n ] 
  </message> 
  <portType> 
    <operation> 
      원격 프로시저 기술, [ 1 or n ] 
    </operation> 
    [1 or n] 
  </portType> 
  <binding> 
    호출에 사용되는 프로토콜에 대한 정보 기술, [1 or n] 
  </binding> 
  <service> 
    <port> 
    웹 서비스 시스템의 URL(종점:endpoint) 기술, [1 or n]  
    </port> 
    [1 or n] 
  </service> 
</definitions> 
<!-- 부수적인 엘리멘트 들 --> 
<documentation> 
  사람이 읽기 위한 주석 , [0 or n] 
</documentation> 
<import> 
  외부 파일에 정의되어 있는 내용을 참조, [0 or n] 
</import> | 
<definitions> 엘리멘트
- WSDL에서 사용되는 네임스페이스들을 선언
- 속성
- name : WSDL 문서의 내부 이름을 기술
- targetNamespace : WSDL에서 정의하는 원격 프로시저에 대한 ns 이름 기술
- 관례적으로 많이 사용되는 네임스페이스
| 
접두사 | 
네임스페이스명 | 
설명 | 
| 
wsdl | 
http://schemas.xmlsoap.org/wsdl/ | 
WSDL에 대한 네임 스페이스 | 
| 
soap | 
http://schemas.xmlsoap.org/wsdl/soap/ | 
SOAP 바인딩에 대한 네임 스페이스 | 
| 
http | 
http://schemas.xmlsoap.org/wsdl/http/ | 
HTTP GET & POST 바인딩에 대한 네임스페이스 | 
| 
mime | 
http://schemas.xmlsoap.org/wsdl/mime/ | 
MIME 바인딩에 대한 네임스페이스 | 
| 
soapenc | 
http://schemas.xmlsoap.org/soap/encoding | 
SOAP 1.1 인코딩에 대한 네임스페이스 | 
| 
soapenc | 
http://www.w3.org/2003/05/soap-encoding | 
SOAP 1.2 인코딩에 대한 네임스페이스 | 
| 
soapenv | 
http://schemas.xmlsoap.org/soap/envelope | 
SOAP 1.1 에 대한 네임스페이스 | 
| 
soapenv | 
http://www.w3.org/2003/05/soap-envelope | 
SOAP 1.2 에 대한 네임스페이스 | 
| 
xsi | 
http://www.w3.org/2000/10/XMLSchema-instance | 
XML Schema 인스턴스에 대한 네임스페이스 | 
| 
xsd | 
http://www.w3.org/2000/10/XMLSchema | 
XML Schema 에 대한 네임스페이스 | 
| 
tns | 
(various) | 
현재 WSDL 문서에 정의된 내용에 대한 네임스페이스 | 
<message> 엘리멘트
- 원격 프로시저의 인자와 반환값에 대한 정보를 기술함.
- 속성 :
- name : 구분하기 위한 이름, 필수, <operation> 에서 참조함.
- <part> : 하위 엘리멘트, 인자 및 반환 값에 대한 정보를 기술
- 속성
- name : 변수 이름
- type : 데이터 타입 , Qname형태로 기술
- 문법
| 
<message name="$메시지_이름"> 
  <part name="$인자_반환_변수이름" type="$데이터타입"/> 
</message> | 
<types> 엘리멘트
- 원격 프로시저의 인자 및 반환값에 사용되는 복합 타입을 기술하기 위한 엘리멘트
- 복합 타입을 사용하지 않으면 생략가능
- 기본 문법
| 
<types> 
  <schema 
   targetNamespace="$복합_타입_ns명" 
   xmlns:tns="$복합_타입_ns명" 
    <complexType name="$복합타입명"> 
     ~ 
    </complexType> 
  </schema> 
</types> | 
- 사용예
- 배열 정의
| 
<complexType name="$array_name"> 
  <complexContent> 
     <restriction base="soap-enc:Array"> 
        <attribute ref="soap-enc:arrayType" wsdl:arrayType="$data_type[]"/> 
     </restriction> 
  </complexContent> 
</complexType> | 
- 구조체 정의 : 자바의 클래스에 해당됨
| 
<complexType name="$class_name"> 
  <sequence> 
    <element name="member_var_name" type="data_type"/> 
    <element name="member_var_name" type="data_type"/> 
  </sequence> 
</complexType> | 
<portType>과 <operation> 엘리멘트
- <portType> : 자바의 인터페이스에 해당함.
- 하위에 여러 개의 <operation>이 존재 할 수 있음.
- 속성
- name : 필수, 일반적으로 인터페이스명 기술 됨. <binding>에서 참조함
- <operation> : 자바의 메소드에 해당함
- name : 원격 프로시저 즉 메소드명이 기술됨.
- parameterOrder : 인자들의 순서를 지정함
 <message>의 <part> 들의 이름을 순서 대로 적는다.
- <input> 엘리멘트
- 인자 정보를 기술
- message 속성에 <message> 엘리멘트 참조를 기술 함.
- <output> 엘리멘트
- 반환 값 정보를 기술
- message 속성에 <message> 엘리멘트 참조를 기술 함.
- 문법
| 
<portType name="$interfaceName"> 
  <operation name="$methodName" parameterOrder="$para1 $para2"> 
     <input message="$message_elm_name"/> 
     <output message="$message_elm_name"/> 
  </operation> 
  ... 
</portType> | 
<binding> 엘리멘트
- 웹 서비스 시스템과 웹 서비스 소비자인 클라이언트 간의 통신 방법을 기술하는 엘리멘트
- 바인딩 이란 웹 서비스 시스템에 접속하는 것
- <binding> 의 속성
- name : 바인딩 이름, 필수, <service>에 참조됨
- type : <portType>의 name을 기술 함.
- 바인딩의 종류
- SOAP 바인딩
- HTTP 바인딩
- MIME 바인딩
- SOAP 바인딩 작성 문법
- 문법
| 
<binding name="$bindingName" type="$portTypeName"> 
  <soap:binding 
     style="rpc|document"/> 
  <operation name="$operationName"> 
     <soap:operation soapAction="HTTP SOAPAction Header Value"/> 
     <input> 
        <soap:body namespace="$operation_input_ns_name" 
          use="encoded" 
          encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> 
     </input> 
     <output> 
        <soap:body namespace="$operation_output_ns_name" 
          use="encoded" 
          encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> 
     </output> 
     <fault> 
        <soap:body namespace="$fault_ns_name" 
          use="encoded" 
          encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> 
     </fault> 
  </operation> 
</binding> | 
- <soap:binding>
- soap 는 xmlns:soap=”http://schemas.xmlsoap.org/wsdl/soap” 의 네임 스페이스 임
- 하위 속성
- transport : 전송 프로토콜의 네임 스페이스 이름을 기술
- style : 전달되는 SOAP 메시지의 형태를 기술
- rpc : 프로시저명과 인자를 포함하고 있음
- document : 단순 정보 전달용(기본값)
- <operation>
- name 속성 : <portType> 하위의 <operation>의 name
- <soap:operation>
- soapAction 속성
- HTTP를 전송용 프로토콜 사용할때는 반드시 언급해야 함.
- <input>
- 원격 프로시저의 파라미터에 대한 네임스페이스과 인코딩 방법을 기술
- <output>
- 원격 프로시저의 반환값에 대한 네임스페이스과 인코딩 방법을 기술
- <fault>
- 오류값을 표현에 대한 네임스페이스과 인코딩 방법을 기술
- <soap:body>의 속성
- namespace : 호출 및 결과를 표현하기 위한에 대한 네임스페이스 기술
- use : 인코딩 방법을 별도로 사용하는지에 대한 여부를 기술 (literal | encoded)
- literal : 인코딩 없이 그대로 전달
- encoded : encodingStyle에 선언된 방식을 사용한다는 뜻
- encodingStyle : 인코딩 방식
- HTTP 바인딩 작성 문법
- 세가지 방식
- HTTP GET 방식 - URL 인코딩 방식
- HTTP GET 방식 - URL 대체 방식
- HTTP POST 방식
- 필요하면 정리
- MIME 바인딩 작성 문법
- 필요하면 정리
<service>, <port> 엘리멘트
- 웹 서비스 시스템에 대한 URL 정보를 기술
- 작성 문법
| 
<service name="$WebServiceName"> 
  <!-- SOAP 바인딩 종점 URL 정보 --> 
  <port name="$PortName" bindig="$REF_bindingName"> 
     <soap:address location="$WebService_URL"/> 
  </port> 
  <!-- HTTP 바인딩 종점 URL 정보 --> 
  <port name="$PortName" bindig="$REF_bindingName"> 
     <http:address location="$WebService_URL"/> 
  </port> 
</service> | 
- 속성 및 하위 요소 설명
- service.name : 웹 서비스명을 기술
- port.name : 포트 이름을 기술
- port.binding : <binding>의 이름 참조
- <soap:address> : 웹서비스가 soap 바인딩을 이용할 때 정보
- <http:address> : 웹서비스가 http 바인딩을 이용할 때 정보
- <soap:address> 나 <http:address>의 location :
- 실제 Web 서비스의 URL 기술함.
자동 생성된 WSDL 문서 보기
- 자동 생성 시
- <soap:address location="REPLACE_WITH_ACTUAL_URL"/> 부분을 수정해 주어야 한다.
- JAX-RPC에 제공하는 도구
- wsdeploy.bat : tie 클래스 생성및 WSDL 문서 자동 생성하여 WAR 파일에 추가함
- wscompile.bat : 웹 서비스 시스템의 인터페이스 및 구현 클래스 생성
- 관련 : config.xml 필요 wsdl 문서와 동일한 위치
- wscompile -import -keep config.xml
- keep : 소스 파일 생성하는 옵션
- config.xml
| 
<?xml version="1.0" encoding="UTF-8"?> 
   <wsdl location="webservice.wsdl" packageName="book"/> 
</configuration> | 
- 속성
- location : wsdl 문서의 위치
- packageName : 웹 서비스 시스템의 인터페이스 및 구현 클래스가 속하는 패키지를 지정함
12장. 웹 서비스 클라이언트 개발
JAX-RPC 클라이언트 호출 모델
- 정적 스텁 호출 모델
- 정적 스텁을 이용해서 원격 프로시저를 호출하는 모델
- 정적 스텁 : WSDL 문서를 이용해서 수동으로 생성된 스텁 클래스
- 동적 프록시 호출 모델
- 동적 프록시 하여 수동으로 스텁클래스를 생성하지 않고 호출하는 함.
- 동적 프록시 : 동적으로 생성되는 프록시 웹 서비스 시스템과 웹 서비스 클라이언트를 연결해
 주는 스텁 클래스를 말함.
- 동적 호출 인터페이스 모델
- 클라이언트 측에서 원격 인터페이스명을 알지 못해도 동적으로 원격 메서드를 호출할 수
 있도록 해주는 모델
- Call 객체를 이용함
- DII(동적 호출 인터페이스) : 동적으로 호출 가능한 인터페이스
웹 서비스 시스템 실행 확인
- 해당 URL로 시험 하여 결과 나타남.
- stub을 이용하기 위한 기본 정보 WSDL 문서에 있음 **
정적 stub 호출 모델
- stub 클래스 생성
- wscompile.bat 이라는 도구 사용 (jswdp의 jaxrpc/bin에 존재)
- 생성 문법
- wscompile -gen:client -d $output_dir config.xml
- -gen:client : 클라이언트 측 스텁을 생성 시키라는 option
- -d : 생성된 스텁을 저장할 디렉토리, 생략하면 현재 디렉토리 (.)
- config.xml 문서 필요 다음 내용을 포함 함.
- wsdl 문서를 다운로드 받는 URL
- location 속성 : 시스템 종점 URL 이나 UDDI 에서 구할 수 있음
- stub 클래스가 포함될 Package명
- packageName 속성 : 시스템 종점 URL에서 확인 가능
- 클라이언트 프로그램 소스 작성 순서
- 1 - 웹 서비스 시스템의 구현 객체를 참조하는 객체를 생성
- 관련 클래스 명은 <service>엘리멘트의 name 속성값 + _Impl 임
| 
$(wsdl_service_name)_Impl.class | 
- 2 - stub 객체 얻기
| 
Stub stub = (Stub)webServiceRef.get$PortName(); | 
- 3 - 원격 인터페이스 객체로 형 변환
- 4 - 원격 프로시저 호출
- 전체 소스
| 
package hello; 
import javax.xml.rpc.Stub; 
public class HelloClient{ 
  public static void main(String[] args){ 
     //1 - 웹 서비스 시스템 구현 객체 생성 
     WebService_Impl websvc = new WebService_Impl(); 
     //2 - stub 객체 얻기 
     Stub stub = (Stub) websvc.getHelloIFPort(); 
     //3 - 원격 인터페이스 객체로 형 변환 
     HelloIF hello = (HelloIF)stub; 
     //4 - 원격 프로시저 호출 
     String greet = hello.sayHello("cosmoslight"); 
     System.out.println(greet); 
  } } | 
동적 Proxy 호출 모델 - 소스 작성
- ServiceFactory 객체 생성
- 관련 패키지 : javax.xml.rpc
- ServiceFactory 클래스 추상화 클래스 임.
- Service 객체 생성
- javax.xml.rpc.Service 인터페이스형 객체를 생성
- 생성시 필요한 정보
- wsdl 다운로드 URL
- 웹 서비스 네임스페이스명 - wsdl 문서에 있음
- <definitions>의 targetNamespace
- 웹 서비스명 - wsdl 문서에 있음
- <service>의 name
- stub 객체 생성하기
- 원격 인터페이스 객체로 형 변환
- 원격 프로시저 호출
- 전체 소스
| 
package hello; 
import javax.xml.rpc.*; 
import javax.xml.namespace.*; 
import java.net.*; 
public class HelloClient{ 
  public static void main(String[] args){ 
     //1 - ServiceFactory 객체 생성 
     ServiceFactory svcFactory = ServiceFactory.newInstance(); 
     //2 - Service 객체 생성 
     URL wsdlurl = new URL( 
         "Webservice");  
     Service service =  
         svcFactory.createService(wsdlurl,serviceQName); 
     //3 - stub 객체 생성하기 
     QName portQName = new QName("http://localhost:8080/hello/webservice/wsdl/webservice" 
         ,"HelloIFPort") 
     Stub stub = (Stub) service.getPort(portQName,hello.HelloIF.class); 
     //4 - 원격 인터페이스 객체로 형 변환 
     HelloIF hello = (HelloIF)stub; 
     //5 - 원격 프로시저 호출 
     String greet = hello.sayHello("cosmoslight"); 
     System.out.println(greet); 
  } } | 
동적 호출 인터페이스 모델 - 소스 작성
- ServiceFactory 객체 생성
- Service 객체 생성
- Call 객체 생성의 속성값 지정
| 
구분 | 
관려 메소드 | 
설명 | 
| 
종점 지정 | 
call.setTargetEndpointAddress("종점URL") | |
| 
SOAPACTION 사용 여부 | 
call.setProperty( 
 Call.SOAPACTION_USE_PROPERTY, 
 new Boolean(true) or new Boolean(false));  | 
false : 사용 안함 (기본값) 
true  : 사용함 (일반적) | 
| 
SOAPACTION URI 지정 | 
call.setProperty("URI"); | 
SOAPACTION을 사용할 경우에 URI 경로가 없다면 “”로 지정해야 함. | 
| 
SOAP 메시지 인코딩 지정 | 
call.setProperty( 
 "javax.xml.rpc.encodingstyle.namespace.uri", 
 "http://schemas.xmlsoap.org/soap/encoding/"); | 
기본 인코딩을 soap 인코딩으로 지정 | 
| 
원격 프로시저 이름 지정 | 
call.setOperationName( 
  new QName("원격 프로시저 네임스페이스명", 
    "원격 프로시저명")); | 
원격 프로시저명은 WSDL 문서에 있는 <operation> 엘리멘트의 name 속성값과 동일해야 함 | 
| 
원격 프로시저 인자형 지정  | 
call.addParameter("인자형", 
    "인자형"), 
  ParameterMode.IN); | 
addParameter는 인자 개수만큼 존재 해야 함. 
인자명은 WSDL 문서에 있는 <part> 엘리멘트 name 속성명과 동일 해야 함. 
인자형은 XML 스키마 언어의 빌트인 SympleType이 와야 함. | 
| 
원격 프로시저 반환형 
지정 | 
    "반환형")); | 
원격 프로시저의 반환형 지정 | 
- Call 객체를 통해 원격 메소드 호출
소스 
| 
package hello; 
import javax.xml.rpc.*; 
import javax.xml.namespace.*; 
import java.net.*; 
public class HelloClient{ 
  public static void main(String[] args){ 
     //1 - ServiceFactory 객체 생성 
     ServiceFactory svcFactory = ServiceFactory.newInstance(); 
     //2 - Service 객체 생성 
     URL wsdlurl = new URL( 
         "Webservice");  
     Service service =  
         svcFactory.createService(wsdlurl,serviceQName); 
     //3 - call 객체 생성하기 및 속성값 지정 
     QName portQName = new QName("http://localhost:8080/hello/webservice/wsdl/webservice" 
         ,"HelloIFPort") 
     Call call = service.createCall(portQName); 
     call.setProperty(Call.SOAPCTION_USE_PROPERTY,new Boolean(true)); 
     call.setProperty(Call.SOAPCTION_URI_PROPERTY,""); 
     call.setProperty("javax.xml.rpc.encodingstyle.namespace.uri", 
          "http://schemas.xmlsoap.org/soap/encoding/"); 
          "sayHello")); 
     call.addParameter("String_1" 
          ,ParameterMode.IN); 
     call.setReturnType("String_1" 
     //4 - Call 객체를 통해 원격 메소드 호출 
     Object params[] = {new String("cosmoslight")}; 
     //5 - 원격 프로시저 호출 
     String greet = (String) call.invoke(params); 
     System.out.println(greet); 
  } } | 
SAAJ를 이용한 클라이언트
| 
import java.io.*; 
import java.util.*; 
import javax.xml.parsers.*; 
import org.w3c.dom.*; 
import org.xml.sax.*; 
import javax.xml.soap.*; 
import javax.xml.transform.dom.*; 
public class HelloClient { 
  /// Field 
  /// Constructor 
  /// Method 
  public static void main(String args[]) { 
    try { 
      //DOM 파서 생성 
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
      factory.setNamespaceAware(true);   
      DocumentBuilder parser = factory.newDocumentBuilder(); 
      //요청 SOAP 메세지 DOMSource 생성 
      String sendMessage =  
        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + 
        "<env:Envelope " + 
        "  xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\"" + 
        "  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" + 
        "  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" + 
        "  xmlns:enc=\"http://schemas.xmlsoap.org/soap/encoding/\"" + 
        "  xmlns:ns0=\"http://localhost:8080/hello/webservice/wsdl/webservice\""  + 
        "  env:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" + 
        "  <env:Body>" + 
        "    <ns0:sayHello>" + 
        "      <String_1 xsi:type=\"xsd:string\">길동</String_1>" + 
        "    </ns0:sayHello>" + 
        "  </env:Body>" + 
        "</env:Envelope>";   
      StringReader reader = new StringReader(sendMessage); 
      InputSource is = new InputSource(reader); 
      Document document = parser.parse(is); 
      DOMSource requestSource = new DOMSource(document); 
      //SOAPMessage 객체 생성 
      MessageFactory messageFactory = MessageFactory.newInstance(); 
      SOAPMessage requestSoapMessage = messageFactory.createMessage();   
      SOAPPart requestSoapPart = requestSoapMessage.getSOAPPart();   
      requestSoapPart.setContent(requestSource); 
      //SOAPConnection 객체 생성 
      SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance(); 
      SOAPConnection connection = scf.createConnection(); 
      //요청 SOAP 메세지 보내고, 응답 SOAP 메세지 받기 
      SOAPMessage responseSoapMessage = connection.call(requestSoapMessage,  
                                    "http://localhost:8080/hello/webservice"); 
      //응답 결과 얻기 
      SOAPPart responseSoapPart = responseSoapMessage.getSOAPPart(); 
      SOAPEnvelope se = responseSoapPart.getEnvelope(); 
      SOAPBody sb = se.getBody(); 
      Name name = se.createName("sayHelloResponse","ns0", 
                   "http://localhost:8080/hello/webservice/wsdl/webservice");  
      Iterator iterator = sb.getChildElements(name); 
      SOAPElement eSayHelloRespons = (SOAPElement) iterator.next();  
      name = se.createName("result"); 
      iterator = eSayHelloRespons.getChildElements(name); 
      SOAPElement eResult = (SOAPElement) iterator.next(); 
      iterator = eResult.getChildElements(); 
      javax.xml.soap.Text text = (javax.xml.soap.Text) iterator.next(); 
      System.out.println(text.getValue()); 
    } catch(Exception e) { 
      e.printStackTrace();   
    }    
  } 
} | 


댓글 없음:
댓글 쓰기