JAX-RPC 웹 서비스 설정 파일 작성
본 장에서는 JAX-RPC 웹 서비스의 표준 웹 서비스 DD 파일 작성 방법과 JAX-RPC 매핑 파일 작성 방법에 대해 설명한다.
JAX-RPC 웹 서비스 DD 파일 작성
Jakarta EE JAX-RPC 웹 서비스는 webservices.xml이라는 이름을 가진 웹 서비스 서술자를 Java 클래스 Endpoint나 EJB Endpoint를 포함하는 압축 파일(WAR나 JAR)에 포함할 것을 요구한다.
webservices.xml을 EJB Endpoint의 경우에는 EJB JAR 파일의 META-INF 디렉터리에 저장하고, 서블릿 Endpoint의 경우에는 WAR 파일의 WEB-INF 디렉터리에 위치시킨다.
다음은 FileAttachmentService라는 웹 서비스의 webservices.xml 파일이다.
<?xml version="1.0"?> <webservices version="1.1" xmlns="http://java.sun.com/xml/ns/j2ee"> <webservice-description> <webservice-description-name> FileAttachmentService </webservice-description-name> <wsdl-file> WEB-INF/wsdl/FileAttachmentService.wsdl </wsdl-file> <jaxrpc-mapping-file> WEB-INF/FileAttachmentService-mapping.xml </jaxrpc-mapping-file> <port-component> <port-component-name>FileAttPort</port-component-name> <wsdl-port xmlns:ns2="urn:FileAttachmentService"> ns2:FileTransferIFPort </wsdl-port> <service-endpoint-interface> filetransfer.FileTransferIF </service-endpoint-interface> <service-impl-bean> <servlet-link>FileAttachmentServlet</servlet-link> </service-impl-bean> <handler> <handler-name>ServerAttachmentHandler</handler-name> <handler-class> filetransfer.ServerAttachmentHandler </handler-class> <init-param> <param-name>directory</param-name> <param-value>/temp</param-value> </init-param> </handler> </port-component> </webservice-description> </webservices>
webservices.xml 파일의 root element는 <webservices>이고, <webservice-description>을 하나 또는 그 이상을 필수 요소로 가진다.
<webservice-description>은 동일한 WSDL을 사용하는 Java 클래스나 EJB Endpoint의 집합을 서술한다. 즉, 패키징 내의 다른 WSDL 각각의 파일 들에 대해서 <webservice-description>이 하나씩 존재해야 한다. 예를 들면 2개의 다른 Java 클래스 Endpoint가 각각 WSDL을 별도로 가지고 하나의 WAR 파일 안에 존재한다면 각각의 JSE를 서술하기 위해서 <webservice-description>은 2개가 존재해야 한다.
<webservice-description>는 Jakarta EE Endpoint를 WSDL 포트 정의, DD 구현, JAX-RPC 매핑 파일 그리고 Endpoint 인터페이스로 바인딩시켜주는 역할을 하며, 본 장에서는 이들의 관계와 필요성에 대해서 설명한다.
-
<wsdl-file>
<wsdl-file>는 WSDL 문서의 WAR나 EJB JAR 파일 내에서의 상대적인 위치를 나타내며, webservices.xml 파일은 WSDL 파일과 같은 WAR나 JAR 파일 내에 위치해야 한다.
-
<jaxrpc-mapping-file>
<jaxrpc-mapping-file>는 JAX-RPC 매핑 파일의 위치를 지정한다. JAX-RPC 매핑 파일은 WSDL 파일과 Jakarta EE Endpoint 간의 매핑을 정의한다. JAX-RPC 매핑 파일에 관한 더 자세한 설명은 웹 서비스의 매핑 파일 작성을 참고한다.
-
<port-component>
<port-component>는 특정한 Java 클래스나 EJB Endpoint를 WSDL 문서 내의 특정한 port element로 매핑하는 역할을 한다. Java 클래스의 경우에 WSDL port 정의와 바인딩 정의는 웹 서비스를 호스트하기 위해 필요한 서블릿을 생성하는 데 사용된다.
EJB Endpoint의 경우에는 port와 바인딩 정의는 EJB 컨테이너가 SOAP 메시지를 무상태 Bean 객체에 보내기 위해 마셜링하는 데 사용된다.
-
<port-component-name>
<port-component-name>는 특정한 Java 클래스나 EJB Endpoint를 지정하기 위한 이름을 제공한다. 이 이름은 webservices.xml 파일 내에서 유일해야 한다.
-
<service-endpoint-interface>
Java 클래스를 Back-end로 가지는 웹 서비스의 경우, SEI의 이름을 지정하는 element이다.
EJB Endpoint 웹 서비스의 경우에도 마찬가지로 이 element에서 정의하며, 추가적으로 ejb-jar.xml의 <service-endpoint>에서도 같은 이름으로 정의해야 한다.
-
<service-impl-bean>
<service-impl-bean>는 서비스 배치가 수행되는 시점에 어떤 서비스의 로직 구현 정의가 Jakarta EE Endpoint가 될 것인지를 정의한다. Java 클래스의 경우에는 web.xml의 서블릿 정의를 가리키고, EJB Endpoint의 경우에는 ejb-jar.xml의 session 정의를 가리킨다.
JSE의 경우에는 <servlet-link>에 정의되며 예는 다음과 같다.
DocLitEchoService : <webservices.xml><?xml version="1.0"?> <webservices …> <webservice-description> <webservice-description-name> DocLitEchoService </webservice-description-name> <wsdl-file>WEB-INF/wsdl/DocLitEchoService.wsdl</wsdl-file> <jaxrpc-mapping-file> WEB-INF/DocLitEchoService-mapping.xml </jaxrpc-mapping-file> <port-component> <port-component-name>EchoPort</port-component-name> <wsdl-port xmlns:ns2="urn:DocLitService"> ns2:EchoPort </wsdl-port> <service-endpoint-interface> jeustest.webservices.java2wsdl.doclit.Echo </service-endpoint-interface> <service-impl-bean> <servlet-link>EchoServlet</servlet-link> </service-impl-bean> </port-component> </webservice-description> </webservices>
<serlvet-link>의 값은 web.xml 내의 <servlet-name>의 값과 일치해야 한다.
DocLitEchoService : <web.xml><?xml version="1.0"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"> <servlet> <servlet-name>EchoServlet</servlet-name> <servlet-class> jeustest.webservices.java2wsdl.doclit.EchoImpl </servlet-class> . . . </servlet> </web-app>
위와 마찬가지로 EJB Endpoint 웹 서비스의 경우 <ejb-link>를 사용하여 정의한다.
AddressBookService : <webservices.xml><?xml version="1.0"?> <webservices …> <webservice-description> <webservice-description-name> AddressBookService </webservice-description-name> <wsdl-file>META-INF/wsdl/AddressBookService.wsdl</wsdl-file> <jaxrpc-mapping-file> META-INF/AddressBookService-mapping.xml </jaxrpc-mapping-file> <port-component> <port-component-name> AddressBookIFPort </port-component-name> <wsdl-port xmlns:ns2="urn:AddressBookService"> ns2:AddressBookIFPort </wsdl-port> <service-endpoint-interface> address.AddressBookIF </service-endpoint-interface> <service-impl-bean> <ejb-link>AddressEJB</ejb-link> </service-impl-bean> </port-component> </webservice-description> </webservices>
<ejb-link>의 값은 ejb-jar.xml 파일 내의 <ejb-name>의 값과 일치해야 한다.
AddressBookService : <web.xml><?xml version="1.0" encoding="UTF-8"?> <ejb-jar …> <display-name>AddressEJB</display-name> <enterprise-beans> <session> <display-name>AddressEJB</display-name> <ejb-name>AddressEJB</ejb-name> <service-endpoint> address.AddressBookIF</service-endpoint> <ejb-class>address.AddressBookEJB</ejb-class> . . . </session> </enterprise-beans> </ejb-jar>
한 가지 유의해야 할 사항은 <servlet-link>나 <ejb-link>를 통해 연결될 대상들은 webservices.xml를 포함하는 압축 파일 안에 존재해야 한다는 것이다.
-
<handler>
메시지 핸들러는 Jakarta EE Endpoint가 보내고 받는 메시지를 걸러서 가공하는 역할을 한다.
webservices.xml 파일 안에서 이 메시지 핸들러들을 설정하고, 처리 순서를 지정할 수 있다. 메시지 핸들러에 대한 더 자세한 설명은 JAX-RPC 웹 서비스 SOAP 메시지 핸들러 생성을 참고한다.
다음은 핸들러를 설정한 webservices.xml의 작성 예이다.
FileAttachmentService : <webservices.xml><?xml version="1.0"?> <webservices version="1.1" xmlns="http://java.sun.com/xml/ns/j2ee"> <webservice-description> . . . <port-component> <port-component-name>FileAttPort</port-component-name> . . . <handler> <handler-name>ServerAttachmentHandler</handler-name> <handler-class> filetransfer.ServerAttachmentHandler </handler-class> <init-param> <param-name>directory</param-name> <param-value>/temp</param-value> </init-param> </handler> </port-component> </webservice-description> </webservices>
다음은 <handler>의 하위 항목에 대한 설명이다.
항목 설명 <handler-name>
정의되는 값은 webservices.xml 파일 안에서 유일한 값이 되어야 하며, 설정한 핸들러에 대한 식별자 역할을 한다.
<handler-class>
핸들러를 구현한 클래스를 정의한다.
정의되는 핸들러 클래스는 javax.xml.rpc.handler.Handler 인터페이스를 직접 또는 간접적으로 구현해야 한다.
<init-param>
필수 사항은 아니며 메시지 핸들러의 생성 주기의 시작 단계에서 핸들러를 초기화하기 위해 전달될 파라미터를 정의한다. 런타임에 HandlerInfo.getHandlerConfig() 메소드를 실행해서 얻어지는 java.util.Map 객체로부터 파라미터들을 가져 올 수 있다.
<soap-header>
핸들러가 처리해야 하는 SOAP Header 블록의 큐 네임(Q Name : Qualified Name)을 정의하며, <handler>는 하나 이상의 <soap-header>를 포함할 수 있다.
<soap-role>
Header 블록을 처리할 때 핸들러가 정하는 역할을 정의한다.
<soap-role> 값이 <soap-header>와 짝을 이루어서 정의될 때에만 어떤 Header 블록을 핸들러가 처리하는지 정확하게 알 수 있다.
SOAP 메시지는 각각의 Header 블록을 처리하기 위한 역할을 명시적으로 지정할 수 있다. actor 속성이 정의되어 있으면 지정된 역할을 수행하는 노드만이 Header 블록을 처리하고, actor 속성이 정의 되지 않은 경우에는 최종적인 메시지 수신자가 header 블록을 처리한다.
-
웹 서비스의 매핑 파일 작성
JAX-RPC 매핑 파일은 JEUS 웹 서비스에 내장된 JAX-RPC 컴파일러가 WSDL 문서와 웹 서비스 Endpoint를 나타내는 Java 인터페이스의 관계를 이해하는 것을 도와준다. 많은 경우에 WSDL과 Java의 매핑은 매핑 파일이 없어도 큰 문제가 없지만 명시적인 정의가 필요할 때가 있으며, 그러한 필요에 의해서 JAX-RPC 매핑 파일이 도입되었다.
JAX-RPC 매핑 파일은 Jakarta EE 웹 서비스 Endpoint나 Jakarta EE 웹 서비스 클라이언트를 사용할 때마다 필요하며, WSDL 문서와 JAX-RPC 매핑 파일은 1대 1로 대응한다. 즉, 각각의 WSDL 파일에는 하나씩의 JAX-RPC 매핑 파일이 존재한다.
JAX-RPC 매핑 파일 내용
JAX-RPC 매핑 파일은 다음과 같은 관계에 있는 요소들의 매핑을 정의한다.
-
XML 복합 타입(Complex Type)과 Java Bean
-
Fault 메시지와 예외 클래스
-
WSDL의 portType 정의와 SEI(Service Endpoint Interface)
-
WSDL의 서비스 정의와 서비스 인터페이스
JAX-RPC 매핑 파일에 정의되지 않은 것들은 WSDL과 XML의 Java로의 표준 매핑 법칙을 따라서 매핑된다. 그리고 매핑 파일에서 정의 되는 것들은 항상 표준 매핑 법칙에 우선한다.
JAX-RPC 매핑 파일 작성
매핑 파일은 상당히 내용이 복잡해 보이고, 크기에 있어서도 단일 설정 파일 중에 큰 편이다.
전체적인 설정 파일의 구성은 다음과 같다.
<java-wsdl-mapping> <package-mapping/> <java-xml-type-mapping/> <exception-mapping/> <service-interface-mapping/> <service-endpoint-interface-mapping> <service-endpoint-method-mapping/> <service-endpoint-method-mapping/> . . . </service-endpoint-interface-mapping> <service-interface-mapping/> <service-endpoint-interface-mapping> <service-endpoint-method-mapping/> <service-endpoint-method-mapping/> . . . </service-endpoint-interface-mapping> </java-wsdl-mapping>
-
<java-wsdl-mapping>
JAX-RPC 매핑 파일의 최상위 element이며, 다른 매핑 element들을 포함하고 있다.
-
<package-mapping>
JAX-RPC 컴파일러가 WSDL에 정의된 여러 가지 타입에 대해 Java 클래스와 인터페이스 정의를 생성하려고 할 경우 사용된하는 항목으로 반드시 설정되어야 한다.
<package-type>의 값은 Java 패키지의 이름이며, <namespaceURI>의 값은 지정된 Java 패키지로 매핑되어야 하는 XML 이름 공간이다.
<java-wsdl-mapping version="1.1" xmlns="http://java.sun.com/xml/ns/j2ee"> <package-mapping> <package-type>address</package-type> <namespaceURI>urn:AddressBookService</namespaceURI> </package-mapping> . . . </java-wsdl-mapping>
-
<java-xml-type-mapping>
XML Schema 복합 타입(Complex Type)이나 단순 타입(Simple Type)을 사용할 때 필요하며, XML Schema와 Java 타입 간의 관계를 정의한다. XML Schema에 정의된 built-in 타입이 Java로 표준적인 매핑이 된다면 이 element를 사용하지 않아도 된다.
<java-wsdl-mapping version="1.1" xmlns="http://java.sun.com/xml/ns/j2ee"> . . . <java-xml-type-mapping> <java-type>address.Address</java-type> <ns1:root-type-qname xmlns:ns1=”http://java.sun.com/xml/ns/j2ee” xmlns="urn:AddressBookService"> Address </ns1:root-type-qname> <qname-scope>complexType</qname-scope> <variable-mapping> <java-variable-name>addr</java-variable-name> <xml-element-name>addr</xml-element-name> </variable-mapping> <variable-mapping> <java-variable-name>street</java-variable-name> <xml-element-name>street</xml-element-name> </variable-mapping> <variable-mapping> <java-variable-name>zipcode</java-variable-name> <xml-element-name>zipcode</xml-element-name> </variable-mapping> </java-xml-type-mapping> . . . </java-wsdl-mapping>
-
<exception-mapping>
WSDL 결함(fault) 메시지를 Java 예외 클래스로 매핑한다.
<java-xml-mapping> . . . <exception-mapping> <exception-type>CLASS_NAME</exception-type> <wsdl-message>WSDL_MESSAGE_NAME</wsdl-message> </exception-mapping> . . . </java-xml-mapping>
-
<service-interface-mapping>
WSDL의 서비스 정의를 JAX-RPC 서비스 인터페이스 타입으로 매핑한다.
<service-interface>는 WSDL의 서비스 정의를 나타내는 Java 인터페이스의 클래스 이름을 정의하고, 서비스 인터페이스의 패키지 이름은 <package-mapping>에 정의된 패키지 이름과 일치해야 한다.
<port-mapping>는 서비스 인터페이스의 getPortName() 메소드의 포트 이름을 WSDL의 <port>와 대응하게 정의한다.
<java-xml-mapping…> . . . <service-interface-mapping> <service-interface> address.AddressBookService </service-interface> <ns3:wsdl-service-name xmlns:ns3="http://java.sun.com/xml/ns/j2ee" xmlns="urn:AddressBookService"> AddressBookService </ns3:wsdl-service-name> <port-mapping> <port-name>AddressBookIFPort</port-name> <java-port-name>AddressBookIFPort</java-port-name> </port-mapping> </service-interface-mapping> . . . </java-xml-mapping>
위와 같이 정의될 경우 생성되는 Java 서비스 인터페이스 정의는 다음과 같다.
Java 서비스 인터페이스 정의 : <AddressBookService.java>package address; public interface AddressBookService extends javax.xml.rpc.Service { public java.lang.String getAddressBookIFPortAddress(); public address.AddressBookIF getAddressBookIFPort() throws javax.xml.rpc.ServiceException; public address.AddressBookIF getAddressBookIFPort(java.net.URL portAddress) throws javax.xml.rpc.ServiceException; }
-
<service-endpoint-interface-mapping>
SEI를 WSDL의 portType과 바인딩 정의로 매핑한다. 이 element는 JAX-RPC 컴파일러가 적절한 Endpoint Stub과 Endpoint 인터페이스를 생성할 때 필요한 정보를 제공한다. 또한 WSDL의 operation과 message part 정의가 어떻게 Java Endpoint 메소드의 정의로 매핑될 것인지에 대한 상세 정보를 제공한다.
다음은 AddressBookService의 매핑 파일에 정의된 예이다.
<java-wsdl-mapping…> . . . <service-endpoint-interface-mapping> <service-endpoint-interface> address.AddressBookIF </service-endpoint-interface> <ns4:wsdl-port-type xmlns:ns4="http://java.sun.com/xml/ns/j2ee" xmlns="urn:AddressBookService"> AddressBookIF </ns4:wsdl-port-type> <ns5:wsdl-binding xmlns:ns5="http://java.sun.com/xml/ns/j2ee" xmlns="urn:AddressBookService"> AddressBookIFSoapBinding </ns5:wsdl-binding> <service-endpoint-method-mapping> <java-method-name>add</java-method-name> <wsdl-operation>add</wsdl-operation> <wrapped-element/> <method-param-parts-mapping> <param-position>0</param-position> <param-type>address.PersonInfo</param-type> <wsdl-message-mapping> <ns6:wsdl-message xmlns:ns6="http://java.sun.com/xml/ns/j2ee" xmlns="urn:AddressBookService"> addRequest </ns6:wsdl-message> <wsdl-message-part-name> parameters </wsdl-message-part-name> <parameter-mode>IN</parameter-mode> </wsdl-message-mapping> </method-param-parts-mapping> <wsdl-return-value-mapping> <method-return-value> address.PersonInfo[] </method-return-value> <ns7:wsdl-message xmlns:ns7=”http://java.sun.com/xml/ns/j2ee“ xmlns="urn:AddressBookService"> addResponse </ns7:wsdl-message> <wsdl-message-part-name> parameters </wsdl-message-part-name> </wsdl-return-value-mapping> </service-endpoint-method-mapping> . . . </service-endpoint-interface-mapping> . . . </java-wsdl-mapping>