 |
|
난이도 : 중급 Nalla Senthilnathan, IT Consultant, Greater Detroit
원문 게재일 : 2009 년 10 월 14 일 번역 게재일 : 2009 년 11 월 03 일 이 기사에서는 웹 서비스 구성요소를 OSGi 번들로 개발하고 전개하는 과정을 단계별로
설명합니다. Apache CXF의 분산 OSGi 프레임워크인 cxf-dosgi와 Eclipse의 Equinox OSGi 프레임워크를 함께 사용하여
서비스 번들을 개발하고 전개합니다. 간단한 웹 애플리케이션 클라이언트를 개발하여 분산 서비스 번들을
액세스합니다. 웹 서비스 제공자는 동시에 다양한 버전의 서비스를 지원해야 하는 과제에 직면하곤
합니다. 또한 이 기사에서는 OSGi를 통해 이러한 요구를 만족시킬 수 있는 완벽한 환경을
제공하는 방법을 제시합니다.
소개
OSGi는 Java용 동적 모듈 시스템이다. OSGi Alliance(참고자료 확인)에서 이러한 모듈 시스템의 스펙을
발행한다. 다양한 OSGi 컨테이너가 있지만 널리 사용되는 OSGi 컨테이너는 Eclipse Equinox(참고자료 확인)와 Apache Felix이다(참고자료 확인). OSGi는
재사용 가능한 모듈식 Java 프로그램을 개발하고 전개하는 데 필요한 프레임워크로 빠르게 확산되고 있다.
OSGi 컨테이너를 사용하면 Java 모듈(OSGi 식으로는 "번들"에 해당)을 jar 형식으로 전개할 수 있다. 다양한 버전의 번들을 같은
컨테이너로 전개할 수 있다는 점이 OSGi의 매력적인 기능이다. OSGi 컨테이너에서 전개된 모든 번들은 하나의 JVM에서
실행된다. 서비스 클라이언트가 이러한 OSGi 컨테이너 외부에 있는 경우에는 해당 서비스 번들에 분산 기능이
있어야 한다. Apache cxf-dosgi(참고자료 확인)는 새로운 서비스 프레임워크로 이 프레임워크를 사용하면 OSGi 번들에서
분산 기능을 사용할 수 있다.
웹 서비스 제공자가 새로운 버전의 서비스를 개발하는 경우 계속해서 기존 클라이언트를 지원해야 하는
상황이 자주 벌어진다. 따라서 웹 서비스 제공자는 다양한 버전의 서비스를 동시에 전개하고 유지해야
한다. OSGi에는 이러한 요구를 해결할 수 있는 주목할 만한 선택사항이 내재되어 있다.
OSGi 컨테이너와 웹 서비스 프레임워크를 각각 Eclipse Equinox와 Apache CXF를 선택했는데, 이는 CXF 팀에서
OSGi 번들에 분산 기능을 제공하는 cxf-dosgi라는 새로운 프레임워크를 출시했기 때문이다. 이 프레임워크를 사용하면
OSGi 번들로 웹 서비스를 개발하고 전개할 수 있다. 다양한 버전의 번들이 동시에 존재할 수 있기 때문에 여러 가지
버전의 웹 서비스를 동시에 전개하고 유지할 수 있다. Apache Tomcat을 서블릿 컨테이너로 사용하여 해당 클라이언트를 전개한다.
이 기사에서는 cxf-dosgi 서비스 번들을 개발하는 과정과 이것을 OSGi 컨테이너에서 전개하고 OSGi 컨테이너가 실행 중인 JVM과는
다른 JVM에서 실행 중인 간단한 웹 클라이언트를 사용하여 액세스하는 방법을 단계별로 살펴본다. 또한 동일한 서비스를 다양한 버전으로
개발하고 이를 같은 OSGi 컨테이너로 전개하는 과정을 설명하며 두 가지 버전의 서비스가 동시에 다양한 유형의 클라이언트에 서비스를
제공할 수 있다는 것을 보여준다.
선수조건
먼저 Eclipse 3.5(Galileo)를 다운로드하여 설치한다. Eclipse 3.5에는 Equinox(참고자료 확인)라는 OSGi
프레임워크가 포함되어 있다.
그런 다음 cxf-dosgi 단일 번들 배포판 및 OSGi Compendium 번들을 다운로드한다. 이 두 번들을 같은 로컬 디렉토리로
다운로드한다. 아래의 참고자료에 있는 다운로드 링크를 참조한다.
Apache Tomcat 5.5.9를 다운로드하여 설치한다. 이 서블릿 컨테이너를 OSGi 컨테이너(Eclipse) 밖에서 사용하여
서비스 클라이언트를 설치하고 실행한다.
OSGi 컨테이너 준비
분산 서비스 번들을 개발하기 전에 먼저 OSGi 컨테이너를 시작하고 csf-dosgi를 서비스 제공자 인에이블러로 등록하여
OSGI 컨테이너를 준비한다.
작업 스페이스를 비워둔 상태로 Eclipse 3.5를 시작한다. 퍼스펙티브를 "Plug-In Development"로
설정한다. Eclipse 플러그인은 기본적인 OSGi 번들이다.
그런 다음 아래와 같은 메뉴 옵션을 사용하여 cxf-dosgi OSGi Compendium 번들과 OSGi Compendium 번들을 가져온다.
File/Import/Plug-In Development/Plug-ins and Fragments
그리고 번들을 다운로드한 디렉토리를 선택한다. 아래 그림 1을 참조한다.
그림 1. 필수 번들 가져오기 디렉토리 위치 지정
Next를 누른다. 그러면 Eclipse의 다음 대화 상자에서 다운로드한 번들이 표시된다. 아래 그림 2를 참조한다.
그림 2. 필수 번들을 가져와서 다운로드한 번들을 선택하기
Add All을 누른 후 다시 Finish를 누른다. Eclipse에서 org.osgi.compendium 및 cxf-dosgi-ri-singlebundle-distribution라고 하는
두 개의 플러그인 개발 프로젝트가 자동으로 작성된다. 그 다음에는 OSGi Compendium 번들을 dosgi 번들의 필수 번들로
지정해야 한다. cxf-dosgi-ri-singlebundle-distribution 프로젝트에서 META-INF/MANIFEST.MF 파일을 두 번
누른다. Eclipse의 디자인 모드에서 명시 파일이 열리면 Dependencies 탭을 선택한 후 org.osgi.compendium을
"Required Plug-ins"에 추가한다. 이제 Eclipse 환경은 그림 3과 같이 된다.
그림 3. 필수 번들 가져오기
이제 OSGi 컨테이너를 사용하여 몇 가지 분산 서비스를 전개할 차례이다.
서비스 번들의 개발
다음에는 하나의 문자열(단어의 의미)을 응답으로 리턴하는 하나의 lookupWord(string) 메소드를 사용하여
DictionaryService라고 하는 간단한 POJO 기반 웹 서비스를 작성한다.
Eclipse에서 서비스 번들을 작성하려면 먼저 퍼스펙티브를 "Plug-in Development"로 설정해야 한다. DictionaryService라고
하는 새로운 플러그인 프로젝트를 작성한다. 프로젝트를 작성하는 과정에서 패키지 구조를 com.demo.cxfdemo.Activator로 선택한다.
Eclipse에서 작성된 기본 Activator.java를 첨부된 번들(cxf-dosgi-dw-article.zip 파일의 DictionaryService_1.0.0.200908011529.jar)에
있는 DictionaryService.java 및 DictionaryServiceImpl.java, Activator.java로 바꾼다. (아래의 다운로드 링크를 참조한다.)
DictionaryService 프로젝트에서 META-INF/MANIFEST.MF를 두 번 누른다. 그러면 Eclipse에 명시 파일의 디자인 뷰가
표시된다. Dependencies 탭을 누르고 Required Plug-ins의 내용을 지운 후 Imported Packages에 org.osgi.framework를
추가한다. 그러면 Eclipse는 그림 4와 같이 표시된다.
그림 4. 서비스 번들의 작성
Activator.java, DictionaryService.java 및 DictionaryServiceImpl.java의 소스는 Listing 1과 같다.
Listing 1. DictionaryService 번들 코드
package com.demo.cxfdosgi;
import java.util.Dictionary;
import java.util.Hashtable;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
public class Activator implements BundleActivator {
private ServiceRegistration registration;
public void start(BundleContext bc) throws Exception {
Dictionary<String, String> props = new Hashtable<String, String>();
props.put("osgi.remote.interfaces", "*");
props.put("osgi.remote.configuration.type", "pojo");
props.put("osgi.remote.configuration.pojo.address",
"http://localhost:9000/DictionaryService");
registration = bc.registerService(DictionaryService.class.getName(),
new DictionaryServiceImpl(), props);
}
public void stop(BundleContext context) throws Exception {
registration.unregister();
}
}
package com.demo.cxfdosgi;
public interface DictionaryService {
public String lookupWord(String word) throws Exception;
}
package com.demo.cxfdosgi;
public class DictionaryServiceImpl implements DictionaryService {
public String lookupWord(String word) throws Exception {
return word + " means...";
}
}
|
해당 웹 서비스는 인터페이스 및 구현 부분이 기본적으로 POJO를 기반으로 한다. Activator 클래스는 서비스
등록 정보를 설정하고 해당 서비스를 등록한다. DictionaryService에서는 cxf 클래스를 구현하거나 확장할 필요가
거의 없다. dosgi 단일 번들을 필수 플러그인으로 설정할 필요조차 없다. cxf-dosgi의 멋진 기능으로 인해 Run Configuration을 실행하면
이것이 cxf 웹 서비스로 전개된다.
서비스 번들의 전개
다음 단계에서는 해당 서비스 번들을 전개하고 실행한다. 이렇게 하려면 Run Configuration을 작성해야
한다. DictionaryService 프로젝트를 오른쪽 마우스 단추로 누른 후 Run As/Run Configurations을
선택한다. demo_dosgi라고 하는 OSGi 프레임워크 폴더에서 새로운 구성을 작성한다. Run Configuration 팝업
대화 상자가 그림 5와 같이 표시된다.
그림 5. Run Configuration
Apply와 Run을 차례로 누른다. 이제 Eclipse에서는 내부 OSGI 프레임워크(Equinox)가 시작되어 작업 스페이스에
3개의 번들이 설치되고 실행된다. 그러면 Eclipse 환경은 그림 6과 같이 된다.
그림 6. Run 번들
Eclipse에서는 osgi> 프롬프트가 자동으로 표시되지 않는다는 점에 유의한다. 콘솔 창을 한 번 눌러서 이 프롬프트를
표시한다. 이 프롬프트에서 ss(short status) 명령을 실행하여 해당 번들의 상태를 확인한다. 사용 가능한 다른 명령에 대한 목록을
표시하려면 프롬프트에서 ?를 실행한다. 또한 위 화면에서 해당 서비스의 엔드포인트 URL(http://localhost:9000/DictionaryService)을
사용할 수 있는지 확인한다. 이렇게 하려면 WSDL 컨텐츠를 표시하는 브라우저의 주소 입력창에 http://localhost:9000/DictionaryService?wsdl을
입력한다. 이 xml 문서를 이름을 DictionaryService.wsdl로 하여 임시 폴더에 저장한다. 이 파일은 다음 섹션에서 클라이언트를
생성하기 위해 사용된다.
서비스를 호출할 수 있는 웹 클라이언트의 개발
새롭게 전개된 웹 서비스를 호출하기 위해 이제 간단한 웹 애플리케이션 클라이언트를 작성한다.
Eclipse에서 Java EE Perspective로 전환한다. DictionaryServiceClient라고 하는 새로운 동적 웹 애플리케이션을
작성한다. DictionaryService.wsdl을 WebContent 폴더로 복사한다. DictionaryService.wsdl 파일을 마우스 오른쪽 단추로 누른 후
Web Services/Generate Client를 선택한다. 그러면 클라이언트 Java 파일 세트가 Eclipse의 src 폴더에 com.demo.cxfdosgi
패키지 이름으로 작성된다. 이제 서비스 프록시를 호출할 수 있는 dictionaryServiceClient.jsp를 아래 Listing 2와 같이 작성한다.
Listing 2. dictionaryServiceClient.jsp 코드
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"
import="com.demo.cxfdosgi.DictionaryServicePortTypeProxy"%>
<html>
<body>
<%
DictionaryServicePortTypeProxy proxy = new
DictionaryServicePortTypeProxy();
out.println("?? DictionaryService response =
"+proxy.lookupWord("whatisthis"));
%>
</body>
</html>
|
DictionaryServiceClient 프로젝트를 마우스 오른쪽 단추로 누른 후 DictionaryServiceClient.war 파일을
내보낸다. 이 파일을 C:/jakarta-tomcat-5.5.9/webapps 폴더로 복사한다. C:/jakarta-tomcat-5.5.9/bin/startup.exe를
실행한 후 http://localhost:8082/DictionaryServiceClient/dictionaryServiceClient.jsp를 액세스한다. 그러면 브라우저에 다음과
같이 표시된다.
?? DictionaryService response = whatisthis means...
|
Eclipse와 Tomcat이 두 개의 서로 다른 JVM에서 실행 중이기 때문에 분산 클라이언트를 사용하여 이 서비스를
테스트했다. 주: Eclipse에서 이미 8080 포트를 사용하여 cxf 웹 서비스를 전개 중이기 때문에 Tomcat의 HTTP 포트는 8082로 설정하였다.
새로운 버전의 서비스 번들
OSGi 번들로 웹 서비스를 전개할 때 흥미로운 부분은 다양한 버전의 웹 서비스를 동시에 전개할 수 있다는
점이다. 이제 다음 버전의 DictionaryService를 DictionaryServiceV2로 개발하는데, 여기에서는 두 개의 문자열로 구성된 배열을
리턴하는 lookupWord 메소드를 사용하며 한 문자열은 단어의 의미이며 다른 하나는 그 동의어이다. 이 메소드의 서명을 변경하는
중이기 때문에 기존 클라이언트가 분명히 중단된다. 개정된 웹 서비스를 별도의 번들로 전개하여 새 클라이언트에서 새 버전의
서비스를 사용할 수 있도록 하는 동안 기존 클라이언트에서 계속 작업할 수 있다.
Eclipse에서 Plug-in Development Perspective로 전환하고 아래의 소스와 함께 3개의 파일(Activator.java,
DictionaryServiceV2.java 및 DictionaryServiceV2Impl.java)을 사용하여 DictionaryServiceV2라고 하는
새 플러그인 프로젝트를 작성한다.
Listing 3. DictionaryServiceV2 번들 코드
package com.demo.cxfdosgi.v2;
import java.util.Dictionary;
import java.util.Hashtable;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
public class Activator implements BundleActivator {
private ServiceRegistration registration;
public void start(BundleContext bc) throws Exception {
Dictionary<String, String> props = new Hashtable<String, String>();
props.put("osgi.remote.interfaces", "*");
props.put("osgi.remote.configuration.type", "pojo");
props.put("osgi.remote.configuration.pojo.address",
"http://localhost:9000/DictionaryServiceV2");
registration = bc.registerService(DictionaryServiceV2.class.getName(),
new DictionaryServiceV2Impl(), props);
}
public void stop(BundleContext context) throws Exception {
registration.unregister();
}
}
package com.demo.cxfdosgi.v2;
public interface DictionaryServiceV2 {
/**
* @param word - String, whose meaning and synonyms are requested
* @return String[] - where String[0] has the word meaning and
* String[1] has synonyms
* @throws Exception
*/
public String[] lookupWord(String word) throws Exception;
}
package com.demo.cxfdosgi.v2;
public class DictionaryServiceV2Impl implements DictionaryServiceV2 {
public String[] lookupWord(String word) throws Exception {
// TODO Auto-generated method stub
String[] result = new String[2];
result[0] = word + " means...";
result[1] = "Synonyms:...";
return result;
}
}
|
Eclipse 창은 그림 7과 같이 표시된다.
그림 7. DictionaryServiceV2 번들의 작성
demo_dosgi Run Configuration을 편집한 후 DictionaryServiceV2 번들이 그림 8과 같이 구성에 포함되었는지 확인한다.
그림 8. 개정된 Run Configuration
Apply와 Run을 차례로 누른다. 이제 Eclipse에서 OSGi 프레임워크를 다시 시작한 후 네 번째 번들(DictionaryServiceV2)을
설치하고 네 가지 번들을 모두 시작한다. Eclipse는 그림 9와 같이 표시된다.
그림 9. Run 번들
여기에서 네 가지 번들이 모두 설치되어 실행 중인지 확인한다. 또한 로그 메시지를 이용하여 다음과 같은 서비스 엔드포인트를
확인한다.
http://localhost:9000/DictionaryService 및
http://localhost:9000/DictionaryServiceV2는
사용 중이다. 브라우저에서 http://localhost:9000/DictionaryServiceV2?wsdl과 같은 두 번째 서비스를 액세스한 후 표시된
wsdl 컨텐츠를 DictionaryServiceV2.wsdl 파일에 저장한다.
새로운 서비스의 호출
새 버전의 웹 서비스를 호출하려면 새 클라이언트를 생성해야 한다.
새 프로젝트인 DictionaryServiceV2Client를 동적 웹 애플리케이션으로 작성한다. 앞서 설명한 단계와 마찬가지로
wsdl 파일을 복사하고 Java 클라이언트를 생성한다. 다음과 같이 새로운 dictionaryServiceV2Client.jsp 파일을 작성한다.
Listing 4. dictionaryServiceV2Client.jsp 코드
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"
import="com.demo.cxfdosgi.v2.DictionaryServiceV2PortTypeProxy"%>
<html>
<body>
<%
DictionaryServiceV2PortTypeProxy proxy = new
DictionaryServiceV2PortTypeProxy();
String[] resp = proxy.lookupWord("whatisthis");
out.println("?? DictionaryService response = "+resp[0]);
%>
<br/>
<%
out.println("?? DictionaryService response = "+resp[1]);
%>
</body>
</html>
|
이 프로젝트를 DictionaryServiceV2Client.war로 내보낸 후 Eclipse 밖에서 실행 중인 Tomcat 서버에
설치한다. 브라우저로 http://localhost:8082/DictionaryServiceV2Client/dictionaryServiceV2Client.jsp를 액세스하면
다음과 같이 표시된다.
?? DictionaryService response = whatisthis means...
?? DictionaryService response = Synonyms:...
|
이것으로 두 가지 버전의 웹 서비스를 성공적으로 개발하고, 전개하고, 테스트했다.
요약
이 기사에서는 POJO 서비스 번들에 있는 cxf-dosgi API 클래스를 사용하지 않았다. 그러나, manifest.mf 파일(위 "Imported Packages" 섹션)을
편집하여 특정 패키지를 가져옴으로써 cxf-dosgi 클래스를 사용할 수 있다. 본래 모든 J2SE 클래스를 번들로 사용할 수 있다는
점에 유의한다. 그러나 서비스 번들에서 메일 보내기와 같은 JEE 서비스를 사용하려면 manifest.mf 파일을 편집하여
특정 JEE 패키지를 가져와야 한다. Eclipse에서는 대부분의 JEE 패키지를 가져올 수 있다.
OSGi 번들로 웹 서비스를 개발하고 전개한 후에 간단한 웹 애플리케이션을 사용하여 해당 서비스를 호출하는
과정을 단계별로 살펴보았다. 또한 정리된 OSGi 컨테이너 환경에서 다양한 버전의 서비스를 동시에 전개하고 지원하는 경우에 대한
SOA 전략의 이점을 검토했다.
다운로드 하십시오 | 설명 | 이름 | 크기 | 다운로드 방식 |
|---|
| Service and Client Bundles for this article | cxf-dosgi-dw-article.zip | 3,562KB | HTTP |
|---|
참고자료 교육
제품 및 기술 얻기
토론
필자소개  | 
|  | Nalla는 2000년 이후 Metro Detroit 지역에서 IT 컨설턴트로 일하고 있다. 그는 주요 자동차 제조업체의 엔터프라이즈급
IT 프로젝트를 여러 건 디자인하고 개발했다. Nalla는 싱가폴 국립대학에서 기계 공학 박사 학위를 획득했다. |
기사에 대한 평가
 |
| 이 문서 북마킹 하기
|
|