12.07.2015 Views

Anyframe CXF Plugin

Anyframe CXF Plugin

Anyframe CXF Plugin

SHOW MORE
SHOW LESS
  • No tags were found...

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Anyframe</strong> <strong>CXF</strong> <strong>Plugin</strong>Version 4.5.2저작권 © 2007-2010 삼성SDS본 문서의 저작권은 삼성SDS에 있으며 <strong>Anyframe</strong> 오픈소스 커뮤니티 활동의 목적하에서 자유로운 이용이 가능합니다. 본 문서를 복제, 배포할경우에는 저작권자를 명시하여 주시기 바라며 본 문서를 변경하실 경우에는 원문과 변경된 내용을 표시하여 주시기 바랍니다. 원문과 변경된문서에 대한 상업적 용도의 활용은 허용되지 않습니다. 본 문서에 오류가 있다고 판단될 경우 이슈로 등록해 주시면 적절한 조치를 취하도록하겠습니다.


I. Installation ................................................................................................................ 11. Install a <strong>CXF</strong> <strong>Plugin</strong> ............................................................................................ 2II. Web Services ............................................................................................................ 32. Overview .......................................................................................................... 42.1. Web Services 개념 .................................................................................. 42.1.1. Architecture ................................................................................. 42.1.2. SOAP(Simple Object Access Protocol) ............................................... 52.1.3. WSDL(Web Services Description Language) ........................................ 52.1.4. 기술 표준 ................................................................................... 72.2. 구현 기술 .............................................................................................. 82.2.1. JAX-RPC vs. JAX-WS ...................................................................... 82.2.2. XML Schema ............................................................................... 92.2.3. 기타 구현 기술 .......................................................................... 102.3. Web Services Framework ........................................................................ 112.3.1. Web Services Framework 종류 ...................................................... 112.3.2. Apache <strong>CXF</strong> 특징 ........................................................................ 112.4. Tools ................................................................................................. 123. Databinding .................................................................................................... 133.1. JAXB Databinding .................................................................................. 133.1.1. Server Configuration .................................................................... 143.1.2. 유의 사항 ................................................................................. 163.2. Aegis Databinding ................................................................................. 163.2.1. Server Configuration .................................................................... 173.2.2. Client Configuration ..................................................................... 183.3. MTOM Databinding ................................................................................ 193.3.1. Server Configuration .................................................................... 193.3.2. Client Configuration ..................................................................... 203.3.3. 참고 - MTOM에 관련된 내용 ......................................................... 213.4. Resources ........................................................................................... 224. JAX-WS Frontend .............................................................................................. 244.1. Web Service 작성 .................................................................................. 254.1.1. Samples ................................................................................... 254.2. Spring Configuration XML - jaxws:endpoint tag 사용 ...................................... 264.2.1. Samples ................................................................................... 264.3. Spring Configuration XML - jaxws:server tag 사용 ......................................... 274.3.1. Samples ................................................................................... 284.4. Server: JAX-WS Frontend API 사용 ............................................................. 294.4.1. Samples ................................................................................... 294.5. Spring Configuration XML - jaxws:client tag 사용 .......................................... 294.5.1. Samples ................................................................................... 294.6. Client: JAX-WS Frontend API 사용 ............................................................. 304.6.1. Samples ................................................................................... 304.7. Annotation 작성 .................................................................................... 314.7.1. @WebService (javax.jws.WebService) ............................................... 314.7.2. @WebParam (javax.jws.WebParam) ................................................. 324.7.3. @WebMethod (javax.jws.WebMethod) .............................................. 324.7.4. @OneWay (javax.jws.OneWay) ........................................................ 334.7.5. @WebResult (javax.jws.WebResult) ................................................. 334.7.6. Samples ................................................................................... 334.8. [참고] Spring Configuration XML Schema .................................................... 354.9. Resources ........................................................................................... 355. Simple Frontend .............................................................................................. 375.1. Web Services 작성 ................................................................................ 375.1.1. Samples ................................................................................... 375.2. Server: Simple Frontend API 코드 사용 ...................................................... 38ii


<strong>Anyframe</strong> <strong>CXF</strong> <strong>Plugin</strong>5.2.1. Samples ................................................................................... 385.3. Spring Configuration XML - simple:server tag 사용 ........................................ 395.3.1. Samples ................................................................................... 395.4. Client: Simple Frontend API 코드 사용 ....................................................... 405.4.1. Samples ................................................................................... 405.5. Spring Configuration XML - simple:client tag 사용 ......................................... 415.5.1. Samples ................................................................................... 415.6. [참고] Spring Configuration XML Schema .................................................... 415.7. Resources ........................................................................................... 426. Asynchronous Invocation ................................................................................... 436.1. Server Configuration .............................................................................. 436.1.1. Samples ................................................................................... 436.2. Client Configuration ............................................................................... 466.2.1. Samples ................................................................................... 476.3. Resources ........................................................................................... 487. RESTful Services ............................................................................................. 497.1. JAX-RS 활용한 RESTful 서비스 구현 .......................................................... 507.1.1. Server Configuration .................................................................... 517.1.2. Client Configuration ..................................................................... 527.2. HTTP Binding(JRA) 활용한 RESTful 서비스 구현 ........................................... 557.2.1. Server Configuration .................................................................... 557.2.2. Client Configuration ..................................................................... 567.2.3. 유의 사항 ................................................................................. 597.3. HTTP Binding(Naming Convention) 활용한 RESTful 서비스 구현 ....................... 627.3.1. Server Configuration .................................................................... 627.3.2. Client Configuration ..................................................................... 637.4. JAX-WS Provider/Dispatch API 활용한 RESTful 서비스 구현 ............................. 677.4.1. Server Configuration .................................................................... 677.4.2. Client Configuration ..................................................................... 687.5. [참고] Spring Configuration XML Schema .................................................... 717.6. Resources ........................................................................................... 718. WAS(Web Application Server) Configuration ........................................................... 738.1. Tomcat ............................................................................................... 738.1.1. Tomcat 5.5.23 ........................................................................... 738.2. JEUS .................................................................................................. 738.2.1. JEUS 5 ..................................................................................... 738.2.2. JEUS 6 ..................................................................................... 738.3. WebLogic ............................................................................................. 738.3.1. WebLogic 9.2, 10.1 .................................................................... 73iii


I.Installation웹 서비스 구현을 위해 많이 사용하고 있는 오픈소스 프레임워크에는 Apache <strong>CXF</strong>, Apache Axis/Axis2, Spring WebServices 등등 여러가지가 존재한다. <strong>CXF</strong> <strong>Plugin</strong>은 이 중 Apache <strong>CXF</strong> [http://cxf.apache.org/]의 기본 활용 방법을가이드하기 위한 샘플 코드와 이 오픈 소스를 활용하는데 필요한 참조 라이브러리들로 구성되어 있다.


1.Install a <strong>CXF</strong> <strong>Plugin</strong>본 장에서는 <strong>CXF</strong> <strong>Plugin</strong> 설치로 생성된 샘플 코드를 중심으로 <strong>CXF</strong>를 활용한 Web Service 구현 방법에대해 보다 상세히 다루게 될 것이다.본 장의 내용을 본격적으로 시작하기에 앞서 로컬 PC에 <strong>CXF</strong> <strong>Plugin</strong>을 설치해 보도록 하자. (본 장에서는 <strong>CXF</strong> <strong>Plugin</strong> 설치 절차만을 간략히 소개하므로 보다 자세한 <strong>Plugin</strong> 설치에 대해서는 본 문서 내의 <strong>Anyframe</strong> 기반 개발 환경 구성 [http://dev.anyframejava.org/docs/anyframe/ide/1.0.0/reference/htmlsingle/ide.html#cli_maven]을 참조하도록 한다.)1. <strong>CXF</strong> <strong>Plugin</strong> 설치는 Maven 기반으로 진행되므로, 본 문서 내의 Maven 설치및 환경 설정 [http://dev.anyframejava.org/docs/anyframe/ide/1.0.0/reference/htmlsingle/ide.html#installation_maven_configuration]을 참조하여 설치 환경이 제대로 셋팅되었는지 확인한다. 또한, <strong>CXF</strong> <strong>Plugin</strong>을 설치하기 위해서는 모든 <strong>Plugin</strong>의 기반이 되는 Foundation <strong>Plugin</strong>이 설치되어 있어야 한다. Foundation <strong>Plugin</strong> 설치가 필요한 경우에는 Foundation <strong>Plugin</strong> 설치하기 [http://dev.anyframejava.org/docs/anyframe/plugin/foundation/4.6.0/reference/htmlsingle/foundation.html#foundation_installation]를 참조하도록 한다.2. Command 창에서 샘플 프로젝트의 위치로 이동한 후, db/hsqldb/start.cmd (or start.sh)을 실행시킴으로써 샘플 DB를 시작시킨다. (기본적으로 제공되는 HsqlDB가 아닌 다른 DB를 활용하고자 하는경우에는 본 문서 내의 DB 변경 [http://dev.anyframejava.org/docs/anyframe/ide/1.0.0/reference/htmlsingle/ide.html#cli_maven_db]을 참조하도록 한다.)3. Command 창에서 다음과 같이 명령어를 입력하여 cxf plugin을 설치한다.mvn anyframe:install -DpluginName=cxf4. Command 창에서 다음과 같이 명령어를 입력한 후, Jetty Server가 정상적으로 시작되었으면 브라우저를 통해 cxf plugin이 정상적으로 설치되었는지 확인한다. (생성된 샘플 프로젝트명이 myproject인경우 브라우저 주소창에 http://localhost:8080/myproject를 입력한다.)mvn clean jetty:run위 그림에서 보이는 바와 같이 왼쪽 메뉴에 Foundation Sample 메뉴 외에 <strong>CXF</strong> Sample 메뉴가 추가된 것을 확인할 수 있을 것이다. <strong>CXF</strong> Sample 메뉴를 클릭하여 <strong>CXF</strong>로 구현된 웹 서비스를 통해 목록조회 기능이 수행되는 모습과 생성된 WSDL을 확인해 보도록 하자.2


II.Web Services<strong>Anyframe</strong>은 Apache <strong>CXF</strong> 2.2.7 버전을 이용하여 웹 서비스 기능을 제공하고 있다.웹 서비스란 인터넷 네트워크를 통하여 다수의 기존 어플리케이션 시스템을 표준화된 기술로서 상호 작용 시키고,이러한 표준 기술을 이용하여 모든 비즈니스를 가능하게 한다.웹 서비스는 언제, 어디에서나 원하는 정보나 서비스를 제공해 주는 역할을 하며 기존의 다른 소프트웨어처럼 완벽한 정의를 지정하여 구성하는 것이 아니라 서로 주고받는 데이터 표준에 대한 정의를 규정함으로써 매우 유연하고이질적인 운영시스템, 이질적인 프로그램 언어 간의 커뮤니케이션 차이를 극복해 주는 연결고리 역할을 수행한다.Web Service Architecture Working Group. W3C [http://www.w3.org/2002/ws/arch/] (Web Services Glossary, WebServices Architecture 등 자료 조회 가능)에서는 Web Services를 다음과 같이 정의하고 있다."A Web service is a software system designed to support interoperable machine-to-machineinteraction over a network. It has an interface described in a machine-processable format(specifically WSDL). Other systems interact with the Web service in a manner prescribed byits description using SOAP-messages, typically conveyed using HTTP with an XML serializationin conjunction with other Web-related standards."위의 영문 정의를 해석해보면, 다음과 같다. 네트워크를 통해 상호 운용성있는 기계 대 기계 상호작용을 지원하기위해 설계된 소프트웨어 시스템으로, WSDL이라는 형태로 정의된 인터페이스를 가지며, SOAP 메시지를 사용하여타 시스템들은 웹 서비스와 상호 작용할 수 있다. 웹 관련 표준들과 협력하며 전형적으로 HTTP를 사용한 XML 직렬화를 통해 전송한다.


2.Overview2.1.Web Services 개념2.1.1.Architecture기본적으로 웹 서비스(Web Services)는 3가지 역할(Service Provider, Service Broker, Service Consumer)로 구성된 아키텍처 모델에 따라 구현된 기술이다.• 웹 서비스의 3가지 역할RoleService ProviderService Broker (ServiceRegistry)Service Consumer (ServiceRequester)• 웹 서비스 시나리오설명특정 서비스 스펙을 구현한 서비스를 제공한다.서비스 등록 및 검색, 저장, 관리를 통해 Service Provider가 제공하는서비스를 Service Consumer에게 연결한다.Service Broker를 통해 특정 서비스를 찾고, Service Provider에게 해당서비스를 요청하고 사용한다.순서 Role 설명1 서비스 제공자(ServiceProvider)2 서비스 제공자(ServiceProvider)3 서비스 요청자(ServiceConsumer)4 서비스 요청자(ServiceConsumer)자신의 비즈니스 정보 및 제공할 서비스 정보, 그리고 이를이용할 수 있는 방법 등에 대한 정보를 WSDL 파일로 작성한다.자신의 서비스 WSDL을 UDDI 레지스트리에 등록한다. 이때등록되는 서비스는 UUID에 기반한 고유 ID를 부여받게 된다.UDDI 레지스트리에서 분류 및 식별 체계와 같은 여러 검색조건을 통해 필요한 서비스를 검색하여 찾는다. 해당 서비스가 찾아지면, 그 서비스에 대한 WSDL 파일을 받게 된다.WSDL 정보를 이용해 Service Provider와 연결하여 서비스를제공받게 된다. 이때 실행 결과는 SOAP을 이용한 XML 문서형태로 받는다.4


Overview• 웹 서비스의 3가지 기본 기술요소기술요소WSDLSOAPUDDI설명웹 서비스를 표현하고 기술하는 언어 (서비스 표현)웹 서비스에서 사용되는 보편적이며 확장성 있는 메시지 프로토콜 (데이터 통신 프로토콜)필요한 서비스를 찾을 수 있는 웹 서비스 레지스트리 (서비스 등록, 검색)2.1.2.SOAP(Simple Object Access Protocol)SOAP(Simple Object Access Protocol)은 HTTP, HTTPS, SMTP등을 사용하여 XML 기반의 SOAP 메시지를 컴퓨터 네트워크 상에서 교환하는 형태의 프로토콜로써 웹 서비스의 기본적인 메시지 전송 수단 이다. XML-RPC와 WDDX에서 envelope/header/body로 이루어진 구조, 전송(transport), 상호 중립성(interaction neutrality)의 개념을 도입하였다.• SOAP 메시지 구조SOAP 메시지는 루트 요소로 Envelope를 가지며, SOAP Header와 Body를 하위 요소로 가지고 있다.SOAP의 메시지 구조는 XML을 근간으로 Header와 Body를 조합하는 디자인 패턴으로 설계되었고,Body(필수사항)에는 전송될 메시 지의 내용을 기술한다. (Header는 선택사항)• SOAP 특징장점설명1 SOAP은 기본적으로 HTTP 기반 위에서 동작하기 때문에, HTTP와 같이 프록시와방화벽에 구애받지 않고 쉽게 통신 가능하다.2 SOAP은 표준 전송 프로토콜인 HTTP 이외의 다른 전송 프로토콜들을 사용할 수있다.3 플랫폼 및 프로그래밍 언어에 독립적이다.4 간단하고 확장 가능하며, (멀티파트 MIME 구조를 사용하여) 첨부를 통합하는SOAP XML 메시지를 지원한다.단점5설명1 XML 포맷은 태그 형태로 구성되기 때문에 CORBA와 같은 미들웨어 기술과 비교해서 상대적으로 느리다. (최근 네트워크 속도의 비약적인 발전과 성능 최적화 기술의 발전으로 대부분 해결됨)2.1.3.WSDL(Web Services Description Language)WSDL(Web Services Description Language)이란, 웹 서비스로 제공되는 서비스에 대한 정보를 기술하기 위한 XML 기반의 마크업 언어이다.


Overview즉, 원하는 서비스가 어디(Where)에 존재하며, 웹서비스로 무엇(What)을 할 수 있고, 또 이를 실행하기위해서는 어떻게 (How) 해야 하는가를 XML 형식으로 기술하여 제공하는 웹 서비스 기술 언어이다.• WSDL 문서 구조를 루트로 하여 추상적 정의(types/message/portType)와 구체적 정의(binding/service)로 나뉜다. 추상적 정의와 구체적 정의를 분리하여 기술함으로써, 서로 다른 서비스구현시 서비스의 추상적 정의를 재사용할 수 있다.• WSDL 문서 구조 상세WSDL의 주요 기술 내용에는 웹 서비스의 이름과 URI 정보, SOAP 메시지의 인코딩 방법, SOAP 메시지 전송을 위한 프로토콜 정보, 웹 서비스를 이용하는데 필요한 인터페이스 정보가 있다. WSDL의 구성 요소를 상세히 살펴보면 아래와 같다.WSDL 상세 구성 요소에 대한 설명은 다음과 같다.요소설명Endpoint(실제 웹 서비스로 구현된 어플리케이션)의 물리적 위치를 정의하고 각바인딩에 대한 포트 주소를 기술한다.binding 정보와 address location을 정의한다.(WSDL 2.0에서는 로변경됨)portType과 네트워크 프로토콜 매핑 정보를 정의한다. 즉, 어떤 통신 프로토콜을 통해서 통신을 할 것인지를 정의한다.6


Overview요소설명인터페이스의 메소드들을 정의한다. Interface(WSDL 2.0에서 로 변경됨)서비스의 메소드에서 사용되는 요청(Request)/ 응답(Response) 메시지 정의서비스가 사용하는 메시지를 정의한다. 메소드의 인자와 리턴 값을 선언한다.(WSDL 2.0에서는 를 통해 XML 스키마 타입을 사용하여 기술)문서에서 사용되고 있는 데이터 타입을 정의한다.2.1.4.기술 표준웹 서비스는 SOAP, WSDL, UDDI를 중심으로 한 기본 기술 표준을 제공하며 서비스의 품질을 높이기 위해 보안, 트랜잭션 처리, 신뢰성 있는 메시지 처리 등에 대한 다양한 확장 표준을 제공한다.• Security표준WS-SecurityWS-TrustWS-SecureConversation설명무결성(Integrity)과 기밀성(Confidentiality), 인증(Authentication) 등을강화하기 위한 SOAP 메시지 확장 메커니즘 규정. 크게는 WS-Policy,WS-Trust, WS-SecureConversation, WS-Federation, WS-Authorization을 포함한다.상호간에 웹 서비스가 안전하게 작동할 수 있도록 하기 위한 신용 관계의 유지 및 해지를 설정하는 신뢰 모델에 대한 표준이다.메시지 교환시 보안이 어떤 방식으로 관리되는지를 명시한 securitycontext에 대한 관리 표준이다.• Transaction표준WS-Coordination설명분산되어 있는 다양한 웹 서비스들이 트랜잭션에 참여할 수 있도록 액티비티를 생성 및 관리, 조정, 완료하는 메커니즘에 대한 표준(Coordination Framework)이다.7


Overview표준WS-Transaction설명Atomic 또는 Business 트랜잭션 프로토콜에 대한 표준 (CoordinationProtocols)이다.• Reliable Messaging표준WS-ReliableMessagingWS-Addressing설명목적지까지 메시지가 확실하게 도착하는 메시징 신뢰도를 보장하기위해, 분산된 웹 서비스들 간에 주고 받는 ACK (acknowledge) 메시지등을 정의하는 표준이다.웹 서비스 간 메시지를 전달하는 메커니즘을 제공하는 표준이다.2.2.구현 기술Java로 Web Services를 작성하는 방법을 제공하는 자바 API로는 JAX-RPC와 JAX-WS가 있으며, 이외에여러 가지 구현 기술들이 요구된다.2.2.1.JAX-RPC vs. JAX-WSJAX-WS 2.0이 JAX-RPC 1.1의 차후 버전으로 Web Services 구현 시 사용되는 표준 자바 API이다.* JAX-WS : Java API for XML-Based Web Services* JAX-RPC : Java API for XML-Based RPC(Remote Procedure call)• JAX-RPC와 JAX-WS 비교표JAX-RPC 1.1의 다음 버전인 JAX-RPC 2.0이 나오면서, RPC라는 용어 대신 메시지 지향 웹서비스인 WS로 대체되어 JAX-WS 2.0으로 불리게 되었다.Java 환경JAX-RPC 1.1 JAX-WS 2.0JDK 1.4/ J2EE 1.4 환경에서 사용되는Web Services API8Java EE 5/Java SE 6 환경(탑재)에서 사용되는 Web Services APISOAP SOAP 1.1 SOAP 1.1, SOAP 1.2XML/HTTPHTTP 바인딩 지원 안함 (SOAP 바인딩만 지원)HTTP 바인딩 지원 (SOAP없이 HTTP를통해 XML 전송)WS-I Basic Profile WS-I Basic Profile 1.0 WS-I Basic Profile 1.1데이터 매핑 모델 고유의 데이터 매핑 모델이 있음 (스키마 유형의 90% 커버) 커버되지 않는것들은 javax.xml.soap.SOAPElement로매핑인터페이스모델동적모델매핑프로그래밍지원 안함지원 안함JAXB (모든 XML 스키마를 100% 매핑함)Java 5.0 기능 사용 및 비동기식 기능 도입메시지 지향 및 동적 비동기식 기능 도입MTOM 지원 안함 JAXB를 통한 새로운 Attachment 스펙인MTOM에 대한 지원을 추가핸들러 모델 SAAJ 1.2에 기반 SAAJ 1.3에 기반• JAX-RPC 1.1을 사용해야 하는 경우


OverviewCase1 JDK 1.4를 계속 사용해야 하는 경우설명2 SOAP 인코딩 메시지를 보내거나 RPC/encoded 스타일의 WSDL을 보내야 하는경우• JAX-WS 2.0을 사용하는 경우Layered Programming Model을 제공한다. 상위계층은 Annotation을 활용한 쉬운 개발이 가능하게 하며, 하위계층 의 경우 API 기반의 섬세한 조정이 가능하다.Case• JAX-RPC 단점설명1 새로운 메시지 지향 API를 사용해야 할 경우2 MTOM을 사용하여 첨부 데이터를 보내야 하는 경우3 JAXB를 통해 XML 스키마를 더욱 잘 지원하기 위한 경우4 웹 서비스 클라이언트에 비동기식 프로그래밍 모델을 사용하고 싶을 경우5 SOAP 1.2 메시지를 처리할 수 있는 클라이언트와 서비스가 있어야 하는 경우6 웹 서비스에서 SOAP을 배제하고 XML/HTTP 바인딩만 사용하고 싶을 경우구버전인 JAX-RPC에는 다음과 같이 몇가지 단점이 존재한다.단점2.2.2.XML Schema1 제한된 XML Schema를 지원한다.설명2 Java와 WSDL간의 매핑 지원이 부족하다.3 어플리케이션 이식성이 낮다.4 런타임(Runtime) 크기가 비대하다.5 개발 방법이 매우 복잡하다.XML 문서의 구조와 컨텐츠를 정의하는 파일을 가리키는 일반적인 용어로 DTD와 마찬가지로 문서의 구조를 정의하며, 문법, 어휘, 구조, 데이터 타입 등을 규정하는 모든 규칙들을 제공한다.* XML Schema Definition (XSD) : XML Schema를 작성하기 위한 XML Schema language• XML Schema vs. DTDDTD의 문제점을 해결하기 위한 목적으로 XML Schema가 나왔다. XML Schema는 DTD보다 더 표현력이 풍부하고, 정확한 자료 구조를 제공하는 새로운 구조 정의 언어로, Web Services는 XML Schema를 사용한다.XML 문법으로 작성namespace 지원XML SchemaDTDXML 문법 아님 (EBNF 문법 사용)namespace 지원 안함다양한 데이터 타입 지원, 데이터 타입 확장 가능 제한적인 데이터 타입상속과 같은 객체 지향 개념 지원개방적 컨텐츠 모델• XML Schema element 정의객체 지향 개념 없음폐쇄적 컨텐츠 모델9


Overview각 속성 값에 대한 설명은 다음과 같다.속성설명nameelement의 명칭typeelement의 데이터 타입ref전역 element 선언을 참조하기 위해 사용minOccurs element의 최소 반복 횟수, default 값은 1maxOccurs element의 최대 반복 횟수, default 값은 1default element의 값이 정의되지 않았을 때 할당되는 기본값fixedelement에 들어갈 고정값• XML Schema attribute 정의각 속성 값에 대한 설명은 다음과 같다.속성nametyperefformusedefaultfixed설명attribute의 명칭attribute의 데이터 타입전역 attribute 선언을 참조하기 위해 사용한정된 이름인지의 여부 (qualified/unqualified)사용 조건 (optional/prohibited/required)attribute의 값이 정의되지 않았을 때 할당되는 기본값attribute에 들어갈 고정값2.2.3.기타 구현 기술• JAXB(Java Architecture for XML Binding)XML 스키마를 자바 클래스로 바인딩하기 위한 자바 API로 크게 2가지 기능을 제공한다. 그 기능은 바로 자바 객체를 XML로 마샬링(marshalling)하는 기능과 반대로 XML에서 자바 객체로 언마샬링(unmarshalling)하는 기능이다. 더욱 자세한 내용은 여기 [http://java.sun.com/developer/technicalArticles/WebServices/jaxb/] 를 참고하도록 한다.• MTOM(Message Transmission Optimization Mechanism)SOAP 메시지와 함께 큰 바이너리 첨부 파일을 원시 바이트로 전송하여 메시지 크기를 줄이는 메커니즘으로 바이너리 데이터를 포함한 XML에 대한 메시지 전송을 최적화시킨다. 더욱 자세한 내용은여기 [http://www.w3.org/TR/soap12-mtom/] 를 참고하도록 한다.• SAAJ(SOAP with Attachments API for Java)SOAP 메시지를 생성하고 파일 첨부하고 전송하는 방법을 제공하는 자바 API이다. 더욱 자세한 내용은 여기 [http://java.sun.com/webservices/saaj/docs.html] 를 참고하도록 한다.10


Overview2.3.Web Services Framework많이 사용되는 웹 서비스 오픈 소스 프레임워크로는 Apache <strong>CXF</strong>, Apache Axis/Axis2, Spring WebServices 등이 존재하며 여러 프레임워크 중 사용하고자 하는 목적에 적합한 웹 서비스 프레임워크를선정한다. <strong>Anyframe</strong>에서는 Apache <strong>CXF</strong>를 선정하였다.2.3.1.Web Services Framework 종류Web Service 구현 스타일은 크게 Contract-Last와 Contract-First가 있다. Contract-Last 스타일은 Java 소스 코드를 먼저 작성한 후에 WSDL을 자동생성하여 구현하는 방식(Code-First라고 불리기도 함)이고,Contract-First 스타일은 WSDL 파일을 먼저 작성한 후 Java 소스 코드를 작성하는 방식이다.Web Services Open Source Framework에는 여러 가지가 있는데 이 중 현재 가장 많이 쓰이고 있는 4가지에 대해서 소개한다.• Apache <strong>CXF</strong>Contract-First 스타일과 Contract-Last 스타일 모두를 지원한다. 자세한 내용은 http://cxf.apache.org/[http://cxf.apache.org/] 를 참조한다.• Apache AxisAxis2의 구버전으로 웹 서비스 개발 방식이 복잡하다. 자세한 내용은 http://ws.apache.org/axis/[http://ws.apache.org/axis/] 를 참조한다.• Apache Axis2Apache Axis의 업그레이드 버전으로 구조 등이 새롭게 변경되었다. 기능적인 면에서 Apache <strong>CXF</strong>와유사하다. 자세한 내용은 http://ws.apache.org/axis2/ 를 참조한다.• Spring Web ServicesContract-First 스타일의 웹 서비스 개발 방식만 지원한다. 자세한 내용은 http://static.springframework.org/spring-ws/site/ 를 참조한다.2.3.2.Apache <strong>CXF</strong> 특징여러가지 Web Services Framework 중 Apache <strong>CXF</strong>를 선정하게 된 이유는 다음과 같은 특징 때문이다.JAX-WS 지원특징Spring IntegrationAegis DatabindingRESTful servicesWS-* SupportApache LicensedCeltix와 X-Fire 프로젝트의 합작품설명<strong>CXF</strong>에서는 JAX-WS API를 구현하고 있어서 웹 서비스 구현을 쉽게 하고 있다.<strong>CXF</strong>는 Spring 2.X 이상을 지원하며 endpoint 설정이나 client injection 등Spring과의 통합을 용이 하게 한다.<strong>CXF</strong>는 JAXB, Aegis Databinding을 모두 지원한다. JAXB의 경우와 다르게 Annotation 방식으로 사용할 필요가 없으며, List/Map/Date 등의 다양한 데이터 타입 사용이 매우 쉽다.Annotation 설정 방식으로 RESTful 서비스 구현을 용이하게 한다.<strong>CXF</strong>는 다양한 웹 서비스 스펙(WS-Addressing, WS-Policy, WS-ReliableMessaging, WS-Security)을 지원한다.아파치 라이센스 사용으로 활용에 자유롭다.기능 보강 및 사용 편의성 면에서 새롭게 재구성된 부분이 많이 존재한다.11


Overview특징웹 서비스 표준 지원Frontend 모델 제공사용 편의성바이너리와 기존 프로토콜 지원비동기 방식 호출 가능JDK 1.5 이상 지원2.4.Tools설명SOAP, the Basic Profile, WSDL, WS-Addressing, WS-Policy, WS-ReliableMessaging, WS-SecurityJAX-WS Frontend와 Simple Frontend를 제공한다.간단한 API 사용으로 서비스 구현 가능, Tool(ANT Task 등)을 제공한다.XML/비-XML 타입 바인딩(JSON, CORBA)을 제공, 여러 전송 프로토콜을지원할 수 있는 조립식 아키텍처를 제공한다.비동기 방식의 호출이 가능(Asynchronous Invocation Model 제공)하다.Annotation 기능 등 여러 가지 이유 때문에 JDK 1.5 이상만 지원한다.Apache <strong>CXF</strong>에서 여러가지 Tool을 제공함으로써 웹 서비스 구현 시 개발 편의성을 높여주고 있다. 아래에 언급된 Tool 이외에 Eclipse <strong>Plugin</strong>과 Maven <strong>Plugin</strong> 형태의 Tool도 제공되고 있다. Apache <strong>CXF</strong>를다운로드 페이지 [http://cxf.apache.org/download.html] 에서 Binary distribution을 내려 받고 압축을풀면 루트 폴더 하위의 bin 폴더 내에 Tool이 존재한다. 자세한 사항은 이곳 [http://cwiki.apache.org/<strong>CXF</strong>20DOC/tools.html] 을 참고하도록 한다.Ant TasksJava to WSJava to WSDLtool설명wsdl2java, java2ws를 위한 ant task를 제공한다.SEI 클래스와 관련 타입 클래스들로부터 WSDL document, wrapperbean 클래스, server/client side 소스 코드들을 생성한다.(<strong>CXF</strong> 2.1)SEI 클래스와 관련 타입 클래스들로부터 WSDL document를 생성한다.(<strong>CXF</strong> 2.0.x)Maven Integration and <strong>Plugin</strong> 관련 라이브러리를 배포해주는 Maven Repository들과 함께 빌드 툴로써 Maven을 사용할 수 있도록 Maven <strong>Plugin</strong> 을 제공한다.XSD to WSDLWSDL to JavaWSDL to ServiceWSDL to SOAPWSDL to XMLWSDLValidatorXSD(Schema 파일)를 통해서 WSDL document를 생성한다.WSDL document로부터 서비스 구현에 필요한 annotation으로 작성된Java 소스 코드와 어플리케이션을 빌드할 수 있는 ANT 기반 XML 파일을 생성한다.WSDL document로부터 HTTP 혹은 JMS 서비스 정의를 갖는 새로운WSDL document를 생성한다.WSDL document로부터 SOAP binding 정보를 갖는 새로운 WSDLdocument를 생성한다.WSDL document로부터 XML binding 정보를 갖는 새로운 WSDLdocument를 생성한다.WSDL document나 WSDL URL이 well-formed document이고 Schema에맞게 작성된 것인지 확인해주는 일을 한다.12


3.DatabindingXML 문서의 XSD Schema를 기준으로 XML문서와 JavaBeans 객체를 매핑하는 것을 Databinding이라고하며, Web Services에서 서버와 클라이언트 간의 XML 문서를 주고 받아서 일을 수행하려고 할때 사용되는 기술이다. Apache <strong>CXF</strong>는 Databinding을 위해 JAXB를 디폴트로 사용하며 Aegis, MTOM을 추가적으로 지원한다. Databinding의 종류는 다음과 같다.• JAXBJava Architecture for XML Binding의 약자로 XML Schema로부터 클래스 데이터를 바인딩하여 XML로부터 객체를 Unmarshalling 하거나, 반대로 객체를 XML로 저장하는 Marshalling을 수행할 수 있도록 해 준다.• AegisAegis는 JAXB와 다르게 표준(Spec.)이 아니며, Apache <strong>CXF</strong>에서만 제공되는 기능으로 JAXB와 역할이동일하다. Xfire 프로젝트의 일부로 시작되었으나 Celtix와 Xfire의 합체로 현재 Apache <strong>CXF</strong>에 포함되어 발전되고 있다.• MTOMMessage Transmission Optimization Mechanism의 약자로 SOAP 메시지 통신 최적화 메커니즘이다.웹 서비스를 통해 바이너리 데이터를 효과적으로 편리하게 전송할 수 있도록 하는 표준이다.Databinding 기술 종류를 그림으로 살펴보면 다음과 같다. 보통 JAXB, JAXB+MTOM, Aegis, Aegis+MTOM의 형태로 Databinding 기술이 사용된다. 그림에서 JAXB와 Aegis의 공통 영역이 존재하는 이유는 Aegis를 사용하면서 몇가지 JAXB Annotation을 함께 사용할 수 있기 때문이다.다음은 각각의 Databinding 기술 별로 어떻게 사용하는지에 대한 사용법이다.3.1.JAXB DatabindingJAXB는 Java Architecture for XML Binding의 약자로 XML Schema로부터 클래스 데이터를 바인딩하여XML로부터 객체를 Unmarshalling 하거나, 반대로 객체를 XML로 저장하는 Marshalling을 수행할 수 있도록 해 준다.JAXB의 특징 을 살펴보면 다음과 같다.• Apache <strong>CXF</strong> 사용 시 디폴트 Databinding 방식이 JAXB이므로, JAXB 사용을 위한 추가 설정이 필요없다.• JavaBeans 코드에 @XmlElement와 같은 Annotation을 설정하여 element 명을 변경시킬 수 있다.• JavaBeans 코드에 Annotation 설정 없이도 JAXB를 사용할 수 있다.13


Databinding• List 형태의 타입은 지원하나 Map 형태의 타입에 대해서는 Databinding을 기본적으로 지원하지 않으므로 Map 형태의 타입을 이용하여 Databinding 하기 위해서는 XmlAdapter 클래스를 추가로 작성해줘야 한다.• JAXB Databinding와 Simple frontend를 함께 사용 시 문제가 발생하는 경우가 있기 때문에, JAXBDatabinding은 JAX-WS frontend와 함께 사용하도록 한다.JavaBeans 객체와 XML Schema 간의 매핑 관계 를 보면 다음과 같다.JAXB의 역할 수행 모습을 그림을 통해 살펴보면 다음과 같다.다음은 JAXB 기능을 Server와 Client 단에서 어떻게 사용해야 하는지에 대한 사용법이다.3.1.1.Server ConfigurationMovie Service를 JAX-WS Frontend를 사용하여 Web Services로 노출시킬 때 인터페이스 메소드의 파라인터 인자와 리턴 값의 타입을 다양한 타입으로 선언하여 테스트해보도록 한다.3.1.1.1.Samples다음은 Movie Service의 인터페이스 클래스 정의와 Map 타입 사용을 위한 XmlAdapter 클래스 정의에대한 예제이다.• Interface Class다음은 Movie Service의 인터페이스 클래스를 작성한 MovieService.java의 일부이다.@WebService@XmlSeeAlso(Movie.class)14


Databindingpublic interface MovieService extends GenericService {@XmlJavaTypeAdapter(<strong>CXF</strong>MapAdapter.class)Map getMovieWithMap(String movieId) throws Exception;중략...• XmlAdapter ClassMovie Service의 인터페이스 메소드 중 리턴 타입이 Map인 경우, XmlAdapter 클래스가 추가 작성되어야 한다. Map 타입을 사용하지 않는 경우 작성할 필요 없다. 다음은 XmlAdapter 클래스를 작성한<strong>CXF</strong>MapAdapter.java 의 일부이다.public class <strong>CXF</strong>MapAdapter extends XmlAdapter {public <strong>CXF</strong>Map marshal(Map v) throws Exception {<strong>CXF</strong>Map map = new <strong>CXF</strong>Map();for (Map.Entry e : v.entrySet()) {<strong>CXF</strong>Map.<strong>CXF</strong>Entry iue = new <strong>CXF</strong>Map.<strong>CXF</strong>Entry();iue.setValue(e.getValue());iue.setKey(e.getKey());map.getEntries().add(iue);}return map;}public Map unmarshal(<strong>CXF</strong>Map v) throws Exception {Map map = new LinkedHashMap();for (<strong>CXF</strong>Map.<strong>CXF</strong>Entry e : v.getEntries()) {map.put(e.getKey(), e.getValue());}return map;}}중략...• XmlAdapter Class에서 사용하는 부가 클래스위에서 작성한 XmlAdapter 클래스 내에서 marshalling/unmarshalling 작업 시 사용되는 <strong>CXF</strong>Map 클래스 또한 추가 작성되어야 한다. Map 타입을 사용하지 않는 경우 작성할 필요 없다. 다음은 <strong>CXF</strong>Map클래스를 작성한 <strong>CXF</strong>Map.java 의 일부이다.@XmlType(name = "<strong>CXF</strong>Map")@XmlAccessorType(XmlAccessType.FIELD)public class <strong>CXF</strong>Map {@XmlElement(nillable = false, name = "entry")private List entries = new ArrayList();public List getEntries() {return entries;}@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "Identified<strong>CXF</strong>")static class <strong>CXF</strong>Entry {// Map keys cannot be null@XmlElement(required = true, nillable = false)private String key;private Object value;public String getKey() {return key;}15


Databinding3.1.2.유의 사항public void setKey(String key) {this.key = key;}public Object getValue() {return value;}public void setValue(Object value) {this.value = value;}중략...JAXB Databinding 방식을 사용하여 Web Services로 노출된 메소드에 접근하여 사용 시 유의해야 하는사항이다.3.1.2.1.SEI 클래스에서 정의되지 않은 Java Type 클래스가Runtime시 Databinding되어야 하는 경우SEI 클래스에 정의된 메소드의 입력값이나 리턴값으로 참조되지 않은 Java Type 클래스의 경우, Runtime시 Databinding이 일어날 때 다음과 같은 에러 메시지가 나오게 됩니다.org.apache.cxf.interceptor.Fault: Marshalling Error: class anyframe.sample.domain.Movie nor any of itssuper class is known to this context.아래 방법을 통해서 해결하도록 한다.• Interface ClassSEI(Service Endpoint Interface) 클래스의 메소드에는 List 형태의 결과값을 리턴하는 메소드가 존재하고 해당 List내에 저장된 Java Type 클래스에 대해서는 참조하는 메소드가 없는 경우, 클라이언트가 해당 메소드를 호출할 때 Runtime시에 JAXB Databinding을 시도하려고 하면서 Marshalling Error가 발생하게 된다. 이를 방지하기 위해서 @XmlSeeAlso Annotation 혹은 JDK1.5의 Generic Type을 설정하도록 한다.@XmlSeeAlso 사용 예제@WebService@XmlSeeAlso({Movie.class})public interface MovieService {public List getMovieList(SearchVO searchVO);중략...JDK 1.5의 Generic Type 사용 예제@WebServicepublic interface MovieService {public List getMovieList(SearchVO searchVO);중략...3.2.Aegis DatabindingAegis는 JAXB와 다르게 표준(Spec.)이 아니며, Apache <strong>CXF</strong>에서만 제공되는 기능으로 JAXB와 역할이 동일하다. 즉, XML Schema로부터 클래스 데이터를 바인딩하여 XML로부터 객체를 Unmarshalling 하거16


Databinding나, 반대로 객체를 XML로 저장하는 Marshalling을 수행할 수 있도록 해 준다. Xfire 프로젝트의 일부로시작되었으나 Celtix와 Xfire의 합체로 현재 Apache <strong>CXF</strong>에 포함되어 발전되고 있다.Aegis의 특징 을 살펴보면 다음과 같다.• Apache <strong>CXF</strong> 사용 시 디폴트 Databinding 방식이 JAXB이므로, Aegis를 사용하기 위해서는 추가 설정이 필요하다.• JavaBeans 코드에 Annotation 설정 없이 Aegis를 사용할 수 있다.• List 형태의 타입 뿐 아니라 Map 형태의 타입에 대해서 추가 작성해야 하는 클래스 필요없이 기본적으로 Databinding을 지원한다.• Java 객체를 XML Schema에 의해 작성되는 XML 문서로 매핑해주는 일을 수행하는데 객체 제어 및확장을 개발자가 최소한의 작업을 통해 가능하게 해준다.• Aegis를 사용하는 대부분의 개발자들은 Simple Frontend를 사용한다.Aegis에서 지원하는 데이터 타입 은 다음과 같다.구분Basic typesCollectionsDatesXMLComplex types데이터 타입int, double, float, long, byte[], short, String, BigDecimal, BigInteger, Character,Double, Float 등 *주의)char는 지원되지 않음Arrays, Mapsjava.util.Date, java.util.Calendar, java.sql.Timestamp, java.sql.Date, java.sql.Timeorg.w3c.dom.Docmument, org.jdom.Element, XMLStreamReader, Source위 데이터 타입의 조합으로 새로 작성한 User Defined Types다음은 Aegis 기능을 Server와 Client 단에서 어떻게 사용해야 하는지에 대한 사용법이다.3.2.1.Server ConfigurationMovie Service를 Simple Frontend를 사용하여 Web Services로 노출시킬 때 인터페이스 메소드의 파라인터 인자와 리턴 값의 타입을 다양한 타입으로 선언하여 테스트해보도록 한다.3.2.1.1.Samples다음은 Movie Service의 인터페이스 클래스 예제이다. Map 타입 사용을 위해서 부가적인 작업이 필요없다.• Interface Class다음은 Movie Service의 인터페이스 클래스를 작성한 MovieService.java 의 일부이다.public interface MovieService {public List findMovieListAll() throws Exception;public Map findMovieMapAll() throws Exception;public Movie findMovie(String movieId) throws Exception;public void createMovie(Movie movie) throws Exception;public void updateMovie(Movie movie) throws Exception;17


Databindingpublic void removeMovie(Movie movie) throws Exception;// ================= method for Type testspublic int testMovieIntVal(int val);public long testMovieLongVal(long val);public short testMovieShortVal(short val);public float testMovieFloatVal(float val);public double testMovieDoubleVal(double val);public BigDecimal testMovieBigDecimalVal(BigDecimal val);public boolean testMovieBooleanVal(boolean val);public Character testMovieCharacterVal(Character val);중략...• Configuration다음은 서버 사이드의 서비스를 Web Services로 노출시키는 Spring Configuration 파일 예이다. (SpringConfiguration XML Server 설정 이용) Spring Configuration XML 설정을 통해 Aegis Databinding 사용을 정의할 수 있다.중략...3.2.2.Client ConfigurationWeb Services에 접근하기 위한 클라이언트 작성 방식 중 Spring Configuration XML 파일 설정 방식을사용해본다.3.2.2.1.Samples다음은 Web Services로 노출된 Movie Service에 접근하는 Spring Configuration 파일 예이다. (SpringConfiguration XML Server 설정 이용) Spring Configuration XML 설정을 통해 Aegis Databinding 사용을 정의할 수 있다.• ConfigurationSpring Configuration XML Client 설정 이중략...18


Databinding3.3.MTOM DatabindingMTOM은 Message Transmission Optimization Mechanism의 약자로 SOAP 메시지 통신 최적화 메커니즘이다. 웹 서비스를 통해 바이너리 데이터를 효과적으로 편리하게 전송할 수 있도록 하는 표준이다.JAXB Databinding 혹은 Aegis Databinding과 함께 사용될 수 있다. 서비스를 통해 바이너리 데이터를효과적으로 편리하게 전송할 수 있도록 하는 표준으로 XML 문서의 일부가 아닌 첨부파일(Attachment)형태로 생성되어 전송되며 Schema Type 혹은 자바 코드에 Annotation으로 설정한다. Schema Type에xmime:expectedContentTypes="application/octet-stream" 을 추가 설정하면 base64Binary element를위한 byte[] array 형태를 생성하지 않고 데이터를 스트림하는데 쓰이는 DataHandler를 생성한다.MTOM의 특징 을 살펴보면 다음과 같다.• Apache <strong>CXF</strong> 사용 시 디폴트로 MTOM 기능이 동작하지 않으므로, MTOM 사용을 위한 추가 설정이필요하다.• XML 문서의 일부가 아닌 첨부파일(Attachment) 형태로 생성되어 전송한다.• 바이너리 데이터를 나타내는 JavaBeans의 attribute를 javax.activation.DataHandler type으로 정의하고, @XmlMimeType("application/octet-stream") Annotation 설정을 추가해주도록 한다.다음은 MTOM 기능을 Server와 Client 단에서 어떻게 사용해야 하는지에 대한 사용법이다. 예제는 JAX-WS Frontend, JAXB, MTOM을 함께 사용하는 것으로 구성되어 있다.• Server Configuration• Client Configuration• 참고 - MTOM에 관련된 내용3.3.1.Server ConfigurationMovie Service를 JAX-WS Frontend를 사용하여 Web Services로 노출시키는 예제로, MTOM을 테스트하기 위해서 추가 작업한 부분을 중심으로 살펴본다. 또한 MTOM을 사용하지 않고 기존에 XML 문서의 일부로 바이너리 데이터를 전송하는 경우와 MTOM을 이용하여 XML 문서 일부가 아닌 첨부파일 형태로전송하는 경우에 대해서 바이너리 데이터의 전송과 수신이 올바르게 동작하는지 알아본다.3.3.1.1.Samples다음은 Movie Service의 인터페이스 메소드를 통해 클라이언트와 서버 간 주고받는 데이터인 Movie 클래스 정의에 대한 예제이다.• JavaBeans Class다음은 Movie Service의 인터페이스 메소드를 통해 클라이언트와 서버 간 주고받는 데이터인 Movie클래스를 작성한 Movie.java 의 일부이다.public class Movie implements Serializable {private String movieId = "";private String title = "";private String director = "";private byte[] posterImgByteArray = null;@XmlMimeType("application/octet-stream")private DataHandler posterImgDataHandler = null;19


Databindingpublic byte[] getPosterImgByteArray() {return posterImgByteArray;}public void setPosterImgByteArray(byte[] posterImgByteArray) {this.posterImgByteArray = posterImgByteArray;}public DataHandler getPosterImgMTOM() {return posterImgDataHandler;}public void setPosterImgDataHandler(DataHandler posterImgDataHandler) {this.posterImgDataHandler = posterImgDataHandler;}중략...• Test caseSpring Configuration XML Server 설정 이용(JAX-WS Frontend)Spring Configuration XML 설정을 통해 MTOM Databinding 사용을 정의할 수 있다.중략...[참고] Spring Configuration XML Server 설정 이용(Simple Frontend) Simple Frontend를 사용하는 경우에도 마찬가지로 Spring Configuration XML 설정을 통해 MTOM Databinding 사용을 정의할 수 있다.중략...3.3.2.Client ConfigurationWeb Services에 접근하기 위한 클라이언트 작성 방식 중 Spring Configuration XML 설정 방식을 사용하면 간편하고 편리하게 사용할 수 있다.3.3.2.1.Samples다음은 Web Services로 노출된 Movie Service에 접근하는 예제이다.• Test Case20


DatabindingMTOM을 이용하여 XML 문서 일부가 아닌 첨부파일 형태로 바이너리 데이터를 전송하는 경우에MTOM Databinding 기능이 올바로 동작하여 Movie의 poster image 바이너리 파일을 조회하고 수정이 되는지 테스트한다.Spring Configuration XML Client 설정 이용(JAX-WS Frontend)Spring Configuration XML 설정을 통해 MTOM Databinding 사용을 정의할 수 있다.중략...[참고] Spring Configuration XML Server 설정 이용(Simple Frontend) Simple Frontend를 사용하는 경우에도 마찬가지로 Spring Configuration XML 설정을 통해 MTOM Databinding 사용을 정의할 수 있다.중략...3.3.3.참고 - MTOM에 관련된 내용• Web Services 성능 향상을 위해 W3C에서 제시한 스펙• 2005년 1월 W3C(World Wide Web Consortium)는 다음과 같이 3가지의 Web Services 스펙을 제시하였다. 이들은 SOAP 1.2 메시지를 참조하거나 포함하는 바이너리 데이터를 효율적으로 패키징하거나 송신하는 방법을 제공한다.• XOP (XML-binary Optimized Packaging), MTOM (SOAP Message Transmission OptimizationMechanism), RRSHB (Resource Representation SOAP Header Block)• 바이너리 데이터 전송• XML 문서의 일부가 바이너리 데이터인 경우, base64로 인코딩 되어야 하는데 이는 CPU 점유 시간을 증가시키고 Payload 사이즈를 증가시키는 문제가 있다. Web Services의 특징 중 하나는 전송되는 메시지가 XML로 구성되어 이기종간의 통신을 원활하게 한 것이다. 이는 XML이 일종의 텍스트 문서이므로 이기종 사이에서 이식성이 좋기 때문이다. 하지만 텍스트인 XML 문서에 바이너리데이터를 추가하기 위해서는 base64 방식으로 인코딩해야 하며 이러한 인코딩 과정에서 바이너리 데이터의 용량은 50%이상 증가하고, 인코딩과 디코딩을 처리하기 위해서 발생하는 CPU의 부하도 5~10% 정도 추가된다는 통계가 있다. 즉, 바이너리 데이터를 전송하는데 있어 Web Services를 이용하게 되면 성능이 저하되는 문제가 발생하게 된다.• MTOM을 사용하면 XML 문서의 일부가 아닌 첨부파일(SOAP-Attachment) 형태로 생성되어 전송되어지므로 위와 같은 문제를 해소시킬 수 있다.21


Databinding• Schema Type에 xmime:expectedContentTypes="application/octet-stream" 을 추가 설정하면base64Binary element를 위한 byte[] array 형태를 생성하지 않고 데이터를 스트림하는데 쓰이는DataHandler를 생성한다.• 대용량 바이너리 데이터의 송신을 위한 표준적인 수단과 방법 제공• XOP와 MTOM을 이용하여 보다 효율적인 SOAP 메시지의 직렬화와 송신이 가능해진다.• XOP는 바이너리 데이터를 그대로 통신 패킷에 포함되도록 하는 표준적인 수단을 제공함으로써 작은 데이터 저장공간이나 좁은 데이터 통신 대역에서도 효율적으로 동작하게 하며 XML InformationSet(InfoSet)을 이용하여 다양한 방법으로 XML 문서를 직렬화시킨다.• XOP를 구현하는 MTOM은 XOP가 제공하는 기능을 활용하여 SOAP 통신을 처리한다. SOAP 바인딩과 송신을 최적화하는 전송 메커니즘을 정의하여 필요한 통신 대역을 축소하고 대용량 바이너리데이터의 인코딩과 디코딩에 필요한 시간을 단축한다. 또한 다양한 바이너리 데이터 송신 시 MIME첨부 형식으로 SOAP 통신을 한다.• RRSHB(Resource Representation SOAP Header Block)는 SOAP 메시지 수신자가 원격에 위치한 자원의 로컬 캐시에 접근하게 한다. 메시지 수신자는 URI에 의해 식별된 파일과 SOAP 통신으로 함께 보내진 데이터에 대한 로컬 캐시 중 하나를 선택하여 이용할 수 있다. MTOM과 함께 사용됨으로써 메시지 수신자는 원격에 위치한 데이터에 대한 로컬 캐시가 이미 존재하고 있다면 요청 처리 속도는 현격하게 향상될 것이다.3.4.Resources• 다운로드다음에서 테스트 DB를 포함하고 있는 hsqldb.movie.zip과 sample 코드를 포함하고 있는anyframe.sample.cxf.jaxws.zip 파일을 다운받은 후, 압축을 해제한다. 그리고 hsqldb 폴더 내의start.cmd (or start.sh) 파일을 실행시켜 테스트 DB를 시작시켜 놓는다.• Maven 기반 실행Command 창에서 압축 해제 폴더로 이동한 후 mvn clean jetty:run이라는 명령어를 실행시킨다. Jetty Server가 정상적으로 시작되었으면 브라우저를 열고 주소창에 http://localhost:8080/anyframe.sample.cxf.jaxws를 입력하여 실행 결과를 확인한다.• Eclipse 기반 실행 - m2eclipse, WTP 활용Eclipse에서 압축 해제 프로젝트를 import한 후, 해당 프로젝트에 대해 마우스 오른쪽 버튼을 클릭하고 컨텍스트 메뉴에서 Maven > Enable Dependency Management를 선택하여 컴파일 에러를해결한다. (위와 같이 했음에도 컴파일 에러가 사라지지 않으면 컨텍스트 메뉴에서 Properties >JavaEE Module Dependencies를 클릭하고, 오른쪽 JAR/Module 목록에서 Maven Dependencies 항목을 체크하도록 한다.) 그리고 해당 프로젝트에 대해 마우스 오른쪽 버튼을 클릭한 후, 컨텍스트메뉴에서 Run As > Run on Server (Tomcat 기반)를 클릭한다. Tomcat Server가 정상적으로 시작되었으면 브라우저를 열고 주소창에 http://localhost:8080/anyframe.sample.cxf.jaxws를 입력하여 실행 결과를 확인한다.• Eclipse 기반 실행 - WTP 활용Eclipse에서 압축 해제 프로젝트를 import한 후, build.xml 파일을 실행하여 참조 라이브러리를 src/main/webapp 폴더의 WEB-INF/lib내로 복사시킨다. 해당 프로젝트를 선택하고 마우스 오른쪽 버튼을 클릭한 후, 컨텍스트 메뉴에서 Run As > Run on Server를 클릭한다. Tomcat Server가 정상적으로 시작되었으면 브라우저를 열고 주소창에 http://localhost:8080/anyframe.sample.cxf.jaxws를입력하여 실행 결과를 확인한다. (* build.xml 파일 실행을 위해서는 ${ANT_HOME}/lib 내에 mavenant-task-2.0.10.jar파일이 있어야 한다.)22


Databinding• [참고] Eclipse 내 프로젝트에서 Validation Error 발생 시 대처Eclipse에서 압축 해체 프로젝트를 import한 후, Eclipse Preferences 화면의 Validation 메뉴에서XML Validator 항목의 체크 박스를 제거하고 Apply 버튼을 선택하여 적용하면 src/main/resources소스폴더의 spring/context-cxf.xml 파일과 springmvc/cxf-servlet.xml 파일에서 나타나던 ValidationError가 없어질 것이다. 기능 동작 상에는 전혀 문제가 없다.표 3.1. Download ListNamehsqldb.movie.zipanyframe.sample.cxf.jaxws.zipmaven-ant-tasks-2.0.10.jarDownloadDownload [http://dev.anyframejava.org/docs/anyframe/plugin/foundation/4.6.0/reference/sample/hsqldb.movie.zip]Download [http://dev.anyframejava.org/docs/anyframe/plugin/cxf/4.5.2/reference/sample/anyframe.sample.cxf.jaxws.zip]Download [http://dev.anyframejava.org/docs/anyframe/plugin/foundation/4.6.0/reference/sample/maven-ant-tasks-2.0.10.jar]• 참고자료• JSR 222: Java Architecture for XML Binding (JAXB) 2.0 [http://jcp.org/en/jsr/detail?id=222]• Java Architecture for XML Binding (JAXB) [http://java.sun.com/developer/technicalArticles/WebServices/jaxb/]• SOAP Message Transmission Optimization Mechanism [http://www.w3.org/TR/soap12-mtom/]• Apache <strong>CXF</strong> User's Guide - JAXB Databinding [http://cwiki.apache.org/<strong>CXF</strong>20DOC/jaxb.html]• Apache <strong>CXF</strong> User's Guide - MTOM Attachments with JAXB [http://cwiki.apache.org/<strong>CXF</strong>20DOC/mtom-attachments-with-jaxb.html]23


4.JAX-WS FrontendWeb Services 표준 API인 JAX-WS를 사용하여 Annotation 설정을 통해 Web Services를 구현할 수 있게해주는 Frontend 모델이다.JAX-WS(Java API for XML Web Services)는 웹 서비스를 작성하는 자바 API로써, Java EE의 일부이다. 다른Java EE의 자바 API와 같이, JAX-WS는 Java SE 5에서 도입된 어노테이션(Annotation)을 사용하여 웹 서비스 클라이언트 및 서버 모듈의 개발 및 배포를 쉽게 하고 있다. JAX-WS는 JAX-RPC 표준을 발전 시킨 개념으로 XML의 바인딩을 위한 JAXB 표준과 표준 스트리밍 파서를 위한 SAX 표준, 기능이 향상된 새로운SAAJ 표준을 기반으로 통합, 발전된 웹 서비스 기술 표준이다. JAX-WS의 특징을 살펴보면 다음과 같다.• JAX-RPC에 비해 Web Service 작성 편리JAX-RPC와 비교해보았을때 Web Service 작성이 매우 편리해진 장점을 갖고 있다. Annotation 설정을통해 Web Service Endpoint 작성 및 자바 타입과 WSDL 간의 매핑 등을 명시적으로 수행할 수 있다.기존의 JAX-RPC 환경에서 Web Service를 생성하기 위해 작성해야만 했던 Web Service 배치 서술자등을 모두 Annotation으로 대체 가능함으로써 Web Service 작성의 어려움을 크게 없애준다.• Annotation을 통해 하는 작업자바와 WSDL의 매핑 및 자바 타입과 WSDL에서 참조하는 메시지의 Schema 타입으로의 매핑을 담당한다. 실제 Web Service 메시지를 처리하는 Runtime Process 중에 필요한 정보를 제공하며 WebService 호출에 응답하는데 사용된다.• Annotation 관련 Spec.JAX-WS 2.0에서 사용하게 되는 Annotation은 Web Services Metadata(JSR-181) Spec.과 JAX-WS 2.0Spec.에 분리 정의되어 있다. 이외의 메시지 타입 매핑을 위해 사용되는 Annotation은 JAXB 2.0Spec.에 정의되어 있다. Web Services Metadata(JSR-181) Spec.에 정의된 대표적인 Annotation으로는 다음과 같은 것들이 있다.(javax.jws.WebService, javax.jws.WebMethod, javax.jws.WebParam,javax.jws.WebResult, javax.jws.soap.SOAPBinding)JAX-WS의 프로세스를 그림으로 살펴보면 다음과 같다.다음은 JAX-WS Frontend를 Server와 Client 단에서 어떻게 사용해야 하는지에 대한 사용법이다. JAX-WS Frontend는 크게 JAX-WS Frontend API를 사용하여 서버와 클라이언트를 작성하는 방식과 SpringConfiguration을 이용하는 방식으로 구분하여 사용될 수 있다.• Server Configuration1. Web Service 작성24


JAX-WS Frontend2. 서버 구동(3가지 방식 중 택1)• Spring Configuration XML - tag 사용 (추천 방식)• Spring Configuration XML - tag 사용• [Server] JAX-WS Frontend API 사용• Client Configuration1. 클라이언트 작성(2가지 방식 중 택1)• Spring Configuration XML - tag 사용 (추천 방식)• [Client] JAX-WS Frontend API 사용• [참고] Web Services 작성 시 Annotation 설정 방법4.1.Web Service 작성Web Service로 노출시킬 서비스를 작성하는데, 일반 서비스 Bean 개발 방식과 거의 동일하다. 단, 인터페이스 클래스에 @WebService Annotation이 설정되어야 함에 유의하도록 한다.4.1.1.Samples다음은 Web Service로 노출시킬 Movie Service에 대한 예제이다. 서비스는 일반 Spring Bean 개발과 동일하게 인터페이스 클래스, 구현 클래스, DAO(Data Access Object) 클래스, VO(Value Object) 클래스들로 구성되어 있다.• Interface Class다음은 Movie Service의 인터페이스 클래스를 작성한 MovieService.java 의 일부이다. 인터페이스 클래스 상단에 @WebService Annotation을 작성해줘야 한다. @WebService Annotation의 속성 값들도다양하게 존재하고, 각 메소드와 파라미터 별로 정의할 수 있는 Annotation의 종류도 여러가지가 있으나 필수 사항으로 필요한 Annotation은 @WebService뿐이다. 다른 종류의 Annotation에 대해서 추가 작성하는 방법에 대해서는 [참고] Web Services 작성 시 Annotation 설정 방법 을 참고하도록 한다.@WebService@XmlSeeAlso(Movie.class)public interface MovieService extends GenericService {Page getPagingList(SearchVO searchVO) throws Exception;@XmlJavaTypeAdapter(<strong>CXF</strong>MapAdapter.class)Map getMovieWithMap(String movieId) throws Exception;public void create(Movie movie) throws Exception;public void update(Movie movie) throws Exception;@WebMethod(exclude = true)public void remove(String movieId) throws Exception;중략...• Implementation ClassInterface Class를 구현한 클래스로 Web Service 구현과 관련된 부분 없이 작성될 수 있다. 다음은 Movie Service의 인터페이스 클래스를 구현한 MovieServiceImpl.java 의 일부이다. 내부적으로MovieDAO를 사용하여 Movie 정보를 관리하고 있다. 구현 클래스 상단에 @WebService Annotation을25


JAX-WS Frontend추가 작성해줄 수도 있다. 이미 인터페이스 클래스 상단에 @WebService Annotation을 작성해주었으므로 여기서는 생략시킨다. Annotation 설정 방법에 대해서는 [참고] Web Services 작성 시 Annotation설정 방법 을 참고하도록 한다.@Service("movieService")public class MovieServiceImpl extends GenericServiceImplimplements MovieService {@ResourceMovieDao movieDao;@PostConstructpublic void initialize() {super.setGenericDao(movieDao);}public Page getPagingList(SearchVO searchVO) throws Exception {return this.movieDao.getPagingList(searchVO);}중략...4.2.Spring Configuration XML -jaxws:endpoint tag 사용작성된 서비스를 Web Service로 노출시키는 서버를 구동하기 위해서 3가지 방식이 지원된다. 이중 Spring Configuration XML - tag를 사용하여 서버를 구동시켜보도록 한다. tag의 각 속성값에 대한 설명은 다음 표와 같다. 아래 표에 나와있지 않은 속성들도여러 가지가 존재한다. 단, 여기서는 필수적으로 작성해야 하는 속성값에 대한 설명을 작성해놓은 것으로 나머지 속성값들에 대한 설명은 JAX-WS Spring Configuration [http://cwiki.apache.org/<strong>CXF</strong>20DOC/jax-ws-configuration.html] 을 참고하도록 한다.Property Name Description Required DefaultValueid spring bean id를 작성한다. Y N/Aimplementor구현 클래스를 작성한다. 클래스명 대신에 spring bean id로대체하고자 하면 bean id 앞에 #을 붙여서 작성하면 된다.address 서비스가 동작할 주소를 상대 경로로 작성한다. Y N/A4.2.1.Samples다음은 Spring Configuration XML - tag를 사용하여 Movie Service를 Web Service로노출시키는 서버를 구동하는 예제이다.• 다음은 비즈니스 레이어의 서비스를 Web Service로 노출시키는 tag 속성을 정의한 context-cxf.xml 의 일부이다.ConfigurationYN/A26


JAX-WS FrontendJetty 혹은 Tomcat 서버 등의 WAS를 이용하여 웹 어플리케이션을 구동하고 비즈니스 레이어의서비스를 Web Service로 노출시키게 되는데, 이때 web.xml 파일에 Spring 속성 정의 XML 파일을 org.springframework.web.context.ContextLoaderListener를 이용하여 등록시켜 줘야 한다. 다음은<strong>CXF</strong>Servlet과 ContextLoaderListener를 정의한 web.xml의 일부이다.


JAX-WS FrontendProperty Name Description Required DefaultValueserviceBean구현 클래스를 작성한다. 클래스명 대신에 spring bean id로대체하고자 하면 bean id 앞에 #을 붙여서 작성하면 된다.address 서비스가 동작할 주소를 상대 경로로 작성한다. Y N/A4.3.1.Samples다음은 Spring Configuration XML - tag를 사용하여 Movie Service를 Web Service로 노출시키는 서버를 구동하는 예제이다.• Configuration다음은 서버 사이드의 서비스를 Web Services로 노출시키는 tag 속성을 정의한 파일 예이다.YN/AJetty 혹은 Tomcat 서버 등의 WAS를 이용하여 웹 어플리케이션을 구동하고 비즈니스 레이어의서비스를 Web Service로 노출시키게 되는데, 이때 web.xml 파일에 Spring 속성 정의 XML 파일을 org.springframework.web.context.ContextLoaderListener를 이용하여 등록시켜 줘야 한다. 다음은<strong>CXF</strong>Servlet과 ContextLoaderListener를 정의한 web.xml의 일부이다.


JAX-WS Frontend<strong>CXF</strong>Servlet/ws/*중략...4.4.Server: JAX-WS Frontend API 사용작성된 서비스를 Web Service로 노출시키는 서버를 구동하기 위해서 3가지 방식이 지원된다. 이중 JAX-WS Frontend API를 이용하여 직접 자바코드를 작성하여 서버를 구동시켜보도록 한다. Apache <strong>CXF</strong>에서제공하는 JAX-WS Frontend API를 직접 호출하여 작성하는 것이 가능하며, JaxWsServerFactoryBean 클래스를 Spring Configuration 파일의 Bean으로 등록하여 설정하는 것도 가능하다.4.4.1.Samples다음은 Apache <strong>CXF</strong>에서 제공하는 JaxWsServerFactoryBean을 직접 이용하여 Movie Service를 WebService로 노출시키는 서버를 구동하는 예제이다.• Apache <strong>CXF</strong> JaxWsServerFactoryBean을 사용한 서버 구동다음은 비즈니스 레이어의 서비스를 Web Service로 노출시키는 서버를 구동하는 코드 작성 예이다.MovieServiceImpl implementor = new MovieServiceImpl();JaxWsServerFactoryBean svrFactory=new JaxWsServerFactoryBean();svrFactory.setServiceClass(MovieService.class);svrFactory.setAddress("http://localhost:8080/anyframe.sample.cxf.jaxws/ws/movieList");svrFactory.setServiceBean(implementor);svrFactory.create();4.5.Spring Configuration XML - jaxws:clienttag 사용Web Services에 접근하기 위한 클라이언트 작성 방식에는 2가지 방식이 지원된다. 이중 SpringConfiguration XML - tag를 사용하여 클라이언트를 작성하여 Web Services에 접근해보도록 한다. tag의 각각의 Attribute 속성값에 대한 설명은 다음 표와 같다. 아래 표에 나와있지 않은 속성들도 여러 가지가 존재한다. 단, 여기서는 필수적으로 작성해야 하는 Attribute 속성값에대한 설명을 작성해놓은 것으로 나머지 속성 값들에 대한 설명은 JAX-WS Spring Configuration [http://cwiki.apache.org/<strong>CXF</strong>20DOC/jax-ws-configuration.html] 을 참고하도록 한다.Property Name Description Required Default ValueidserviceBeanspring bean id를 작성한다.서비스의 인터페이스 클래스를 작성한다.address 서비스 접근 URLAddress를 절대 경로로작성한다.4.5.1.SamplesYYYN/AN/AN/A다음은 Spring Configuration XML - tag를 사용하여 Movie Service에 접근하는 예제이다.29


JAX-WS Frontend• Configuration다음은 Web Services로 노출된 Movie Service에 접근하는 tag 속성을 정의한 cxfservlet.xml의 일부이다.• Controller다음은 앞서 정의한 속성 설정 파일들을 기반으로 하여 Web Services로 노출된 Movie Service에 접근하는 Controllert 클래스인 MovieController.java의 일부이다.@Controllerpublic class MovieController {@Resource(name = "wsClientMovieService")private MovieService wsMovieService;@RequestMapping("/cxfGetMovie.do")public ModelAndView get(HttpServletRequest request) throws Exception {String movieId = request.getParameter("movieId");if (!StringUtils.isBlank(movieId)) {Map movieMap = wsMovieService.getMovieWithMap(movieId);Movie gettedMovie = (Movie) movieMap.get("movie");request.setAttribute("movie", gettedMovie);}return new ModelAndView("/WEB-INF/jsp/cxf/movie/viewMovie.jsp");}중략...4.6.Client: JAX-WS Frontend API 사용Web Service에 접근하기 위한 클라이언트 작성 방식에는 2가지 방식이 지원된다. 이중 JAX-WS FrontendAPI를 직접 이용한 클라이언트를 작성하여 Web Service에 접근해보도록 한다. Apache <strong>CXF</strong>에서 제공하는 JAX-WS Frontend API를 직접 호출하여 작성하는 것이 가능하며, JaxWsProxyFactoryBean 클래스를Spring Configuration 파일의 Bean으로 등록하여 설정하는 것도 가능하다.4.6.1.Samples다음은 Apache <strong>CXF</strong>에서 제공하는 JaxWsProxyFactoryBean를 직접 이용하여 Web Services로 노출된Movie Service에 접근하는 예제이다.• Apache <strong>CXF</strong> JaxWsProxyFactoryBean 사용한 클라이언트다음은 Apache <strong>CXF</strong>에서 제공하는 JaxWsProxyFactoryBean 클래스를 사용하여 Web Services로 노출된 Movie Service에 접근하는 코드 작성 예이다.JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();factory.setServiceClass(MovieService.class);factory.setAddress("http://localhost:8080/anyframe.sample.cxf.jaxws/ws/movieList");MovieService movieService = (MovieService) factory.create();Map movieMap = movieService.getMovieWithMap("MV-00003");30


JAX-WS Frontend4.7.Annotation 작성@WebService()만 필수 사항이고 대부분 annotation의 경우 디폴트 값이 제공되므로 작성이 불필요 하다.4.7.1.@WebService (javax.jws.WebService)Annotation을 포함하고 있는 자바 클래스가 Web Service Endpoint 인터페이스 클래스 혹은 구현 클래스임을 명시할 때 사용하며 SEI와 구현 클래스에 설정한다.(필수 사항) 모든 Property의 값을 작성할 필요는 없으나 되도록 많은 정보를 작성하는 것을 권장한다. SEI에 더 많은 Annotation 정보를 작성할 수록잘 정의된 WSDL을 생성시킬 수 있기 때문이다. Property에 대한 세부 내용은 다음 표와 같다.Property Name Type 필수 WSDLMappingDefault설명name String X wsdl:portType 클래스명 웹 서비스 명으로wsdl:portType으로 매핑됨, 기본값은 인터페이스클래스 혹은 구현 클래스의 패키지를 제외한 명targetNamespace String X N/A 패키지 명 웹 서비스로부터 생성된XML element와 WSDL에사용될 XMLnamespaceserviceName String X wsdl:service 클래스명+"Service"wsdlLocation String X N/A 서비스 디플로이 URISEI에 설정불가 , 서비스 명으로wsdl:service로 매핑됨, 기본값은 인터페이스클래스 혹은 구현 클래스의 패키지명을 제외한명+"Service"미리 정의된 WSDL의 위치로WSDL에 정의된 portType,binding은 서비스 구현 클래스에 작성된 값들과 일치해야 함31


JAX-WS FrontendProperty Name Type 필수 WSDLMappingDefault설명endpointInterface String X N/A SEI의 패키지명을 포함한클래스명, 구현 클래스 명+"Port"portName String X wsdl:port 구현 클래스명+"Port"SEI에 설정 불가 , 구현 클래스의 SEI 명SEI에 설정 불가 , wsdl:port로 매핑됨, 기본값은 구현클래스명+"Port"• @WebService annotation 설정이 적용된 클래스 내의 메소드 규칙• 구현 클래스의 @WebService annotation이 SEI를 참조하는 경우 구현 클래스에 @WebMethodannotation은 없어야 한다.• SEI의 모든 공용 메소드는 @WebMethod annotation 설정 여부와 관계 없이 Web Service로 노출된 메소드로 간주된다.• SEI를 참조하지 않는 구현 클래스의 경우 @WebMethod annotation이 exclude=true 값으로 지정되면 해당 메소드가 Web Service로 노출되지 않는다.4.7.2.@WebParam (javax.jws.WebParam)Web Service의 자바 메소드의 입력 파라미터와 WSDL 파일에서 파라미터를 표현하는 XML element 간의 매핑을 설정하며 Property에 대한 세부 내용은 다음 표와 같다.Property Type 필수 설명name String X 파라미터명으로 RPC style의 Web Service의 경우 파라미터를 나타내는wsdl:part으로 매핑되고, Document style의 Web Service의 경우 파라미터를 나타내는 XML element의 로컬 네임이 됨. 기본값은 메소드의 파라미터명targetNamespace String X 파라미터의 XML namespace로 파라미터가 XML element로 대응되는Document style의 Web Service에서만 사용됨. 기본값은 Web Service의targetNamespacemode Enum X 파라미터가 전달되는 방향으로 IN, OUT 혹은 INOUT 중 하나 선택. 기본값은INheader Boolean X true로 설정되면 파라미터를 SOAP 메시지 BODY가 아닌 SOAP 메시지헤더로부터 가져옴. 기본값은 falsepartName String X RPC 혹은 Document style의 매개변수 양식이 BARE인 경우에만 사용됨4.7.3.@WebMethod (javax.jws.WebMethod)Web Service 메소드로 공개되는 메소드를 설정할 때 사용하며 @WebMethod annotation은 @WebServiceannotation 설정이 된 클래스에서만 지원된다. Property에 대한 세부 내용은 다음 표와 같다.Property Type 필수 설명operationName String X 공개되는 메소드 명으로 wsdl:operation으로 매핑됨. 기본값은 자바 메소드 명32


JAX-WS FrontendProperty Type 필수 설명action String X 메소드에 적용되는 action 속성으로 SOAPBinding의 경우SOAP 메시지에서 SOAPAction 헤더의 값을 결정exclude Boolean X Web Service에서 메소드를 제외시킬지 여부 지정함. 기본값은 false4.7.4.@OneWay (javax.jws.OneWay)입력 값은 있으나 리턴 값이 없는 단방향 메소드를 정의할 때 사용한다. @WebMethod annotation과 함께 사용되며 별도의 속성 정의가 필요없다.4.7.5.@WebResult (javax.jws.WebResult)Web Service 메소드로 공개되는 메소드의 리턴 값과 WSDL의 리턴 값을 표현하는 XML 요소 간의 매핑을 설정할 때 사용한다. Property에 대한 세부 내용은 다음 표와 같다.Property Type 필수 설명name String X WSDL에서 리턴 값을 나타내는 element 명, RPC style의 WebService에서는 리턴 값을 나타내는 wsdl:part 에 매핑되며,Document style의 Web Service에서는 리턴 값을 나타내는XML element의 로컬targetNamespace String X 리턴값의 XML namespace로 RPC style의 Web Service 혹은Document style의 매개변수 양식이 BARE인 Web Service에서만 사용됨. 기본값은 Web Service의 targetNamespace값header String X 결과를 헤더에서 수행하는지 여부 지정. 기본값은 falsepartName String X RPC 혹은 Document style의 매개변수 양식이 BARE인 경우에만 사용됨4.7.6.Samples다음은 Movie Service의 인터페이스 클래스에 여러 가지 Annotation을 설정해 본 예제이다.• Interface Class다음은 Movie Service의 인터페이스 클래스를 작성한 MovieService.java 의 일부이다. 인터페이스클래스 상단에 @WebService Annotation 작성은 필수 사항이다. 이외에 @WebMethod, @Oneway,@WebParam Annotation을 설정해보고 어떻게 동작하는지 살펴보도록 한다.@WebService@XmlSeeAlso(Movie.class)public interface MovieService extends GenericService {@WebMethod(exclude = true)public void remove(String movieId) throws Exception;// ================= method for Annotation tests@WebMethod(operationName = "testAnnotationMethodInclude")public void testAnnotationMethod();@Onewaypublic String testAnnotationOneWay();public String testAnnotationWebParam(@WebParam(name = "movieAnnotationWebParam") String input);중략...33


JAX-WS Frontend• Implementation Class다음은 Movie Service의 인터페이스 클래스를 작성한 MovieServiceImpl.java 의 일부이다.@Service("movieService")public class MovieServiceImpl extends GenericServiceImplimplements MovieService {// ================= method for Annotation testspublic void testAnnotationMethod() {System.out.println("testAnnotationMethod method is called.");}public String testAnnotationOneWay() {System.out.println("testAnnotationOneWay method is called.");return "testAnnotationOneWay";}public String testAnnotationWebParam(String input) {System.out.println("testAnnotationWebParam method is calledwith the input parameter=" + input);return "testAnnotationWebParam";}중략...• Test case다음은 Apache <strong>CXF</strong>에서 제공하는 JaxWsProxyFactoryBean 클래스를 사용하여 Web Services로 노출된 Movie Service에 접근하는 코드 작성 예이다. WebServices Annotation 설정 값에 따라 어떻게 동작하는지 확인해보도록 한다.JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();factory.setServiceClass(MovieService.class);factory.setAddress("http://localhost:8080/anyframe.sample.cxf.jaxws/ws/movieList");MovieService movieService = (MovieService) factory.create();/*** @WebMethod annotation을 이용하여 특정 method를 Web Service method로* 노출되지 않도록 한다.* @WebMethod의 속성 값 중 exclude 값을 true로 설정한다.* (ex. @WebMethod(exclude=true) )*/try {movieService.remove("MV-00003");} catch (WebServiceException e) {// Exception should be occurred.}/*** @WebMethod annotation을 이용하여 특정 method name을 다른 name으로 변경하여* 호출가능하도록 한다.* @WebMethod의 속성 값 중 operationName 값을 다른 name으로 설정한다.* (ex. @WebMethod(operationName="testAnnotationMethodInclude") )** 실제 SEI에서 제공하는 method는 testAnnotationMethod 뿐이고,* @WebMethod 속성 값 중 operationName값을* testAnnotationMethodInclude로 설정해놓았으므로,* Client에서 Web Service method를 호출할 때에는* testAnnotationMethodInclude method를 갖는* Service Interface class를 재정의해서 호출하여 사용하도록 한다.*/34


JAX-WS Frontendtry {movieService.testAnnotationMethodInclude();} catch (Exception e) {// It should not be failed.}/*** @OneWay annotation을 이용하여* 특정 method의 입력값은 있을 수 있으나 리턴 값이 없는 단방향 method를* 정의하여 사용하도록 한다.* @OneWay의 다른 속성값 설정은 필요 없다.* (ex. @OneWay )*/try {movieService.testAnnotationOneWay().trim();fail();} catch (NullPointerException e) {// Exception should be occurred.}4.8.[참고] Spring Configuration XMLSchemaApache <strong>CXF</strong>에서 제공하는 Tag를 사용하여 Server와 Client 설정 시 Spring Configuration XML 파일 상단에 아래와 같이 Schema를 등록해줘야 한다. JAX-WS Frontend 사용 시에는 jaxws Namespace와 Schema파일을 반드시 등록해줘야 한다.중략...4.9.Resources• 다운로드다음에서 테스트 DB를 포함하고 있는 hsqldb.movie.zip과 sample 코드를 포함하고 있는anyframe.sample.cxf.jaxws.zip 파일을 다운받은 후, 압축을 해제한다. 그리고 hsqldb 폴더 내의start.cmd (or start.sh) 파일을 실행시켜 테스트 DB를 시작시켜 놓는다.• Maven 기반 실행Command 창에서 압축 해제 폴더로 이동한 후 mvn clean jetty:run이라는 명령어를 실행시킨다. Jetty Server가 정상적으로 시작되었으면 브라우저를 열고 주소창에 http://localhost:8080/anyframe.sample.cxf.jaxws를 입력하여 실행 결과를 확인한다.• Eclipse 기반 실행 - m2eclipse, WTP 활용35


JAX-WS FrontendEclipse에서 압축 해제 프로젝트를 import한 후, 해당 프로젝트에 대해 마우스 오른쪽 버튼을 클릭하고 컨텍스트 메뉴에서 Maven > Enable Dependency Management를 선택하여 컴파일 에러를해결한다. (위와 같이 했음에도 컴파일 에러가 사라지지 않으면 컨텍스트 메뉴에서 Properties >JavaEE Module Dependencies를 클릭하고, 오른쪽 JAR/Module 목록에서 Maven Dependencies 항목을 체크하도록 한다.) 그리고 해당 프로젝트에 대해 마우스 오른쪽 버튼을 클릭한 후, 컨텍스트메뉴에서 Run As > Run on Server (Tomcat 기반)를 클릭한다. Tomcat Server가 정상적으로 시작되었으면 브라우저를 열고 주소창에 http://localhost:8080/anyframe.sample.cxf.jaxws를 입력하여 실행 결과를 확인한다.• Eclipse 기반 실행 - WTP 활용Eclipse에서 압축 해제 프로젝트를 import한 후, build.xml 파일을 실행하여 참조 라이브러리를 src/main/webapp 폴더의 WEB-INF/lib내로 복사시킨다. 해당 프로젝트를 선택하고 마우스 오른쪽 버튼을 클릭한 후, 컨텍스트 메뉴에서 Run As > Run on Server를 클릭한다. Tomcat Server가 정상적으로 시작되었으면 브라우저를 열고 주소창에 http://localhost:8080/anyframe.sample.cxf.jaxws를입력하여 실행 결과를 확인한다. (* build.xml 파일 실행을 위해서는 ${ANT_HOME}/lib 내에 mavenant-task-2.0.10.jar파일이 있어야 한다.)• [참고] Eclipse 내 프로젝트에서 Validation Error 발생 시 대처Eclipse에서 압축 해체 프로젝트를 import한 후, Eclipse Preferences 화면의 Validation 메뉴에서XML Validator 항목의 체크 박스를 제거하고 Apply 버튼을 선택하여 적용하면 src/main/resources소스폴더의 spring/context-cxf.xml 파일과 springmvc/cxf-servlet.xml 파일에서 나타나던 ValidationError가 없어질 것이다. 기능 동작 상에는 전혀 문제가 없다.표 4.1. Download ListNamehsqldb.movie.zipanyframe.sample.cxf.jaxws.zipmaven-ant-tasks-2.0.10.jarDownloadDownload [http://dev.anyframejava.org/docs/anyframe/plugin/foundation/4.6.0/reference/sample/hsqldb.movie.zip]Download [http://dev.anyframejava.org/docs/anyframe/plugin/cxf/4.5.2/reference/sample/anyframe.sample.cxf.jaxws.zip]Download [http://dev.anyframejava.org/docs/anyframe/plugin/foundation/4.6.0/reference/sample/maven-ant-tasks-2.0.10.jar]• 참고자료• JAX-WS 2.0 Specification [http://jcp.org/en/jsr/detail?id=224]• Building Web Services with JAX-WS [http://java.sun.com/javaee/5/docs/tutorial/doc/bnayl.html]• JAX-WS Spring Configuration [http://cwiki.apache.org/<strong>CXF</strong>20DOC/jax-ws-configuration.html]36


5.Simple FrontendSimple Frontend는 JAX-WS Frontend와 다르게 annotation 설정 필요 없이 Web Services를 구현할 수 있게해주는 Frontend 모델이다. 클래스를 WSDL 모델에 매핑하는데 Reflection을 이용하며 현재 JAXB binding과 함께 사용 시 문제가 발생하므로 Aegis databinding을 사용하도록 함에 유의한다. Simple Frontend의구현 방법은 매우 간편하나 실제 사용 시 제약 사항이 발생할 수 있으므로 표준 방식인 JAX-WS Frontend사용을 추천한다.다음은 Simple Frontend를 Server와 Client 단에서 어떻게 사용해야 하는지에 대한 사용법이다. SimpleFrontend는 크게 Simple Frontend API 코드를 사용하여 서버와 클라이언트를 작성하는 방식과 SpringConfiguration을 이용하는 방식으로 구분하여 사용될 수 있다.• Server Configuration1. Web Services 작성2. 서버 구동(2가지 방식 중 택1)• [Server] Simple Frontend API 코드 사용• Spring Configuration XML - tag 사용>• Client Configuration1. 클라이언트 작성(2가지 방식 중 택1)• [Client] Simple Frontend API 코드 사용• Spring Configuration XML - tag 사용5.1.Web Services 작성Web Services로 노출시킬 서비스를 작성하는데, 일반 서비스 빈 개발 방식과 완벽히 동일하다. JAX-WSFrontend와 다르게 인터페이스 클래스에 어떠한 Annotation도 설정할 필요가 없다.5.1.1.Samples다음은 Web Service로 노출시킬 Movie Service에 대한 예제이다. 서비스는 일반 Spring Bean 개발과동일하게 인터페이스 클래스, 구현 클래스, DAO(Data Access Object) 클래스, VO(Value Object)들로 구성되어 있다.• Interface Class다음은 Movie Service의 인터페이스 클래스를 작성한 MovieService.java 의 일부이다.public interface MovieService {Log LOGGER = LogFactory.getLog(MovieService.class.getName());public List findMovieListAll() throws Exception;public Map findMovieMapAll() throws Exception;public List findMovieList(Country country, Category category) throws Exception;public Movie findMovie(String movieId) throws Exception;public void createMovie(Movie movie) throws Exception;37


Simple Frontendpublic void updateMovie(Movie movie) throws Exception;public void removeMovie(Movie movie) throws Exception;...중략• Implementation ClassInterface Class를 구현한 구현 클래스로 Web Service 구현과 관련된 부분 없이 작성한다. 다음은 Movie Service의 인터페이스 클래스를 구현한 MovieServiceImpl.java 의 일부이다. 내부적인MovieDAO 를 사용하여 Movie 정보를 관리하고 있다.public class MovieServiceImpl implements MovieService {private MovieDAO movieDAO = null;public void setMovieDAO(MovieDAO movieDAO) {this.movieDAO = movieDAO;}public List findMovieListAll() throws Exception {return this.movieDAO.findMovieListAll();}public Map findMovieMapAll() throws Exception {return this.movieDAO.findMovieMapAll();}public List findMovieList(Country country, Category category)throws Exception {return this.movieDAO.findMovieList(country, category);}public Movie findMovie(String movieId) throws Exception {return this.movieDAO.fineMovie(movieId);}public void createMovie(Movie movie) throws Exception {this.movieDAO.createMovie(movie);}중략...5.2.Server: Simple Frontend API 코드 사용작성된 서비스를 Web Services로 노출시키는 서버를 구동하기 위해서 2가지 방식이 지원된다. 이중Apache <strong>CXF</strong>에서 제공하는 Simple Frontend API 코드를 직접 작성하여 서버를 구동시켜보도록 한다.5.2.1.Samples다음은 Apache <strong>CXF</strong>에서 제공하는 ServerFactoryBean를 직접 이용하여 Movie Service를 Web Service로노출시키는 서버를 구동하는 예제이다.• Apache <strong>CXF</strong> ServerFactoryBean 사용한 서버 구동다음은 서버 사이드의 서비스를 Web Services로 노출시키는 서버를 구동하는 코드 작성 예이다.MovieServiceImpl movieImpl = new MovieServiceImpl();ServerFactoryBean svrFactory = new ServerFactoryBean();svrFactory.setServiceClass(MovieService.class);38


Simple FrontendsvrFactory.setAddress("http://localhost:9002/Movie");svrFactory.setServiceBean(movieImpl);svrFactory.getServiceFactory().setDataBinding(new AegisDatabinding());svrFactory.create();5.3.Spring Configuration XML -simple:server tag 사용작성된 서비스를 Web Services로 노출시키는 서버를 구동하기 위해서 2가지 방식이 지원된다.이중 Spring Configuration XML - tag를 사용하여 서버를 구동시켜보도록 한다. tag의 각각의 Attribute 속성값에 대한 설명은 다음 표와 같다. 아래 표에 나와있지 않은 속성들도 여러 가지가 존재한다. 단, 여기서는 필수적으로 작성해야 하는 Attribute 속성값에 대한 설명을 작성해놓은 것으로 나머지 속성 값들에 대한 설명은 Simple Frontend Spring Configuration [http://cwiki.apache.org/<strong>CXF</strong>20DOC/simple-frontend-configuration.html] 을 참고하도록 한다.Property Name Description Required DefaultValueid spring bean id를 작성한다. Y N/AserviceBean구현 클래스를 작성한다. 클래스명 대신에 spring bean id로대체하고자 하면 bean id 앞에 #을 붙여서 작성하면 된다.YN/AserviceClass 서비스의 인터페이스 클래스를 작성한다. Y N/Aaddress 서비스가 동작할 주소를 상대 경로로 작성한다. Y N/A[하위 element]Simple Frontend는 디폴트 databinding인 JAXB를 사용하지 않고 AegisDatabinding을 사용해야 하므로 39


Simple FrontendJetty 혹은 Tomcat 서버 등의 WAS를 이용하여 웹 어플리케이션을 구동하고 서버 사이드의 서비스를 Web Services로 노출시키게 되는데, 이때 web.xml 파일에 Spring Configuration XML 파일을 org.springframework.web.context.ContextLoaderListener를 이용하여 등록시켜 줘야 한다. 다음은<strong>CXF</strong>Servlet과 ContextLoaderListener를 정의한 web.xml 의 일부이다.contextConfigLocationWEB-INF/context-movie-server.xmlorg.springframework.web.context.ContextLoaderListener<strong>CXF</strong>Servlet<strong>CXF</strong> Servletorg.apache.cxf.transport.servlet.<strong>CXF</strong>Servlet1<strong>CXF</strong>Servlet/*5.4.Client: Simple Frontend API 코드 사용Web Services에 접근하기 위한 클라이언트 작성 방식에는 2가지 방식이 지원된다. 이중 pache <strong>CXF</strong>에서 제공하는 Simple Frontend API 코드를 직접 이용한 클라이언트를 작성하여 Web Services에 접근해보도록 한다.5.4.1.Samples다음은 Apache <strong>CXF</strong>에서 제공하는 ClientProxyFactoryBean를 직접 이용하여 Web Services로 노출된Movie Service에 접근하는 예제이다.• Apache <strong>CXF</strong> ClientProxyFactoryBean 사용한 클라이언트다음은 Apache <strong>CXF</strong>에서 제공하는 ClientProxyFactoryBean 클래스를 사용하여 Web Services로 노출된 Movie Service에 접근하는 코드 작성 예이다.ClientProxyFactoryBean factory = new ClientProxyFactoryBean();factory.setServiceClass(MovieService.class);factory.setAddress("http://localhost:9002/Movie");40


Simple Frontendfactory.getServiceFactory().setDataBinding(new AegisDatabinding());MovieService movieService = (MovieService)factory.create();Movie movie= movieService.findMovie("001");5.5.Spring Configuration XML -simple:client tag 사용Web Services에 접근하기 위한 클라이언트 작성 방식에는 2가지 방식이 지원된다. 이중 SpringConfiguration XML - tag를 사용하여 클라이언트를 작성하여 Web Services에 접근해보도록 한다. tag의 각각의 Attribute 속성값에 대한 설명은 다음 표와 같다. 아래 표에 나와있지 않은 속성들도 여러 가지가 존재한다. 단, 여기서는 필수적으로 작성해야 하는 Attribute 속성값에대한 설명을 작성해놓은 것으로 나머지 속성 값들에 대한 설명은 Simple Frontend Spring Configuration 을 참고하도록 한다.Property Name Description Required DefaultValueid spring bean id를 작성한다. Y N/AserviceClass 서비스의 인터페이스 클래스를 작성한다. Y N/Aaddress 서비스 접근 URL Address를 절대 경로로 작성한다. Y N/A[하위 element] Simple Frontend는 디폴트 databinding인 JAXB 를 사용하지 않고 AegisDatabinding을 사용해야 하므로


Simple Frontend중략...5.7.Resources• 참고자료• Simple Frontend [http://cwiki.apache.org/<strong>CXF</strong>20DOC/simple-frontend.html]• Simple Frontend Spring Configuration [http://cwiki.apache.org/<strong>CXF</strong>20DOC/simple-frontendconfiguration.html]42


6.Asynchronous Invocation보통의 synchronous한 호출 방식과 함께, Apache <strong>CXF</strong>는 JAX-WS Spec.에 정의된 2가지(Polling approach,Callback approach) 형태의 비동기(asynchronous) 호출 방식을 지원한다. 즉, 클라이언트 사이드에서 서버 사이드의 Web Services를 호출 시 비동기적으로 호출하여 사용할 수 있게 하는 기능이다.Polling approach의 특징 을 살펴보면 다음과 같다.• 서버) 서비스 인터페이스에 메소드(메소드명: 대상 메소드 명 + "Async")를 추가 작성하는데, 이때 리턴타입이 Response인 메소드를 작성한다.• 클라이언트) 원격에 존재하는 메소드를 호출하기 위해, output 파라미터 없이 javax.xml.ws.Response객체를 리턴하는 특정 메소드를 호출한다.• javax.util.concurrency.Future 인터페이스를 상속받은 Response 객체는 응답 메시지가 도착했는지 여부를 확인하는 표를 받는다.Callback approach의 특징 을 살펴보면 다음과 같다.• 서버) 서비스 인터페이스에 메소드(메소드명: 대상 메소드 명 + "Async")를 추가 작성하는데, 이때 리턴 타입이 Future이며 AsynchHandler 파라미터를 추가로 갖는 메소드를 작성한다.• 클라이언트) AsyncHandler 클래스 구현이 필요하다.• 클라이언트) 원격에 존재하는 메소드를 호출하기 위해, 파라미터 중 하나가javax.xml.ws.AsyncHandler 타입인 callback 객체에 참조 관계가 있는 위에서 작성한 메소드를 호출한다.• 응답 메시지가 클라이언트에 도착하자마자, Apache <strong>CXF</strong> 런타임 환경은 응답 메시지의 컨텐츠에 응답 메시지를 전달해주기 위해 AsyncHandler 객체를 재호출한다.다음은 Asynchronous Method Invocation 기능을 사용하기 위해서 Server와 Client 단에서 어떤 작업을수행해야 하는지에 대한 내용이다. 2가지(Polling approach와 Callback approach) 형태의 asynchronous한 호출 방식에 대해서 하나의 예제를 가지고 살펴보도록 한다.6.1.Server ConfigurationApache <strong>CXF</strong>에서 제공하는 Tool을 이용하여 비동기적으로 Web Services의 메소드를 호출할 수 있도록지원하고 있다. 아래 예제를 통해서 Tool 사용 모습을 포함하여 어떻게 비동기적인 호출을 가능하게 하는지 살펴보도록 한다.Tool을 아직 준비하지 못했다면 Apache <strong>CXF</strong>를 다운로드 페이지 [http://cxf.apache.org/download.html]에서 내려 받아서 압축을 풀고 루트 폴더 하위의 bin 폴더 내에 존재하는 Tool을 사용하도록 한다.6.1.1.SamplesWeb Service로 노출시킬 Movie Service의 인터페이스 클래스를 대상으로 java2ws Tool을 사용하여 WSDL 파일을 생성해낸다. WSDL 파일을 생성한 이후, wsdl2java Tool을 통해 WSDL파일과 asynch_binding.xml 파일을 이용하여 asynchronous한 호출을 가능하게 하는 Java 소스 코드들(anyframe.sample.movie.jaxws.asynch.asynch_soap_http package 하위의 클래스들(SEI,WebServiceClient, complex type classes))을 생성한다. 이때 이미 WSDL 파일을 가지고 있다면 java2wsTool을 사용할 필요는 없다.• Temporary Interface Class다음은 Movie Service의 인터페이스 클래스를 작성한 MovieServiceAsynch.java의 일부이다. JAX-WS Frontend 모델을 이용하여 Web Service를 구현하므로, 인터페이스 클래스 상단에 @WebServiceAnnotation을 작성해줘야 한다. 인터페이스 메소드로는 findMovieListAll() 메소드를 정의하고, 클라이43


Asynchronous Invocation언트에서 asynchronous하게 이 메소드를 호출하고자 한다. 실제로는 이 인터페이스를 사용하지 않는다. WSDL 파일을 생성시키고자 하는 목적에서 작성한 것 이다. 실제로는 WSDL 파일로부터 생성된 인터페이스 클래스를 사용하게 됨에 유의하도록 한다.@WebService(targetNamespace = "http://asynch.jaxws.movie.sample.anyframe/asynch_soap_http")public interface MovieServiceAsynch {public List findMovieListAll() throws Exception;}...중략• WSDL 파일 생성인터페이스 클래스를 기준으로 WSDL 파일을 생성시키도록 한다. 이때 Apache <strong>CXF</strong>에서 제공하는Tool 중 java2ws을 이용하여 생성시킨다. Command Prompt 상에서 아래와 같은 명령어를 수행시키도록 한다. 수행 시키는 위치는 프로젝트가 존재하는 루트 폴더이다.command>java2ws -wsdl -cp target/classesanyframe.sample.movie.jaxws.asynch.MovieServiceAsynch다음은 생성된 WSDL 파일(MovieServiceAsynchService.wsdl) 의 일부이다. 생성된 후 soap:addresslocation 정보 등 수정하고 싶은 정보가 있는 경우 변경하도록 한다.


Asynchronous Invocationxmlns="http://java.sun.com/xml/ns/jaxws">true중략...• Java 코드 생성지금까지 준비된 WSDL 파일과 asynch_binding.xml 파일을 이용하여 Asynchronous 기능을 제공하는Java 소스 코드를 생성하도록 한다. 이때 Apache <strong>CXF</strong>에서 제공하는 Tool 중 wsdl2java을 이용하여 생성시킨다. Command Prompt 상에서 아래와 같은 명령어를 수행시키도록 한다. 수행 시키는 위치는프로젝트가 존재하는 루트 폴더이다.command>wsdl2java -d src -b src/test/resources/webservices/asynch/wsdl/asynch_binding.xmlsrc/test/resources/webservices/asynch/wsdl/MovieServiceAsynchService.wsdlTool을 통해 생성되는 Java 코드들은 모두 anyframe.sample.movie.jaxws.asynch.asynch_soap_httppackage 하위에 위치한다. MovieService의 인터페이스 클래스인 MovieServiceAsynch.java ,MovieService 접근을 위한 WebService Client 클래스인 MovieServiceAsynchService.java , JavaBeans클래스인 Movie.java 클래스 등 여러 가지의 Java 소스 코드가 생성된다. 다음은 생성된 인터페이스클래스인 MovieServiceAsynch.java 의 일부이다. 이 인터페이스 클래스가 실제로 사용된다. Pollingapproach 방식 및 Callback approach에서 사용되는 2개의 findMovieListAllAsync() 메소드와 추가로생성되어 있음을 확인할 수 있다.@WebService(targetNamespace = "http://asynch.jaxws.movie.sample.anyframe/asynch_soap_http",name = "MovieServiceAsynchService")@XmlSeeAlso( {ObjectFactory.class })public interface MovieServiceAsynch {@ResponseWrapper(localName = "findMovieListAllResponse",targetNamespace = "http://asynch.jaxws.movie.sample.anyframe/asynch_soap_http",className ="anyframe.sample.movie.jaxws.asynch.asynch_soap_http.FindMovieListAllResponse")@RequestWrapper(localName = "findMovieListAll",targetNamespace = "http://asynch.jaxws.movie.sample.anyframe/asynch_soap_http",className = "anyframe.sample.movie.jaxws.asynch.asynch_soap_http.FindMovieListAll")@WebResult(name = "return", targetNamespace = "")@WebMethodpublic java.util.ListfindMovieListAll() throws Exception;@ResponseWrapper(localName = "findMovieListAllResponse",targetNamespace = "http://asynch.jaxws.movie.sample.anyframe/asynch_soap_http",className ="anyframe.sample.movie.jaxws.asynch.asynch_soap_http.FindMovieListAllResponse")@RequestWrapper(localName = "findMovieListAll",targetNamespace = "http://asynch.jaxws.movie.sample.anyframe/asynch_soap_http",className = "anyframe.sample.movie.jaxws.asynch.asynch_soap_http.FindMovieListAll")@WebMethod(operationName = "findMovieListAll")publicResponsefindMovieListAllAsync();@ResponseWrapper(localName = "findMovieListAllResponse",targetNamespace = "http://asynch.jaxws.movie.sample.anyframe/asynch_soap_http",className ="anyframe.sample.movie.jaxws.asynch.asynch_soap_http.FindMovieListAllResponse")45


Asynchronous Invocation@RequestWrapper(localName = "findMovieListAll",targetNamespace = "http://asynch.jaxws.movie.sample.anyframe/asynch_soap_http",className = "anyframe.sample.movie.jaxws.asynch.asynch_soap_http.FindMovieListAll")@WebMethod(operationName = "findMovieListAll")public Future findMovieListAllAsync(@WebParam(name = "asyncHandler", targetNamespace = "")AsyncHandlerasyncHandler);}중략...• Implementation ClassInterface Class를 구현한 구현 클래스로 2개의 findMovieListAllAsync() 메소드에 대해서 빈 내용으로구현 메소드만 작성해놓는다. 실제로 호출되지는 않는다. 다음은 Movie Service의 인터페이스 클래스인 MovieServiceAsynch를 구현한 MovieServiceImpl.java 의 일부이다.@WebService(serviceName = "MovieServiceAsynchService", portName ="MovieServiceAsynchPort", 중략...public class MovieServiceImpl implements MovieServiceAsynch {public List findMovieListAll() throws Exception {return this.movieDAO.findMovieListAll();}public Response findMovieListAllAsync() {return null;/* not called */}public Future findMovieListAllAsync(AsyncHandler asyncHandler) {return null;/* not called */}중략...• Apache <strong>CXF</strong> JaxWsServerFactoryBean 사용한 서버 구동다음은 서버 사이드의 서비스를 Web Services로 노출시키는 서버를 구동하는 코드를 작성 예이다.인터페이스 클래스, 구현 클래스의 인스턴스, Web Services 주소를 JaxWsServerFactoryBean 속성 정보로 설정해준다.MovieServiceImpl implementor = new MovieServiceImpl();JaxWsServerFactoryBean svrFactory=new JaxWsServerFactoryBean();svrFactory.setServiceClass(MovieServiceAsynch.class);svrFactory.setAddress("http://localhost:9002/Movie");svrFactory.setServiceBean(implementor);svrFactory.create();6.2.Client Configuration클라이언트에서 서버 사이드의 Web Services를 호출 시 비동기적으로 호출하여 사용해 보도록 한다.이때, 위에서 Tool을 통해 생성된 Java 코드 중 MovieServiceAsynchService를 이용하여 Web Service에접근한다.46


Asynchronous Invocation6.2.1.Samples다음은 Web Services로 노출된 Movie Service의 메소드를 비동기적으로 호출하여 사용하는 예제이다.• Callback approach 사용 시 AsyncHandler 클래스 구현Polling approach 방식을 사용하면 부가 작성해야 하는 클래스가 없지만, Callback approach 방식을사용하려면 AsynchHandler 클래스를 추가 구현해줘야 한다. javax.xml.ws.AsyncHandler 인터페이스를 implement 하며, handleReponse method를 구현하여야 한다. 다음은 AsyncHandler 클래스를 구현한 MovieAsyncHandler.java의 일부이다.public class MovieAsyncHandler implements AsyncHandler {private FindMovieListAllResponse reply;public void handleResponse(Response response) {try {System.err.println("handleResponse called");reply = response.get();} catch (Exception ex) {ex.printStackTrace();}}public List getResponse() {return reply.getReturn();}...중략• Test case다음은 앞서 작성한 코드와 Tool을 통해 생성된 Java 코드들을 이용하여 Web Services로 노출된 MovieService에 접근하는 예이다. Tool을 통해 생성된 WebService Client 코드인 MovieServiceAsynchService를 통해, Web Services로 노출된 Movie Service의 인터페이스 메소드를 asynchronous하게 호출한다. 이때 WSDL 파일과 서비스명을 이용하여 접근하도록 한다. Movie Service를 얻은 후에는 MovieService에서 findMovieListAllAsync() 메소드를 비동기 방식으로 호출하여 동작이 올바른지 테스트해본다.private static final QName SERVICE_NAME =new QName("http://asynch.jaxws.movie.sample.anyframe/asynch_soap_http","MovieServiceAsynchService");/*** Asynchronous method invocation 방식 중* Polling approach 방법으로 List 형태의 Movie 전체 목록을 조회한다.*/File wsdl = new File("src/test/resources/webservices/asynch/wsdl/MovieServiceAsynchService.wsdl");MovieServiceAsynchService client =new MovieServiceAsynchService(wsdl.toURL(), SERVICE_NAME);MovieServiceAsynch movieService = client.getMovieServiceAsynchPort();// 1. find movie list allResponse response =movieService.findMovieListAllAsync();// 2. wait for response after asynchronous method invocationwhile (!response.isDone()) {47


Asynchronous Invocation}Thread.sleep(100);// 3. check the movie list countFindMovieListAllResponse reply = response.get();assertEquals(2, reply.getReturn().size());/*** Asynchronous method invocation 방식 중* Callback approach 방법으로 List 형태의 Movie 전체 목록을 조회한다.*/File wsdl = new File("src/test/resources/webservices/asynch/wsdl/MovieServiceAsynchService.wsdl");MovieServiceAsynchService client =new MovieServiceAsynchService(wsdl.toURL(), SERVICE_NAME);MovieServiceAsynch movieService = client.getMovieServiceAsynchPort();// 1. find movie list allMovieAsyncHandler asynchHandler = new MovieAsyncHandler();Future response = movieService.findMovieListAllAsync(asynchHandler);// 2. wait for response after asynchronous method invocationwhile (!response.isDone()) {Thread.sleep(100);}// 3. check the movie list countList reply = asynchHandler.getResponse();assertEquals(2, reply.size());중략...6.3.Resources• 참고자료• Developing a Consumer - Asynchronous Invocation Model [http://cwiki.apache.org/<strong>CXF</strong>20DOC/developing-a-consumer.html]• Asynchronous Web Service Invocation with JAX-WS 2.0 [http://today.java.net/pub/a/today/2006/09/19/asynchronous-jax-ws-web-services.html]48


7.RESTful ServicesRepresentational state transfer (REST)는 World Wide Web처럼 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍처 스타일이다. 요즈음 웹 서비스를 논할 때마다, 화제가 되는 REST는 Roy T Fielding이 2000년에 제창한, 네트워크 기반 어플리케이션을 위한 아키텍쳐 *스타일*로 표준이나 스펙이 아님에 유의한다.Representational state transfer은 마치 리소스(Resource)가 요청(Request)에 따라 상태가 변화하는 것처럼 동작한다는 의미에서 작성된 용어이다.REST(XML over HTTP) 특징 을 살펴보면 다음과 같다.• HTTP와 XML 이용HTTP와 XML을 이용하여 데이터를 주고 받는 웹 서비스를 이용한다.• 소프트웨어 아키텍처 스타일표준 기술이 아닌, 소프트웨어 아키텍처 스타일이다. 아키텍처 스타일은 아키텍처적인 제한 및 제약조건을 정의해놓은 집합이다. HTTP와 같은 기존의 기술을 이용하여 잘 설계된 분산 웹 어플리케이션을 만들수 있도록 하는 설계 가이드에 해당한다.• WWW(웹), Open API적용 예로 WWW(웹), Open API(ex. Google, Microsoft, Amazone, eBay, Yahoo등)가 있다. 더 자세한 내용은 REST 적용 예 를 참고한다.다음은 SOAP을 이용한 웹 서비스와 REST 방식의 웹 서비스를 비교한 그림이다. 그림에서와 같이"http://***/movieservice/movies/001" 형태의 URL을 요청한 경우, 그 결과 데이터는 XML 형식으로반환된다.Apache <strong>CXF</strong>을 이용하여 RESTful 서비스를 구현하는 방법 에는 다음과 같이 3가지 방법이 있다.• JAX-RS (JSR-311)JAX-RS(JSR-311) Spec. 을 이용하여 RESTful 서비스를 구현하는데, Apache <strong>CXF</strong>에서 Spec.에 대한구현체를 제공하여 표준 방식으로 RESTful 서비스를 작성할 수 있게 한다. JAX-RS에서 제공하는Annotation 설정을 이용한다.• HTTP Binding49


RESTful Services표준 방식이 아닌 방법으로 가장 쉽고 용이한 방식으로 RESTful 서비스를 작성할 수 있게 한다.JRA(Java REST Annotation) 설정 또는 Naming Convention 기반의 매핑 방식을 이용한다.• JAX-WS Provider/Dispatch API간단한 RESTful 서비스 작성을 지원한다. 표준 API를 사용하나 HTTP Binding 방식에 비해 유연한 구조가 아니다.다음은 각각의 RESTful 서비스 구현 방법 별로 어떻게 사용하는지에 대한 사용법이다.• JAX-RS 활용• HTTP Binding 방식• JRA(Java REST Annotation) 설정• Naming Convention 기반 매핑• JAX-WS Provider/Dispatch API 사용REST 적용 예는 아래와 같다.• WWW(웹)REST 적용 예시로 가장 많이 사용되는 것이 바로 WWW(웹)이다.설명상태를 유지하지 않는 클라이언트/서버 구조를 가진다.어디에서나 적용되는 인터페이스를 가진다. (e.g., GET, POST, PUT, DELETE)모든 자원은 URI를 이용하여 유일하게 지칭될 수 있다.자원들의 표현(Representation)들이 URI을 통해 서로 연결되어 있다.• Open API설명특정 기능 또는 컨텐츠를 가진 서비스 업체가 자신들의 서비스에 접근할 수 있도록 외부에 접근방법을 공개하는 것을 Open API라고 한다.Open API를 이용하여 새로운 서비스를 개발할 수 있다. 즉 Open API는 해당 서비스로 접근하기 위한 규약 또는 표준적인 인터페이스를 의미한다.Google, Microsoft, Amazon, eBay, Yahoo에서는 이미 여러 Open API를 공개하고 있다.7.1.JAX-RS 활용한 RESTful 서비스 구현JAX-RS(JSR-311) Spec [http://jcp.org/en/jsr/detail?id=311]. 을 이용하여 RESTful 서비스를 구현하는데, Apache <strong>CXF</strong>에서 Spec.에 대한 구현체를 제공하여 표준 방식으로 RESTful 서비스를 작성할 수 있게한다. JAX-RS에서 제공하는 Annotation 설정을 이용한다.JAX-RS의 특징 을 살펴보면 다음과 같다.• Web Service로 노출시킬 서비스 인터페이스 클래스의 각 method별로 JAX-RS에서 제공하는Annotation을 설정하여 RESTful Web Service를 구현한다.• 인터페이스 클래스와 메소드에 @Path Annotation을 설정한다. 클래스의 Path 속성 정보가 RESTfulWeb Service로 접근하는 상위 path 정보가 된다.• 인터페이스 클래스에 @Produces Annotation을 설정한다. ProduceMime 설정을 안한 경우, 클라이언트에서 addRequestHeader("Accept" , "application/xml") 메소드를 호출해주는 부가 작업이 필요하다.50


RESTful Services다음은 JAX-RS를 활용하여 RESTful 서비스 구현 시 Server와 Client 단에서 어떻게 사용해야 하는지에대한 사용법이다.• Server Configuration• Client Configuration7.1.1.Server ConfigurationMovie Service를 JAX-WS Frontend나 Simple Frontend를 사용하지 않고 JAX-RS를 지원하는 API를 사용하여 RESTful Web Services로 노출시켜보도록 한다.7.1.1.1.Samples다음은 Movie Service의 인터페이스 클래스 정의에 대한 예제이다.• Interface Class다음은 Movie Service의 인터페이스 클래스를 작성한 MovieService.java 의 일부이다. Annotation 설정에 유의하도록 한다.import javax.ws.rs.Path;import javax.ws.rs.ProduceMime;@Path("/movieservice/")@Produces("application/xml")@XmlSeeAlso(Movie.class)public interface MovieService extends GenericService {@POST@Path("/movie/")public Response createMovie(Movie movie) throws Exception;@GET@Path("/movie/{movieId}/")public Movie getMovie(@PathParam("movieId") String movieId)throws Exception;@PUT@Path("/movie/")public Response updateMovie(Movie movie) throws Exception;@DELETE@Path("/movie/{movieId}/")public Response removeMovie(@PathParam("movieId") String movieId)throws Exception;@GET@Path("/movies")public Movies getList() throws Exception;중략...• Test caseSpring Configuration XML Server 설정 이용JAX-RS를 이용하여 RESTful 서비스를 구현할 때 Spring 설정 파일을 이용하여 서버를 구동시킬 수 있다. 다음은 Spring Configuration XML 예시이다.51


RESTful Services중략...7.1.2.Client ConfigurationWeb Services에 접근하기 위한 클라이언트를 작성한다. Apache Commons HttpClient 혹은 URL 클래스를 이용하여 RESTful WebService에 접근하도록 한다.7.1.2.1.Samples다음은 Apache Commons HttpClient의 GetMethod/PostMethod/PutMethod/DeleteMethod와 URL 클래스를 이용하여 RESTful Web Services로 노출된 Movie Service에 접근하는 예제이다. 이때, RESTfulWebService의 결과 값이 XML 형태로 리턴되기 때문에 실제 클라이언트 코드에서 JavaBeans 객체로변경하여 사용해야 하는 작업이 추가된다. XML을 JavaBeans 객체로 변경하는 일을 JAXB를 통해서 수행하고 있다.• JAXB 활용JAXB를 활용하여 서비스 결과 XML을 JavaBeans로 변경시키기 위해서는 다음과 같이 각 JavaBeans객체에 Annotation을 설정하고 jaxb.index 파일을 추가 생성시켜줘야 한다.다음은 Movie Service의 인터페이스 클래스에서 파라미터와 리턴 값으로 사용하는 Movie.java 의 일부이다. Movie 클래스 정의 시 작성한 @XmlRootElement(name = "movie") Annotation 설정에 유의하도록 한다. JAXB를 이용하여 서비스 결과 XML을 JavaBeans 객체로 변환 시 이 Annotation 정보를 이용한다.import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement(name = "movie")public class Movie extends BaseObject implements java.io.Serializable {public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}중략...다음은 Movie Service의 인터페이스 클래스에서 목록조회 시 리턴 값으로 사용하는 Movies.java 의일부이다. Movies 클래스 정의 시 작성한 @XmlRootElement(name = "movies") Annotation 설정에 유의하도록 한다. JAXB를 이용하여 서비스 결과 XML을 JavaBeans 객체로 변환 시 이 Annotation 정보를 이용한다. 특히 목록 조회 결과 시 사용되는 리턴 값은 내부 멤버 변수로 Collection 객체를 정의하여 새로운 Movies 객체를 작성함에 유의하도록 한다.import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement(name = "movies")public class Movies {private Collection movies;@XmlElement(name="movie")public Collection getMovie() {return movies;52


RESTful Services}public void setMovies(Collection movies) {this.movies = movies;}중략...다음은 JAXB를 사용하기 위해서 필요한 jaxb.index 파일이다. Movie와 Movies 클래스를 정의해 놓는다. 파일 위치는 Movie와 Movies 클래스의 패키지 위치와 동일하다. (예시:src/main/resources/anyframe/sample/domain/jaxb.index)MovieMovies• Test Case다음은 RESTful Web Services로 노출된 Movie Service에 접근하는 클라이언트 코드를 작성한Controller 클래스의 일부이다.메소드 내에서 Get/Post/Put/Delete Method 중 어느 것을 사용할 것인지 정하여 접근하고자 하는Web Serices 주소와 함께 정의하고, HttpClient 객체를 생성하여 위에서 정의한 Method를 실행시킨다. 이때 클라이언트는 서버의 Movie Service 인터페이스 클래스를 이용하지 않고 URL 정보를 이용하여 접근한다. RESTful WebService 실행 결과로 받은 XML 데이터를 JavaBeans 객체로 변경하여 메소드 동작이 올바른지 테스트해본다.@Controllerpublic class MovieController {@RequestMapping("/cxfAddMovie.do")public String add(@ModelAttribute("movie") Movie movie) throws Exception {PostMethod post = new PostMethod("http://localhost:8080/anyframe.sample.cxf.restful/ws/movieservice/movie/");String xmldata = ""+ movie.getMovieId() + ""+ "" + movie.getTitle() + ""+ ""+ movie.getDirector() + ""+ ""+ new SimpleDateFormat("yyyy-MM-dd").format(movie.getReleaseDate()) + ""+ "" + movie.getRank() + "";}RequestEntity entity = new StringRequestEntity(xmldata,"text/xml","ISO-8859-1");post.setRequestEntity(entity);try {new HttpClient().executeMethod(post);} finally {post.releaseConnection();}return "/cxfListMovie.do";@RequestMapping("/cxfGetMovie.do")public ModelAndView get(HttpServletRequest request) throws Exception {String movieId = request.getParameter("movieId");if (!StringUtils.isBlank(movieId)) {// call Restful movie serviceURL url = new URL("http://localhost:8080/anyframe.sample.cxf.restful/ws/movieservice/movie/"53


RESTful Services+ movieId);InputStream in = url.openStream();String response = getStringFromInputStream(in);JAXBContext jaxbContext = JAXBContext.newInstance("anyframe.sample.domain");Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();Movie movie = (Movie) unmarshaller.unmarshal(new InputSource(new StringReader(response)));}request.setAttribute("movie", movie);}return new ModelAndView("/WEB-INF/jsp/cxf/movie/viewMovie.jsp");@RequestMapping("/cxfListMovie.do")public ModelAndView list(HttpServletRequest request) throws Exception {GetMethod get = new GetMethod("http://localhost:8080/anyframe.sample.cxf.restful/ws/movieservice/movies/");HttpClient httpclient = new HttpClient();String response = "";try {httpclient.executeMethod(get);response = get.getResponseBodyAsString();} finally {get.releaseConnection();}JAXBContext jaxbContext = JAXBContext.newInstance("anyframe.sample.domain");Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();anyframe.sample.domain.Movies movies = (Movies) unmarshaller.unmarshal(new InputSource(new StringReader(response)));}request.setAttribute("movieList", movies.getMovies());return new ModelAndView("/WEB-INF/jsp/cxf/movie/listMovie.jsp");@RequestMapping("/cxfDeleteMovie.do")public String deleteUser(@RequestParam("movieId") String movieId)throws Exception {DeleteMethod delete = new DeleteMethod("http://localhost:8080/anyframe.sample.cxf.restful/ws/movieservice/movie/"+ movieId);try {new HttpClient().executeMethod(delete);} finally {delete.releaseConnection();}return "/cxfListMovie.do";}중략...54


RESTful Services7.2.HTTP Binding(JRA) 활용한 RESTful 서비스 구현표준 방식이 아닌 방법으로 가장 쉽고 용이한 방식으로 JRA(Java REST Annotation) 설정을 이용하여RESTful 서비스를 작성할 수 있게 한다.Java REST Annotation의 특징 을 살펴보면 다음과 같다.• Web Service로 노출시킬 서비스 인터페이스 클래스의 각 method별로 JRA 설정을 하여 RESTful WebService를 구현한다.• 인터페이스 클래스의 메소드 별로 @Get/@Post/@Put/@Delete와 @HttpResource Annotation을 설정한다. HttpResource의 location 속성 정보가 RESTful Web Service로 접근하는 path 정보가 된다.• 인터페이스 클래스 메소드가 리턴 타입이 존재하는 경우 @WebResult Annotation을 설정한다.(리턴타입이 void 인 경우 불필요함)다음은 HTTP Binding(JRA)를 활용하여 RESTful 서비스 구현 시 Server와 Client 단에서 어떻게 사용해야 하는지에 대한 사용법이다.• Server Configuration• Client Configuration• 유의 사항7.2.1.Server ConfigurationMovie Service를 JAX-WS Frontend와 JRA 설정을 사용하여 RESTful Web Services로 노출시켜보도록 한다.7.2.1.1.Samples다음은 Movie Service의 인터페이스 클래스 정의에 대한 예제이다.• Interface Class다음은 Movie Service의 인터페이스 클래스를 작성한 MovieService.java 의 일부이다. Annotation 설정에 유의하도록 한다.import org.codehaus.jra.Get;import org.codehaus.jra.Post;import org.codehaus.jra.HttpResource;@WebService(targetNamespace = "http://anyframe.sample.movie.restful.httpbinding.jra")public interface MovieService {@Get@HttpResource(location = "/movies")@WebResult(name = "Movies")public Movies findMovieListAll() throws Exception;@Get@HttpResource(location = "/movies/{movieId}")@WebResult(name = "Movie")public Movie findMovie(FindMovie findMovie) throws Exception;@Post@HttpResource(location = "/movies")55


RESTful Servicespublic void createMovie(@WebParam(name = "Movie")Movie movie) throws Exception;중략...• Test case다음은 서버 사이드의 서비스를 Web Services로 노출시키는 서버를 구동하는 코드 작성 예이다.Spring Configuration XML Server 설정 이용HTTP Binding(JRA)을 이용하여 RESTful 서비스를 구현할 때 Spring 설정 파일을 이용하여 서버를 구동시킬 수 있다. 다음은 Spring Configuration XML 예시이다.중략...7.2.2.Client ConfigurationWeb Services에 접근하기 위한 클라이언트를 작성한다. HttpClient 혹은 URL 클래스를 이용하여 RESTfulWebService에 접근하도록 한다.7.2.2.1.Samples다음은 org.apache.commons.httpclient.HttpClient를 이용하여 RESTful Web Services로 노출된 MovieService에 접근하는 예제이다. 이때, RESTful WebService의 결과 값이 XML 형태로 리턴되기 때문에 실제클라이언트 코드에서 JavaBeans 객체로 변경하여 사용해야 하는 작업이 추가된다. XML을 JavaBeans객체로 변경하는 일을 JAXB를 통해서 수행하고 있다.• JAXB 활용JAXB를 활용하여 서비스 결과 XML을 JavaBeans로 변경시키기 위해서는 다음과 같이 각 JavaBeans객체에 Annotation을 설정하고 jaxb.index 파일을 추가 생성시켜줘야 한다.다음은 Movie Service의 인터페이스 클래스에서 파라미터와 리턴 값으로 사용하는 Movie.java 의 일부이다. Movie 클래스 정의 시 작성한 @XmlRootElement(name = "Movie") Annotation 설정에 유의하도록 한다. JAXB를 이용하여 서비스 결과 XML을 JavaBeans 객체로 변환 시 이 Annotation 정보를 이용한다.import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement(name = "Movie")public class Movie implements Serializable {public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}중략...다음은 Movie Service의 인터페이스 클래스에서 목록조회 시 리턴 값으로 사용하는 Movies.java 의일부이다. Movies 클래스 정의 시 작성한 @XmlRootElement(name = "Movies") Annotation 설정에 유의하도록 한다. JAXB를 이용하여 서비스 결과 XML을 JavaBeans 객체로 변환 시 이 Annotation 정보56


RESTful Services를 이용한다. 특히 목록 조회 결과 시 사용되는 리턴 값은 내부 멤버 변수로 Collection 객체를 정의하여 새로운 Movies 객체를 작성함에 유의하도록 한다.import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement(name = "Movies")public class Movies {private Collection movies;public Collection getMovie() {return movies;}public void setMovie(Collection movies) {this.movies = movies;}중략...다음은 JAXB를 사용하기 위해서 필요한 jaxb.index 파일이다. Movie와 Movies 클래스를 정의해 놓는다.MovieMovies다음은 XML Namespace가 정의된 XML 데이터를 JavaBeans 객체로 변경하기 위해서 필요한 package-info.java 파일이다. JRA를 이용하여 RESTful Service를 구현하면 서비스의 리턴 XML 데이터는 서비스 인터페이스 클래스의 패키지명의 반대 형태로 Namespace가 정의되어 온다. (ex."http://jra.httpbinding.restful.movie.sample.anyframe/") 이 Namespace를 맞춰서 JavaBeans 객체를 생성하려고 하면 에러가 나게 되므로, 현재 Movie와 Movies 클래스의 패키지명으로 Movie Service의 인터페이스 클래스 선언부에 @WebService(targetNamespace= "http://anyframe.sample.movie.restful.httpbinding.jra")와 같이 작성해주도록 한다. 그리고 anyframe.sample.movie.restful.httpbinding.jra 패키지 하위에 package-info.java 파일을 작성해놓음으로써 클라이언트 사이드에서 JAXB를 통해 바이딩할 때 Namespace "http://anyframe.sample.movie.restful.httpbinding.jra"를 인식시키도록 한다.@javax.xml.bind.annotation.XmlSchema(namespace = "http://anyframe.sample.movie.restful.httpbinding.jra",elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)package anyframe.sample.movie.restful.httpbinding.jra;• Test Case다음은 HttpClient 클래스를 사용하여 RESTful Web Services로 노출된 Movie Service에 접근하는 클라이언트 코드 작성 예이다. 테스트 메소드 내에서 Get/Post/Put/Delete Method 중 어느 것을 사용할 것인지 정하여 접근하고자 하는 Web Services 주소와 함께 정의하고, HttpClient 객체를 생성하여위에서 정의한 Method를 실행시킨다. 이때 클라이언트는 서버의 Movie Service 인터페이스 클래스를 이용하지 않고 URL 정보를 이용하여 접근한다. RESTful WebService 실행 결과로 받은 XML 데이터를 JavaBeans 객체로 변경하여 메소드 동작이 올바른지 테스트해본다./*** [Flow #-1] Positive Case : Get method로 Movie Service의 전체 목록 조회 기능을* 호출하여 XML data를 리턴받고* JAXB를 사용하여 Movies 객체로 전환하여 사용한다.* @Get, @HttpResource, @WebResult annotation을 이용하여* findMovieListAll method를 RESTful한 Web Service로 노출하여 Client가* 호출가능하도록 한다.* (ex. @Get* @HttpResource(location = "/movies")* @WebResult(name = "Movies")57


RESTful Services* public Movies findMovieListAll() throws Exception;* )*/public void testFindMovieListAll() throws Exception {// 1. find movieGetMethod get =new GetMethod("http://localhost:9002/movieservice/movies");HttpClient httpclient = new HttpClient();String response = "";try {assertEquals(200, httpclient.executeMethod(get));response = get.getResponseBodyAsString();System.out.println(response);} catch (Exception e) {fail();} finally {get.releaseConnection();}JAXBContext jaxbContext =JAXBContext.newInstance("anyframe.sample.movie.restful.httpbinding.jra");Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();Movies movies =(Movies) unmarshaller.unmarshal(new InputSource(new StringReader(response)));// 2. check the movie informationassertEquals(2, movies.getMovie().size());}/*** [Flow #-2] Positive Case : Get method로 Movie Id가 "001"인 Movie를 조회하는* 기능을 호출하여 XML data를 리턴받고* JAXB를 사용하여 Movie 객체로 전환하여 사용한다.* @Get, @HttpResource, @WebResult annotation을 이용하여* findMovie method를 RESTful한 Web Service로 노출하여 Client가* 호출가능하도록 한다.* (ex. @Get* @HttpResource(location = "/movies/{movieId}")* @WebResult(name = "Movie")* public Movie findMovie(FindMovie findMovie) throws Exception;* )*/public void testFindMovie() throws Exception {// 1. find movieGetMethod get =new GetMethod("http://localhost:9002/movieservice/movies/001");HttpClient httpclient = new HttpClient();String response = "";try {assertEquals(200, httpclient.executeMethod(get));response = get.getResponseBodyAsString();System.out.println("find: " + response);} catch (Exception e) {fail();} finally {get.releaseConnection();}JAXBContext jaxbContext =58


RESTful ServicesJAXBContext.newInstance("anyframe.sample.movie.restful.httpbinding.jra");Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();Movie movie =(Movie) unmarshaller.unmarshal(new InputSource(new StringReader(response)));}// 2. check the movie informationassertEquals("The Sound Of Music", movie.getTitle());assertEquals("Robert Wise", movie.getDirector());/*** [Flow #3] Positive Case : Post method로 Movie Id가 "003"인 신규 Movie를* 생성하는 기능을 호출한다.* @Post, @HttpResource annotation을 이용하여* createMovie method를 RESTful한 Web Service로 노출하여 Client가* 호출가능하도록 한다.* (ex. @Post* @HttpResource(location = "/movies")* public void createMovie(@WebParam(name = "Movie") Movie movie)* throws Exception;* )*/public void testCreateMovie() throws Exception {// 1. create movieString inputFile =this.getClass().getClassLoader().getResource("webservices/restful/httpbinding/jra/create_movie.txt").getFile();File input = new File(inputFile);PostMethod post =new PostMethod("http://localhost:9002/movieservice/movies");RequestEntity entity =new FileRequestEntity(input, "text/xml; charset=ISO-8859-1");post.setRequestEntity(entity);HttpClient httpclient = new HttpClient();String response = "";7.2.3.유의 사항try {assertEquals(200, httpclient.executeMethod(post));response = post.getResponseBodyAsString();System.out.println("create: " + response);} catch (Exception e) {fail();} finally {post.releaseConnection();}중략...위에서 단일항목을 Post Method 방식으로 생성하는 방법과 유사하게 Collection 항목을 Post Method방식으로 보내어 생성해 낼 수 있다.7.2.3.1.SamplesPost 방식으로 보내고자 하는 Collection 항목을 다음과 같이 작성한다. 이때 Movie를 소문자로 시작하여 작성함에 유의하도록 한다. 왜냐하면 기본적으로 RESTful Web Service 사용 시 Collection 데이터 내부 항목에 대해서 소문자로 XML 내용이 채워지게 되기 때문이다.59


RESTful Services• Collection 데이터 작성다음은 생성하고자 하는 Customer에 대한 Collection 데이터를 작성한 create_movies.txt 의 일부이다. Movies 태그 내 하위 태그로 movie 태그가 소문자로 작성되어 있음에 주의한다.005Life Is BeautifulRoberto Benigni006Life Is sadno director만약, 대문자 Movie로 작성하고자 한다면 아래와 같이 Movies 클래스의 멤버변수인 movies에@XmlElement Annotation 설정을 추가해주는데 이때 Movies 목록 조회 시 대문자 Movie와 소문자 movie 내용이 XML 상에 중복하게 나오게 된다. 단, JAXB 데이터 바인딩 이후에는 내용 중복없이 사용된다. 다음은 Movie Service의 인터페이스 클래스에서 목록조회 시 리턴 값으로 사용하는 Movies.java 의 일부이다. Movies 클래스 내 멤버 변수로 선언한 movies 변수 정의 시 작성한@XmlElement(name="Movie") Annotation 설정에 유의하도록 한다.import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement(name = "Movies")public class Movies {@XmlElement(name="Movie")private Collection; movies;public Collection getMovie() {return movies;}public void setMovie(Collection movies) {this.movies = movies;}중략...• Test Case다음은 HttpClient 클래스를 사용하여 RESTful Web Services로 노출된 Movie Service에 접근하는클라이언트 코드 작성 예이다. testCreateMovies() 메소드 내에서 Post Method를 사용하여 MovieCollection 목록을 생성해내도록 한 후, Get Mothod를 사용하여 Movie 목록을 확인한다. RESTfulWebService 실행 결과로 받은 XML 데이터를 JavaBeans 객체로 변경하여 메소드 동작이 올바른지테스트해본다./*** [Flow #-7]Positive Case : Post method로 Movie Id가 "005","006"인 신규 Movie 목록을* 생성하는 기능을 호출한다.* @Post, @HttpResource annotation을 이용하여* createMovies method를 RESTful한 Web Service로 노출하여* Client가 호출가능하도록 한다.* (ex. @Post* @HttpResource(location = "/movielist")* public void createMovies(@WebParam(name = "Movies")* Movies movies) throws Exception;* )60


RESTful Services*/public void testCreateMovies() throws Exception {// 1. create movieString inputFile =this.getClass().getClassLoader().getResource("webservices/restful/httpbinding/jra/create_movies.txt").getFile();File input = new File(inputFile);PostMethod post =new PostMethod("http://localhost:9002/movieservice/movielist");RequestEntity entity =new FileRequestEntity(input, "text/xml; charset=ISO-8859-1");post.setRequestEntity(entity);HttpClient httpclient = new HttpClient();try {assertEquals(200, httpclient.executeMethod(post));} catch (Exception e) {fail();} finally {post.releaseConnection();}// 2. find moviesGetMethod get =new GetMethod("http://localhost:9002/movieservice/movies");HttpClient httpclientforlist = new HttpClient();String response = "";try {assertEquals(200, httpclientforlist.executeMethod(get));response = get.getResponseBodyAsString();System.out.println("movies reponse:"+response);} catch (Exception e) {fail();} finally {get.releaseConnection();}JAXBContext jaxbContext =JAXBContext.newInstance("anyframe.sample.movie.restful.httpbinding.jra");Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();Movies movies =(Movies) unmarshaller.unmarshal(new InputSource(new StringReader(response)));// 3. check the new movie informationCollection col = movies.getMovie();Iterator itr = col.iterator();while(itr.hasNext()){Movie movie = (Movie)itr.next();if(movie.getMovieId().equals("005")){assertEquals("Life Is Beautiful", movie.getTitle());assertEquals("Roberto Benigni", movie.getDirector());}else if(movie.getMovieId().equals("006")){assertEquals("Life Is sad", movie.getTitle());assertEquals("no director", movie.getDirector());61


RESTful Services}}}중략...7.3.HTTP Binding(Naming Convention) 활용한 RESTful 서비스 구현표준 방식이 아닌 방법으로 가장 쉽고 용이한 방식으로 Naming Convention 기반의 매핑 방식을 이용하여 RESTful 서비스를 작성할 수 있게 한다.Naming Convention 기반 매핑의 특징 을 살펴보면 다음과 같다.• Web Service로 노출시킬 서비스 인터페이스 클래스의 각 method를 특정 Naming Convention에 맞춰서 정의하면 부가 Annotation이나 Configuration 없이 손쉽게 RESTful Web Service를 구현할 수 있다.• 기본 CRUD에 대한 메소드 Naming Convention이 존재한다.(아래 표 참조)메소드 Naming ConventionCollection getMovies()Movie getMovie(movieId)void addMovie(Movie movie) *createXXX도 동일함void updateMovie(String movieId, Movie movie)void deleteMovie(String movieId) *removeXXX도 동일함매핑 결과HTTP GET /moviesHTTP GET /movies/{movieId}HTTP POST /moviesHTTP PUT /movies/{movieId}HTTP DELETE /movies/{movieId}다음은 HTTP Binding(Naming Convention)를 활용하여 RESTful 서비스 구현 시 Server와 Client 단에서어떻게 사용해야 하는지에 대한 사용법이다.• Server Configuration• Client Configuration7.3.1.Server ConfigurationMovie Service를 JAX-WS Frontend를 사용하여 RESTful Web Services로 노출시켜보도록 한다.7.3.1.1.Samples다음은 Movie Service의 인터페이스 클래스 정의에 대한 예제이다. 서버 구동을 위해서 <strong>Anyframe</strong>에서제공하는 JaxWsServer 클래스를 이용하고 있다.• Interface Class다음은 Movie Service의 인터페이스 클래스를 작성한 MovieService.java 의 일부이다. Annotation 설정에 유의하도록 한다. 특히, XML 데이터를 서버에 전달하여 객체로 변경시킬 때 JAXB를 사용하므로 addMovie와 updateMovie 메소드에 @WebParam Annotation 속성 name 값을 Movie로 설정해놓아야 하는 것을 기억한다.@WebService(targetNamespace = "http://anyframe.sample.movie.restful.httpbinding.namingconvention")public interface MovieService {public Collection getMovies() throws Exception;public Movie getMovie(String movieId) throws Exception;62


RESTful Servicespublic void addMovie(@WebParam(name = "Movie")Movie movie) throws Exception;public void updateMovie(String movieId, @WebParam(name = "Movie")Movie movie) throws Exception;public void deleteMovie(String movieId) throws Exception;중략...• Test case다음은 서버 사이드의 서비스를 Web Services로 노출시키는 서버를 구동하는 Spring Configuration설정 예이다.Spring Configuration XML Server 설정 이용HTTP Binding(Naming Convention)을 이용하여 RESTful 서비스를 구현할 때 Spring 설정 파일을 이용하여 서버를 구동시킬 수 있다. 다음은 Spring Configuration XML 예시이다.중략...7.3.2.Client ConfigurationWeb Services에 접근하기 위한 클라이언트를 작성한다. HttpClient 혹은 URL 클래스를 이용하여 RESTfulWebService에 접근하도록 한다.7.3.2.1.Samples다음은 org.apache.commons.httpclient.HttpClient를 이용하여 RESTful Web Services로 노출된 MovieService에 접근하는 예제이다. 이때, RESTful WebService의 결과 값이 XML 형태로 리턴되기 때문에 실제클라이언트 코드에서 JavaBeans 객체로 변경하여 사용해야 하는 작업이 추가된다. XML을 JavaBeans객체로 변경하는 일을 JAXB를 통해서 수행하고 있다.• JAXB 활용JAXB를 활용하여 서비스 결과 XML을 JavaBeans로 변경시키기 위해서는 다음과 같이 각 JavaBeans객체에 Annotation을 설정하고 jaxb.index 파일을 추가 생성시켜줘야 한다.다음은 Movie Service의 인터페이스 클래스에서 파라미터와 리턴 값으로 사용하는 Movie.java 의 일부이다. Movie 클래스 정의 시 작성한 @XmlRootElement(name = "Movie") Annotation 설정에 유의하도록 한다. JAXB를 이용하여 서비스 결과 XML을 JavaBeans 객체로 변환 시 이 Annotation 정보를 이용한다.import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement(name = "Movie")public class Movie implements Serializable {public String getTitle() {return title;}public void setTitle(String title) {63


RESTful Services}this.title = title;중략...다음은 Movie Service의 인터페이스 클래스에서 목록조회 시 리턴 값으로 사용하는 Movies.java 의일부이다. Movies 클래스 정의 시 작성한 @XmlRootElement(name = "Movies") Annotation 설정에 유의하도록 한다. JAXB를 이용하여 서비스 결과 XML을 JavaBeans 객체로 변환 시 이 Annotation 정보를 이용한다. 특히 목록 조회 결과 시 사용되는 리턴 값은 내부 멤버 변수로 Collection 객체를 정의하여 새로운 Movies 객체를 작성함에 유의하도록 한다.@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "", propOrder = {"movies" })@XmlRootElement(name = "getMoviesResponse")public class GetMoviesResponse {@XmlElement(name = "return", required = true)private Collection movies;public Collection getMovie() {return movies;}public void setMovie(Collection movies) {this.movies = movies;}중략...다음은 Movie Service의 인터페이스 클래스에서Movie 조회 메소드인 getMovie()의 리턴 타입이 인 경우, 추가 작성해야 하는 GetMovieResponse.java 의 일부이다. 현재 Wrapped mode로 서버를 설정하여 사용하고 있으므로 메소드 명으로 wrapping된 XML 결과 값이 리턴된다.@XmlRootElement(name = "getMovieResponse") Annotation 설정에 유의하도록 한다. JAXB를 이용하여 서비스 결과 XML을 JavaBeans 객체로 변환 시 이 Annotation 정보를 이용한다.@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "", propOrder = {"movie" })@XmlRootElement(name = "getMovieResponse")public class GetMovieResponse {@XmlElement(name = "return", required = true)private Movie movie = null;public Movie getMovie() {return movie;}public void setMovie(Movie movie) {this.movie = movie;}중략...다음은 JAXB를 사용하기 위해서 필요한 jaxb.index 파일이다. Movie와 GetMoviesResponse 그리고GetMovieResponse 클래스를 정의해 놓는다.MovieGetMoviesResponseGetMovieResponse다음은 XML Namespace가 정의된 XML 데이터를 JavaBeans 객체로 변경하기 위해서 필요한 packageinfo.java파일이다. HTTP Binding(Naming Convention) 방식을 이용하여 RESTful Service를 구현하면 서비스의 리턴 XML 데이터는 서비스 인터페이스 클래스의 패키지명의 반대 형태로 Namespace가 정의되어 온다. (ex."http://namingconvention.httpbinding.restful.movie.sample.anyframe/") 이Namespace를 맞춰서 JavaBeans 객체를 생성하려고 하면 에러가 나게 되므로, 현재 Movie 클래스의 패키지명으로 Movie Service의 인터페이스 클래스 선언부에 @WebService(targetNamespace64


RESTful Services= "http://anyframe.sample.movie.restful.httpbinding.namingconvention")와 같이 작성해주도록 한다. 그리고 anyframe.sample.movie.restful.httpbinding.namingconvention 패키지 하위에 packageinfo.java파일을 작성해놓음으로써 클라이언트 사이드에서 JAXB를 통해 바이딩할 때 Namespace"http://anyframe.sample.movie.restful.httpbinding.namingconvention"를 인식시키도록 한다.@javax.xml.bind.annotation.XmlSchema(namespace = "http://anyframe.sample.movie.restful.httpbinding.namingconvention",elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)package anyframe.sample.movie.restful.httpbinding.namingconvention;• Test Case다음은 HttpClient 클래스를 사용하여 RESTful Web Services로 노출된 Movie Service에 접근하는 클라이언트 코드 작성 예이다. 메소드 내에서 Get/Post/Put/Delete Method 중 어느 것을 사용할 것인지 정하여 접근하고자 하는 Web Services 주소와 함께 정의하고, HttpClient 객체를 생성하여 위에서 정의한 Method를 실행시킨다. 이때 클라이언트는 서버의 Movie Service 인터페이스 클래스를 이용하지 않고 URL 정보를 이용하여 접근한다. RESTful WebService 실행 결과로 받은 XML 데이터를JavaBeans 객체로 변경하여 메소드 동작이 올바른지 테스트해본다./*** Get method로 Movie Service의 전체 목록 조회 기능을 호출하여* XML data를 리턴받고 JAXB를 사용하여 GetMoviesResponse 객체로 전환하여 사용한다.* Naming Convention 규칙:* Collection get+"The plural of resource class name"()** getMovies method를 RESTful한 Web Service로 노출하여 Client가 호출가능하도록 한다.* (ex. public Collection getMovies() throws Exception; )*/public void testFindMovieListAll() throws Exception {// 1. find movieGetMethod get = new GetMethod("http://localhost:9002/movieservice/movies");HttpClient httpclient = new HttpClient();String response = "";try {assertEquals(200, httpclient.executeMethod(get));response = get.getResponseBodyAsString();System.out.println(response);} catch (Exception e) {fail();} finally {get.releaseConnection();}JAXBContext jaxbContext =JAXBContext.newInstance("anyframe.sample.movie.restful.httpbinding.namingconvention");Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();GetMoviesResponse movies = (GetMoviesResponse) unmarshaller.unmarshal(new InputSource(new StringReader(response)));}// 2. check the movie informationassertEquals(2, movies.getMovie().size());/*** Get method로 Movie Id가 "001"인 Movie를 조회하는 기능을 호출하여* XML data를 리턴받고 JAXB를 사용하여 GetMovieResponse 객체로 전환하여 사용한다.* Naming Convention 규칙:65


RESTful Services* "resource class name" get+"resource class name"(Object id)** getMovie method를 RESTful한 Web Service로 노출하여 Client가 호출가능하도록 한다.* (ex. public Movie getMovie(String movieId) throws Exception;)*/public void testFindMovie() throws Exception {// 1. find movieGetMethod get=new GetMethod("http://localhost:9002/movieservice/movies/001");HttpClient httpclient = new HttpClient();String response = "";try {assertEquals(200, httpclient.executeMethod(get));response = get.getResponseBodyAsString();System.out.println("find: " + response);} catch (Exception e) {fail();} finally { get.releaseConnection();}JAXBContext jaxbContext = JAXBContext.newInstance("anyframe.sample.movie.restful.httpbinding.namingconvention");Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();GetMovieResponse movie = (GetMovieResponse) unmarshaller.unmarshal(new InputSource(new StringReader(response)));}// 2. check the movie informationassertEquals("The Sound Of Music", movie.getMovie().getTitle());assertEquals("Robert Wise", movie.getMovie().getDirector());/*** Post method로 Movie Id가 "003"인 신규 Movie를 생성하는 기능을 호출한다* Naming Convention 규칙:* void add or create + "resource class name"("resource class" obj)** addMovie method를 RESTful한 Web Service로 노출하여 Client가 호출가능하도록 한다.* (ex. public void addMovie(@WebParam(name = "Movie") Movie movie)*/public void testCreateMovie() throws Exception {// 1. create movieString inputFile = this.getClass().getClassLoader().getResource("webservices/restful/httpbinding/namingconvention/create_movie.txt").getFile();File input = new File(inputFile);PostMethod post =new PostMethod("http://localhost:9002/movieservice/movies");RequestEntity entity =new FileRequestEntity(input, "text/xml; charset=ISO-8859-1");post.setRequestEntity(entity);HttpClient httpclient = new HttpClient();String response = "";try {assertEquals(200, httpclient.executeMethod(post));response = post.getResponseBodyAsString();System.out.println("create: " + response);} catch (Exception e) {fail();} finally {post.releaseConnection();}중략...66


RESTful Services7.4.JAX-WS Provider/Dispatch API 활용한RESTful 서비스 구현표준 API를 사용하여 간단한 RESTful 서비스를 작성할 수 있게 하지만, HTTP Binding 방식에 비해 유연한 구조가 아니다.JAX-WS Provider/Dispatch API의 특징을 살펴보면 다음과 같다.• JAX-WS Provider(javax.xml.ws.Provider)와 Dispatch(javax.xml.ws.Dispatch) API를 사용하여 간단한RESTful 서비스를 구현할 수 있다.• Web Service로 노출시킬 서비스를 Provider 인터페이스 클래스를 구현하여 작성하고 invoke method를 구현한다.다음은 JAX-WS Provider와 Dispatch API를 사용하여 RESTful 서비스 구현 시 Server와 Client 단에서 어떻게 사용해야 하는지에 대한 사용법이다.• Server Configuration• Client Configuration7.4.1.Server ConfigurationMovie Service를 Provider 인터페이스 클래스를 구현한 MovieServicePayloadProvider 클래스로 작성하고 invoke method를 구현함으로써 RESTful Web Services로 노출시켜 보도록 한다.7.4.1.1.Samples다음은 Provider 인터페이스 클래스를 구현한 MovieServicePayloadProvider 클래스 정의에 대한 예제이다. 서버 구동을 위해서 javax.xml.ws.Endpoint 클래스를 이용하고 있다.• Provider 인터페이스 클래스 구현(MovieServicePayloadProvider)다음은 Provider 인터페이스 클래스를 구현한 MovieServicePayloadProvider 클래스를 작성한MovieServicePayloadProvider.java 의 일부이다. Annotation 설정에 유의하도록 한다.import javax.xml.ws.ServiceMode;import javax.xml.ws.WebServiceProvider;@WebServiceProvider()@ServiceMode(value = Service.Mode.PAYLOAD)public class MovieServicePayloadProvider implements Provider {@Resourceprotected WebServiceContext wsContext;public MovieServicePayloadProvider() {}public DOMSource invoke(DOMSource request) {MessageContext mc = wsContext.getMessageContext();String path = (String) mc.get(Message.PATH_INFO);String query = (String) mc.get(Message.QUERY_STRING);String httpMethod = (String) mc.get(Message.HTTP_REQUEST_METHOD);if (httpMethod.equalsIgnoreCase("POST")) {return updateMovie(request);67


RESTful Services} else if (httpMethod.equalsIgnoreCase("GET")) {if (path.equals("/movieservice/movies") && query == null) {return findMovieListAll();} else if (path.equals("/movieservice/movies") && query != null) {return findMovie(query);}}중략...• Test case다음은 서버 사이드의 서비스를 Web Services로 노출시키는 서버를 구동하는 코드 작성 예이다.MovieServicePayloadProvider 클래스 생성 후 javax.xml.ws.Endpoint 클래스를 생성해 준 다음, 접근주소를 설정하여 publish 시킨다. 이때 Endpoint Binding Id를 HTTP Binding ID로 설정하고 있음에 유의하도록 한다.System.out.println("Starting Server");Endpoint e = Endpoint.create(HTTPBinding.HTTP_BINDING,new MovieServicePayloadProvider());String address = "http://localhost:9002/movieservice/movies";e.publish(address);중략...7.4.2.Client ConfigurationWeb Services에 접근하기 위한 클라이언트를 작성한다. HttpClient 혹은 URL 클래스를 이용하여 RESTfulWebService에 접근할 수도 있고, Dispatch API를 이용하여 접근해볼 수도 있다.7.4.2.1.Samples다음은 org.apache.commons.httpclient.HttpClient를 이용하여 RESTful Web Services로 노출된 MovieService에 접근하는 예제이다. 이때, RESTful WebService의 결과 값이 XML 형태로 리턴되기 때문에 실제클라이언트 코드에서 JavaBeans 객체로 변경하여 사용해야 하는 작업이 추가된다. XML을 JavaBeans객체로 변경하는 일을 JAXB를 통해서 수행하고 있다.• JAXB 활용JAXB를 활용하여 서비스 결과 XML을 JavaBeans로 변경시키기 위해서는 다음과 같이 각 JavaBeans객체에 Annotation을 설정하고 jaxb.index 파일을 추가 생성시켜줘야 한다. 다음은 Movie Service에서입력 및 출력 시 Movie 상세조회 XML 데이터와 변환되는 Movie.java의 일부이다. Movie 클래스 정의시 작성한 @XmlRootElement(name = "Movie") Annotation 설정에 유의하도록 한다. JAXB를 이용하여 서비스 결과 XML을 JavaBeans 객체로 변환 시 이 Annotation 정보를 이용한다.import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement(name = "Movie")public class Movie implements Serializable {public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}중략...다음은 Movie Service에서 입력 및 출력 시 Movie 목록조회 XML 데이터와 변환되는 Movies.java 의일부이다. Movies 클래스 정의 시 작성한 @XmlRootElement(name = "Movies") Annotation 설정에 유68


RESTful Services의하도록 한다. JAXB를 이용하여 서비스 결과 XML을 JavaBeans 객체로 변환 시 이 Annotation 정보를 이용한다. 특히 목록 조회 결과 시 사용되는 리턴 값은 내부 멤버 변수로 Collection 객체를 정의하여 새로운 Movies 객체를 작성함에 유의하도록 한다.import javax.xml.bind.annotation.XmlRootElement;@XmlRootElement(name = "Movies")public class Movies {private Collection movies;public Collection getMovie() {return movies;}public void setMovie(Collection movies) {this.movies = movies;}중략...다음은 JAXB를 사용하기 위해서 필요한 jaxb.index 파일이다. Movie와 Movies 클래스를 정의해 놓는다.MovieMovies• Test Case다음은 HttpClient 및 Dispatch 클래스를 사용하여 RESTful Web Services로 노출된 Movie Service에접근하는 클라이언트 코드 작성 예이다. 메소드 내에서 Get/Post/Put/Delete Method 중 어느 것을사용할 것인지 정하여 접근하고자 하는 Web Services 주소와 함께 정의하고, HttpClient 객체를 생성하여 위에서 정의한 Method를 실행시킨다. 이 중 testUpdateMovie() 메소드가 Dispatch API를 이용하여 작성된 클라이언트 코드이다. RESTful WebService 실행 결과로 받은 XML 데이터를 JavaBeans 객체로 변경하여 메소드 동작이 올바른지 테스트해본다./*** HttpClient를 이용하여* List 형태의 Movie 전체 목록을 조회한다.*/public void testFindMovieListAll() throws Exception {// 1. find movieGetMethod get=new GetMethod("http://localhost:9002/movieservice/movies");HttpClient httpclient = new HttpClient();String response = "";try {assertEquals(200, httpclient.executeMethod(get));response = get.getResponseBodyAsString();System.out.println("findMovieListAll : " + response);assertNotNull(response);} catch (Exception e) { fail();} finally { get.releaseConnection(); }JAXBContext jaxbContext =JAXBContext.newInstance("anyframe.sample.movie.restful.jaxrs");Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();Movies movies = (Movies) unmarshaller.unmarshal(new InputSource(new StringReader(response)));}// 2. check the movie informationassertEquals(2, movies.getMovie().size());69


RESTful Services/*** HttpClient를 이용하여 Movie Id가 "001"인 Movie를 조회한다.*/public void testFindMovie() throws Exception {// 1. find movieGetMethod get =new GetMethod("http://localhost:9002/movieservice/movies?movieId=001");HttpClient httpclient = new HttpClient();String response = "";try {assertEquals(200, httpclient.executeMethod(get));response = get.getResponseBodyAsString();System.out.println("find: " + response);assertNotNull(response);} catch (Exception e) {fail();} finally {get.releaseConnection();}JAXBContext jaxbContext =JAXBContext.newInstance("anyframe.sample.movie.restful.jaxrs");Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();Movie movie =(Movie) unmarshaller.unmarshal(new InputSource(new StringReader(response)));}// 2. check the movie informationassertEquals("The Sound Of Music", movie.getTitle());assertEquals("Robert Wise", movie.getDirector());/*** Dispatch를 이용하여 Movie Id가 "002"인 기존 Movie 정보를 변경한다.*/public void testUpdateMovie() throws Exception {QName serviceName = new QName("movieservice");QName portName = new QName("MovieServicePayloadProviderPort");Service service = Service.create(serviceName);service.addPort(portName, HTTPBinding.HTTP_BINDING,"http://localhost:9002/movieservice/movies");Dispatch dispatcher=service.createDispatch(portName, DOMSource.class,Service.Mode.PAYLOAD);Map requestContext = dispatcher.getRequestContext();InputStream is = getClass().getClassLoader().getResourceAsStream("webservices/restful/dispatch/client/Movie-movieId=002Req.xml");Document doc = XMLUtils.parse(is);DOMSource reqMsg = new DOMSource(doc);requestContext.put(MessageContext.HTTP_REQUEST_METHOD, "POST");DOMSource result = dispatcher.invoke(reqMsg);printSource(result);JAXBContext jaxbContext=JAXBContext.newInstance("anyframe.sample.movie.restful.jaxrs");Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();Movie movie = (Movie) unmarshaller.unmarshal(result);// 3. check the new movie informationassertEquals("Life Is Wonderful", movie.getTitle());70


RESTful Services}assertEquals("Roberto", movie.getDirector());중략...7.5.[참고] Spring Configuration XMLSchemaApache <strong>CXF</strong>에서 제공하는 Tag를 사용하여 Server와 Client 설정 시 Spring Configuration XML 파일 상단에 아래와 같이 Schema를 등록해줘야 한다. JAX-RS 사용 시에는 jaxrs Namespace와 Schema 파일을 반드시 등록해줘야 한다.중략...7.6.Resources• 다운로드다음에서 테스트 DB를 포함하고 있는 hsqldb.movie.zip과 sample 코드를 포함하고 있는anyframe.sample.cxf.restful.zip 파일을 다운받은 후, 압축을 해제한다. 그리고 hsqldb 폴더 내의start.cmd (or start.sh) 파일을 실행시켜 테스트 DB를 시작시켜 놓는다.• Maven 기반 실행Command 창에서 압축 해제 폴더로 이동한 후 mvn clean jetty:run이라는 명령어를 실행시킨다. Jetty Server가 정상적으로 시작되었으면 브라우저를 열고 주소창에 http://localhost:8080/anyframe.sample.cxf.restful를 입력하여 실행 결과를 확인한다.• Eclipse 기반 실행 - m2eclipse, WTP 활용Eclipse에서 압축 해제 프로젝트를 import한 후, 해당 프로젝트에 대해 마우스 오른쪽 버튼을 클릭하고 컨텍스트 메뉴에서 Maven > Enable Dependency Management를 선택하여 컴파일 에러를해결한다. (위와 같이 했음에도 컴파일 에러가 사라지지 않으면 컨텍스트 메뉴에서 Properties >JavaEE Module Dependencies를 클릭하고, 오른쪽 JAR/Module 목록에서 Maven Dependencies 항목을 체크하도록 한다.) 그리고 해당 프로젝트에 대해 마우스 오른쪽 버튼을 클릭한 후, 컨텍스트메뉴에서 Run As > Run on Server (Tomcat 기반)를 클릭한다. Tomcat Server가 정상적으로 시작되었으면 브라우저를 열고 주소창에 http://localhost:8080/anyframe.sample.cxf.restful를 입력하여 실행 결과를 확인한다.• Eclipse 기반 실행 - WTP 활용Eclipse에서 압축 해제 프로젝트를 import한 후, build.xml 파일을 실행하여 참조 라이브러리를 src/main/webapp 폴더의 WEB-INF/lib내로 복사시킨다. 해당 프로젝트를 선택하고 마우스 오른쪽 버튼을 클릭한 후, 컨텍스트 메뉴에서 Run As > Run on Server를 클릭한다. Tomcat Server가 정상적으로 시작되었으면 브라우저를 열고 주소창에 http://localhost:8080/anyframe.sample.cxf.restful를71


RESTful Services입력하여 실행 결과를 확인한다. (* build.xml 파일 실행을 위해서는 ${ANT_HOME}/lib 내에 mavenant-task-2.0.10.jar파일이 있어야 한다.)• [참고] Eclipse 내 프로젝트에서 Validation Error 발생 시 대처Eclipse에서 압축 해체 프로젝트를 import한 후, Eclipse Preferences 화면의 Validation 메뉴에서XML Validator 항목의 체크 박스를 제거하고 Apply 버튼을 선택하여 적용하면 src/main/resources소스폴더의 spring/context-cxf.xml 파일과 springmvc/cxf-servlet.xml 파일에서 나타나던 ValidationError가 없어질 것이다. 기능 동작 상에는 전혀 문제가 없다.표 7.1. Download ListNamehsqldb.movie.zipanyframe.sample.cxf.restful.zipmaven-ant-tasks-2.0.10.jarDownloadDownload [http://dev.anyframejava.org/docs/anyframe/plugin/foundation/4.6.0/reference/sample/hsqldb.movie.zip]Download [http://dev.anyframejava.org/docs/anyframe/plugin/cxf/4.5.2/reference/sample/anyframe.sample.cxf.restful.zip]Download [http://dev.anyframejava.org/docs/anyframe/plugin/foundation/4.6.0/reference/sample/maven-ant-tasks-2.0.10.jar]• 참고자료• Architectural Styles and the Design of Network-based Software Architectures, Roy Thomas Fielding,2000 [http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm]• Sun Article: RESTful Web Services [http://java.sun.com/developer/technicalArticles/WebServices/restful/]• RESTful Web Services slides [http://www.stefan-marr.de/downloads/RESTful-Web-Services.slides.pdf]• REST Wiki FrontPage [http://rest.blueoxen.net/cgi-bin/wiki.pl?FrontPage]• RESTful Web Services, John Cowan, 2005 [http://mercury.ccil.org/~cowan/restws.pdf]• Building Web Services the REST Way [http://www.xfront.com/REST-Web-Services.html]72


8.WAS(Web Application Server)ConfigurationApache <strong>CXF</strong> 기반의 Web Services를 구현한 웹 어플리케이션을 WAS(Web Application Server)에 배포하여 구동시키게 되는데, 이때 각 WAS 별로 Apache <strong>CXF</strong>를 실행시키기 위해서 추가 작업이 필요할 수 있다. WAS 별 추가 환경 설정이 필요한 경우 어떻게 해야 하는지 설명하고 있다. Apache <strong>CXF</strong>는 JDK 1.5만을 지원하므로 설치 대상 WAS도 JDK 1.5를 지원하는 WAS로 제한한다.다음은 각 WAS 별 내용이다.8.1.TomcatApache <strong>CXF</strong>는 JDK 1.5를 지원하므로 Tomcat 서버의 경우, Tomcat 5.5.x 버전의 서버가 대상이 된다.Tomcat 서버에 대한 설명 및 다운로드는 이곳 [http://tomcat.apache.org/] 을 참고하도록 한다.8.1.1.Tomcat 5.5.238.2.JEUS추가 설정 없이 Apache <strong>CXF</strong> 사용이 가능하다.Apache <strong>CXF</strong>는 JDK 1.5를 지원하므로 JEUS 서버의 경우, JEUS 5와 JEUS 6 버전의 서버가 대상이 되나,JEUS 5의 경우 JAXB 라이브러리의 충돌로 Apache <strong>CXF</strong> 사용이 불가능하다. JEUS 서버에 대한 설명 및다운로드는 TmaxSoft 홈페이지를 참고하도록 한다.8.2.1.JEUS 5Apache <strong>CXF</strong> 사용이 불가능 하다. JEUS 서버 라이브러리에 배포된 JAXB API, IMPL 및 참조 라이브러리(JAXB 1.x)와 Apache <strong>CXF</strong>를 사용하여 구현한 웹 어플리케이션에 배포된 라이브러리들(JAXB 2.x)과 버전 차이로 동작하지 않는다.8.2.2.JEUS 6추가 설정 없이 Apache <strong>CXF</strong> 사용이 가능하다. JEUS 서버 라이브러리에 배포된 JAXB API, IMPL 및 참조라이브러리(JAXB 2.x)와 Apache <strong>CXF</strong>를 사용하여 구현한 웹 어플리케이션에 배포된 라이브러리들(JAXB2.x)의 버전 일치로 문제없이 동작한다.8.3.WebLogicApache <strong>CXF</strong>는 JDK 1.5를 지원하므로 WebLogic 서버의 경우, WebLogic 9.2, 10.1 버전의 서버가 대상이된다. WebLogic 서버에 대한 설명 및 다운로드는 이곳 [http://www.oracle.com/appserver/index.html]을 참고하도록 한다.8.3.1.WebLogic 9.2, 10.1• JDK_HOME/jre/lib/endorsed 폴더에 geronimo-ws-metadata_2.0_spec-1.1.2.jar 파일 복사73


WAS(Web ApplicationServer) ConfigurationWebLogic 서버 설치 시 설정했던 JDK 1.5의 위치를 확인하여 JDK_HOME/jre/lib 폴더 하위에endorsed 폴더를 생성하고, 현재 배포하려고 하는 웹 어플리케이션의 WEB-INF/lib 폴더 하위의geronimo-ws-metadata_2.0_spec-1.1.2.jar 파일을 endorsed 폴더 하위로 복사해 넣도록 한다.[참고사항] 이 경우, WebLogic 서버 전체에 영향을 미치므로 weblogic-application.xml 파일을 추가 작성하여 EAR 파일로 WAR 파일을 배포하여 해당 웹 어플리케이션에만 변경 영향을 미치도록 할 수도 있다. weblogic-application.xml 작성 방법은 이곳 [http://cwiki.apache.org/<strong>CXF</strong>20DOC/applicationserver-specific-configuration-guide.html#ApplicationServerSpecificConfigurationGuide-WebLogic]을참고하도록 한다.위에 언급한 것처럼 geronimo-ws-metadata_2.0_spec-1.1.2.jar 파일 복사 방법을 택하거나, 참고사항으로 언급한 weblogic-application.xml 파일을 추가 작성하는 방법을 택할 수 있다.(택1)• [Optional] Hibernate와 함께 사용 시EAR이나 WAR 파일로 배포 시 Hibernate Resource 파일(mapping xml)을 로드하지 못하는 문제가 발생하므로, 웹 어플리케이션을 WebLogic 서버에 배포 시 폴더 형태로 풀어진 웹 어플리케이션으로 배포하도록 한다.74

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!