JAX-RPC 웹 서비스 구현
본 장에서는 JAX-RPC 웹 서비스를 구현하는 여러 가지 방식에 대한 설명한다.
1. 개요
JEUS JAX-RPC 웹 서비스 구현 작업은 웹 서비스를 구성하는 Back-end 구성 요소인 Java 코드를 작성 또는 컴파일하는 것을 의미한다. 기본적으로 JEUS JAX-RPC 웹 서비스는 Java 클래스, EJB와 같은 2가지 타입의 웹 서비스 Back-end 구성 요소를 지원한다.
JEUS JAX-RPC 웹 서비스를 구현하는 주요 절차는 다음과 같다.
-
웹 서비스를 구성하는 Back-end 구성 요소인 Java 코드를 작성한다.
-
SOAP 메시지의 내용을 직접 다루기를 원하거나, SOAP 메시지의 Attachment에 직접 접근하기를 원한다면 직접 SOAP 메시지 핸들러나 핸들러 체인(Chain)을 생성한다.
-
Java 코드를 컴파일한다.
2. Java 클래스 웹 서비스 구현
Java 클래스 웹 서비스는 JAX-RPC 웹 서비스의 구현에서 웹 서비스를 생성하는 가장 간단한 방법이다. 간단한 예를 통해 구현하는 방법에 대해 설명한다.
2.1. 간단한 예제
Java 클래스 웹 서비스를 생성하기 위해서는 SEI와 구현 클래스를 정의해야 한다. SEI는 Java 클래스 웹 서비스 Endpoint가 Java 메소드의 형식으로 지원할 웹 서비스 오퍼레이션들을 정의한다. 구현 클래스는 이러한 SEI들을 구현한다.
다음의 Endpoint 인터페이스는 echoString과 echoString_double이라는 웹 서비스 오퍼레이션들을 정의하고 있다.
package jeustest.webservices.java2wsdl.doclit;
public interface Echo extends java.rmi.Remote {
public String echoString(String arg11)
throws java.rmi.RemoteException;
public String echoString_double(String arg1, String arg2)
throws java.rmi.RemoteException;
}
Endpoint 인터페이스는 외부에 공개되어 접근 가능한 웹 서비스 오퍼레이션들을 정의한다. 즉, SOAP이라는 프로토콜을 사용하여 접근할 수 있는 오퍼레이션들을 정의한다. Endpoint 인터페이스는 java.rmi.Remote 인터페이스를 직접적 또는 간접적으로 확장해야 하며, 정의된 메소드들은 java.rmi.RemoteException 타입을 Exception으로 던져야 한다. 위와 같이 서비스 오퍼레이션들을 정의하고 나면 이를 구현하는 로직이 필요하다. 그 역할을 하는 것이 구현 클래스이다.
다음이 구현 클래스에 대한 예이다.
package jeustest.webservices.java2wsdl.doclit;
public class EchoImpl implements Echo {
public String echoString(String input0)
throws java.rmi.RemoteException {
return input0;
}
public String echoString_double(String input0, String input1)
throws java.rmi.RemoteException {
return input0+input1;
}
}
구현 클래스는 Endpoint 인터페이스를 구현하고 있다. Jakarta EE 서버 내에서 인스턴스화되어 실행되며 런타임에는 웹 서비스로 동작하게 될 것이다.
2.2. Java 클래스 작성 원칙
Java 클래스 Back-end로서 웹 서비스를 구현할 때 다음의 규칙들을 준수해야 한다.
-
SEI를 정의한다.
-
public 클래스를 정의한다.
-
파라미터 없는 디폴트 생성자를 정의한다.
-
웹 서비스에서 public, non-static으로 Export되는 Java 클래스의 메소드들을 정의한다.
-
스레드에 안전한(Thread-safety) Java 코드를 작성한다.
-
상호 운용성을 위해서 오버 로딩된 메소드들을 사용하지 말아야 한다.
위와 같은 조건을 만족하는 경우 다음과 같은 절차에 따라서 웹 서비스를 구현한다.
-
웹 서비스 메소드를 포함하고 있는 Java 클래스를 정의한다.
-
서비스로 명시적으로 공개할 메소드를 위한 인터페이스를 정의한다.
3. EJB 웹 서비스 구현
EJB는 Jakarta EE 웹 서비스를 개발하는 데 있어 이전에 언급되었던 Java 클래스 웹 서비스 프로그래밍 모델보다 좀 더 복잡하지만 더 풍부한 기능을 가질 수 있게 하는 프로그래밍 모델이다. 이러한 복잡성은 트랜잭션을 자동으로 관리하게 되면서 부수적으로 발생하는 것이라고 볼 수 있다.
EJB 웹 서비스를 구현하기 위해서는 EJB에 대한 어느 정도의 이해를 필요로 한다. 만약 웹 서비스를 구현하는 데 있어 EJB를 사용하지 않아도 된다면, 본 장의 내용은 숙지하지 않아도 된다.
3.1. 간단한 예제
Stateless Session EJB 또한 웹 서비스로 Export될 수 있다. 이 경우에도 SEI가 필요하다.
다음의 Endpoint 인터페이스(HelloIF.java)는 sayHello(String) 웹 서비스 오퍼레이션을 정의하고 있다.
package helloejb;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface HelloIF extends Remote {
public String sayHello(String s) throws RemoteException;
}
Endpoint 인터페이스는 외부에 공개되어 접근 가능한 웹 서비스 오퍼레이션들을 정의한다. 즉, SOAP이라는 프로토콜을 사용하여 접근할 수 있는 오퍼레이션들을 정의한다. Endpoint 인터페이스는 java.rmi.Remote 인터페이스를 직접적 또는 간접적으로 확장해야 하며, 정의된 메소드들은 java.rmi.RemoteException 타입을 Exception으로 던져야 한다. 위와 같이 서비스 오퍼레이션들을 정의한 후에는 이를 구현하는 로직이 필요하다. 여기서는 EJB가 그 역할을 담당한다.
다음은 리모트 인터페이스의 예이다.
package helloejb;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
public interface Hello extends EJBObject
{
String sayHello(String s) throws RemoteException;
}
다음은 홈 인터페이스의 예이다.
package helloejb;
import java.io.Serializable;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface HelloHome extends EJBHome
{
Hello create() throws RemoteException, CreateException;
}
다음은 Session Bean을 구현한 EJB Endpoint Bean 클래스이다.
package helloejb;
import java.rmi.RemoteException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import java.lang.*;
public class HelloEJB implements SessionBean {
public HelloEJB() {}
public String sayHello(String s) throws RemoteException {
try {
Thread.currentThread().sleep(500);
} catch (Exception ex) {
throw new RemoteException("" + ex);
}
return "Hello World!" + s;
}
public void ejbCreate() {}
public void ejbRemove() throws RemoteException {}
public void setSessionContext(SessionContext sc) {}
public void ejbActivate() {}
public void ejbPassivate() {}
}
4. WSDL로부터 웹 서비스 구현
본 안내서의 대부분은 웹 서비스를 구성하는 Back-end 구성 요소인 Java 코드를 작성하는 것으로부터 시작하는 것을 가정하고 있다.
개발 환경에 따라서 WSDL로부터 서비스 인터페이스를 생성할 수 있다. 이 경우 사용자는 wsdl2java Ant Task를 수행하여 서비스 인터페이스를 얻을 수 있다. wsdl2java Ant Task는 사용자가 작성했거나 가지고 있는 WSDL 파일을 입력으로 한다.
다음은 wsdl2java Ant를 수행하기 위한 빌드 파일의 예이다.
<target name="do-package-war">
...
<antcall target="wsdl2java">
<param name="wsdl2java.option"
value="-import:server -d ${build.war.dir}/WEB-INF/classes
-package sample.datahandleronly.service
-outputmapping ${build.war.dir}/WEB-INF/SubmitBookService-mapping.xml
-compile ${src.web}/WEB-INF/wsdl/SubmitBookService.wsdl" />
</antcall>
...
</target>
다음과 같은 명령을 수행하여 웹 서비스 서비스 인터페이스 소스 코드를 생성할 수 있다.
$ ant do-package-war
사용자는 생성된 서비스 인터페이스에 대한 서비스 구현체를 Java 클래스 웹 서비스 구현과 EJB 웹 서비스 구현의 구현 방식에 따라서 생성한다.
5. SAAJ의 사용
통상적인 SOAP 메시지는 SOAP Body 안에 포함되지만 특정한 Java 타입을 웹 서비스 오퍼레이션을 구현하는 메소드의 파라미터나 리턴 타입으로 사용할 경우에는 SOAP Attachment 형태로 전송된다.
JEUS 웹 서비스는 SAAJ(SOAP with Attachments API for Java)의 사용을 위해 Java에서 MIME 타입으로의 형태 전환을 다음과 같이 정의한다.
Java 타입 | MIME 타입 |
---|---|
java.awt.Image |
image/gif or image/jpeg |
java.lang.String |
text/plain |
javax.mail.internet.MimeMultipart |
multipart/* |
javax.xml.transform.Source |
text/xml or application/xml |
위에 열거된 각각의 MIME 타입에 대해 JAX-RPC Endpoint Stub이 특정한 Java 타입을 적절히 인코딩된 데이터의 스트림으로 변환 또는 역변환 작업을 한다. 보다 자세한 설명은 JAX-RPC 웹 서비스 SOAP 메시지 핸들러 생성을 참고한다.