기술자료

DBMS, DB 구축 절차, 빅데이터 기술 칼럼, 사례연구 및 세미나 자료를 소개합니다.

SOA 복합 비즈니스 서비스 구현하기, Part 2: WebSphere Application Developer-IE v5.1에서 WebSphere Integration Developer v6.0.1로 비즈니스 통합 프로젝트 마이

기술자료
DBMS별 분류
Etc
작성자
admin
작성일
2021-02-23 15:07
조회
1457

SOA 복합 비즈니스 서비스 구현하기, Part 2:
WebSphere Application Developer-IE v5.1에서
WebSphere Integration Developer v6.0.1로 비즈니스 통합 프로젝트 마이그레이션 하기

본 시리즈에서는 복합 애플리케이션(composite application) 개발에 관련한 문제들을 다룹니다. 복합 애플리케이션은 기존 SOA 서비스들을 통합하고 다양한 방식으로 구성될 수 있는 새로운 서비스들을 구현합니다. 원래, 우리는 WebSphere Application Developer IE v5.1과, 런타임으로서 WebSphere Business Integration SF를 사용하여 데모용 복합 애플리케이션을 개발했습니다. (본 시리즈 Part 1 참조) WebSphere Process Server v6과 이와 관련한 개발 툴인 WebSphere Integration Developer v6의 릴리스와 함께, Service Component Architecture (SCA)에 기반한 새로운 프로그래밍 모델이 탄생했습니다. 이에 따라, 레거시 프로그래밍 모델을 새로운 모델로 마이그레이션 해야 할 필요성이 대두되었습니다. 이 글에서, 마이그레이션 기간 동안 배웠던 중요한 교훈들을 여러분과 함께 나눕니다.

머리말

이 글에서는 WebSphere Application Developer-IE v5.1에서 WebSphere Integration Developer v6으로 프로토타입 복합 애플리케이션을 마이그레이션 하는 것과 관련한 문제와 솔루션을 설명한다. 우리가 여기에서 설명할 주요 문제는 WSDL 바인딩, WSDL 인터페이스, XSD 정의, Business Process Execution Language (BPEL) 코딩이다. WebSphere Integration Developer v6에 강력한 마이그레이션 마법사가 있지만, 간단한 프로젝트는 자동으로 마이그레이션 될 수 있다는 것을 알았다. 하지만, 조금 복잡한 BPEL 애플리케이션의 경우 마이그레이션 프로세스에 대한 깊은 지식이 있어야 한다. 마이그레이션과 관련한 자세한 내용은 WebSphere Integration Developer Help 또는 WebSphere Integration Developer /WPS Information Center를 참조하라.

바인딩과 관련한 마이그레이션 문제

본 시리즈 첫 번째 글 에서는 은행 고객에 의해 실행되는 몇 가지 유스 케이스를 설명했다. "apply for loan" 유스 케이스는 BPEL Business Process를 실행했다. 비즈니스 프로세스는 서비스를 호출하고 대출을 처리하는 일련의 단계를 거친다. 호출되는 일부 서비스들은 자바™ 또는 EJB 바인딩을 호출했다.

자바 바인딩과 관련한 문제

WebSphere Application Developer-IE에 의해 생성된 WSDL에서 사용되는 원래의 자바 바인딩 유형은 WebSphere Integration Developer v6에서는 지원되지 않는다. 서비스/포트 정의는 자바 유형을 사용한다. 따라서 ClassName은 엔드포인트 주소 대신 WSDL로 생성된다. (Listing 1)
Listing 1. WSDL과 자바 바인딩
<service name="LoanTrackingServiceProxyPortTypeService">
<port binding="tns:LoanTrackingServiceProxyPortTypeJavaBinding"
name="LoanTrackingServiceProxyPortTypeJavaPort">
<java:address className="loantrackingservice.LoanTrackingServiceProxy"/>
</port>
</service>
이러한 종류의 WSDL이 SCA 모듈로 직접 반입된다면, WebSphere Integration Developer에 의해 기록된 예외나 에러가 없다 하더라도, 반입은 성공적으로 바인딩 할 수 없다. (그림 1) 사실, WebSphere Integration Developer V6는 SOAP 바인딩을 통해 웹 서비스 반입만 지원한다. 따라서, 이러한 반입의 엔드포인트는 비어있게 되고, 모듈이 WPS에 전개되고 호출을 시도한 후에 런타임 예외가 생기게 된다.그림 1. 자바 바인딩을 통한 WSDL 반입

Enterprise JavaBean (EJB) 바인딩과 관련한 문제

WebSphere Application Developer-IE에서 생성된 WSDL에서 사용되는 원래의 EJB 바인딩 유형은 WebSphere Integration Developer v6에서는 지원되지 않는다. 서비스/포트 정의(앞서 언급한 자바 유형과 비슷함)는 EJB 유형을 사용한다. 따라서 EJB Home ClassName과 JNDI Name이 엔드포인트 주소 대신 제공된다. (Listing 2)Listing 2. WSDL과 EJB 바인딩
<service name="LoanTrackingService">
<port binding="binding1:LoanTrackingServiceEJBBinding"
name="LoanTrackingServiceEJBPort">
<ejb:address className="loantrackingservice.LoanTrackingServiceHome"
jndiName="ejb/loantrackingservice/LoanTrackingServiceHome"/>
</port>
</service>
이것은 앞서 언급했던 것과 같은 이유로 실행하는 동안 예외가 발생될 것이다. (그림 2)그림 2. EJB 바인딩을 통한 WSDL 반입

솔루션


  1. EJB나 자바 바인딩을 가진 이전의 WSDL을 버린다생성 하여 SCA 모듈로 직접 반입한다.
  2. BPEL 프로세스를 수정하여 새롭게 반입된 웹 서비스 인터페이스를 참조한다.

WSDL 인터페이스와 관련한 마이그레이션 문제

본 시리즈 Part 1에서 설명했던 유스 케이스들 중 하나는 대출 발생 시나리오이다. 고객이 대출을 신청한 후에, "Platform Sales" 역할을 담당하는 은행 직원은 대출 요청을 검토하고 이를 승인 또는 거절한다. 이 유스 케이스의 일부는 신용 평가 서비스를 실행한다. 이 서비스를 호출하는 과정에서, document/literal 스타일을 사용하고, RPC 스타일과 soapenc:Array 를 피하는 것이 중요하다. 이 스타일을 사용하는 서비스와 상호 작동 해야하는 상황에 처해있다면 다음 섹션에서는 이러한 문제들을 설명하고, 중복 네임스페이스(namespace)를 피하는 것의 중요성에 대해서도 설명하겠다.

soapenc:Array를 사용하지 말 것

soapenc:Array 유형을 참조하는 WSDL 인터페이스를 생성 또는 반입하지 않도록 해야 한다. 이 인터페이스는 SCA 프로그래밍 모델에서는 기본적으로 지원이 안된다. RPC 스타일을 갖춘 SOAP으로 인코딩 된 어레이 유형은 WPS 6.0의 구체적 유형의 무한 시퀀스로 취급된다. 따라서, 이것을 사용하는 것을 권장하고 싶지 않다. 표준은 document/literal 스타일을 사용하는 것이다. WebSphere Application Developer-IE에 의해 생성된 원래의 WSDL 파일의 soapenc:Array 를 이용한 유형 정의는 Listing 3에 나타나 있다.Listing 3. soapenc:Array를 이용한 XML 유형 정의
<complexType name="ArrayOfLoanRequestBean">
<complexContent>
<restriction base="soapenc:Array">
<all/>
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd1:LoanRequestBean[]"/>
</restriction>
</complexContent>
</complexType>

솔루션 1


  1. WSDL에서 Array 유형 정의를 수정한다.
  2. 웹 서비스를 재생성 한다.
  3. WebSphere Application Developer-IE Service Project 마이그레이션 마법사를 실행하여 WebSphere Integration Developer에 새로운 구성물(BPEL 프로세스의 서비스 프로젝트와 자바 조각들)을 생성한다.

솔루션 2

어떤 경우에는, SCA 애플리케이션이 soapenc:Arraytype 을 사용하는 외부 서비스를 호출해야 한다. (예를 들어, 인터페이스 정의에 soapenc:Array 유형을 사용하는 외부 신용 평가 서비스를 호출할 경우). 이 경우에는, 서비스 구현과 인터페이스 정의를 수정하는 것이 불가능하므로, 또 다른 솔루션이 이러한 문제를 해결하기 위해 사용되어야 한다.
  1. WSDL을 SCA 모듈로 반입한 후에 후속 마이그레이션 작업을 실행할 수 있는 플레이스홀더 엘리먼트를 추가함으로써 반입된 외부 WSDL을 직접 수정한다.
  2. Service Data Objects (SDO) API를 사용하여 SCA 모듈의 자바에서 soapenc:Array 데이터를 처리한다.
Listing 4는 데이터 객체의 루트 유형이 soapenc:Array 인 상황 예제이다. sampleElements DataObject가 두 번째 스키마를 사용하여 어떻게 생성되는지에 주목하라. DataObject의 유형이 첫 번째로 획득되고, sampleStructElement 의 프로퍼티가 획득된다. (Listing 5) 이것은 플레이스홀더 프로퍼티이고, DataObject를 시퀀스에 추가하기 위해 유효 프로퍼티를 얻기 위해서만 사용된다.Listing 4. WSDL 코드 샘플
<s:schema elementFormDefault="qualified" targetNamespace="http://soapinterop.org/xsd">
<s:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<s:import namespace="http://schemas.xmlsoap.org/wsdl/" />
<s:complexType name="SOAPStruct">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" form="unqualified" name="varInt"
type="s:int" /> <s:element minOccurs="1" maxOccurs="1" form="unqualified"
name="varString" type="s:string" />
<s:element minOccurs="1" maxOccurs="1" form="unqualified"
name="varFloat" type="s:float" />
</s:sequence>
</s:complexType>
<s:complexType name="ArrayOfSOAPStruct">
<s:complexContent mixed="false">
<s:restriction base="soapenc:Array">
<s:attribute wsdl:arrayType="s0:SOAPStruct[]" ref="soapenc:arrayType" />
</s:restriction>
</s:complexContent>
</s:complexType>
</s:schema>
<wsdl:message name="echoStructArraySoapIn">
<wsdl:part name="inputStructArray" type="s0:ArrayOfSOAPStruct" />
</wsdl:message>
<wsdl:message name="echoStructArraySoapOut">
<wsdl:part name="return" type="s0:ArrayOfSOAPStruct" />
</wsdl:message>
<wsdl:operation name="echoStructArray">
<wsdl:input message="tns:echoStructArraySoapIn" />
<wsdl:output message="tns:echoStructArraySoapOut" />
</wsdl:operation>SampleElements.xsd
<schema targetNamespace="http://sample/elements" xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://sample/elements">
<element name="sampleStringElement" type="string"/>
<element name="sampleStructElement" type="any"/>
</schema>
Listing 5. 웹 서비스용 클라이언트 코드 샘플
// Create the input DataObject and get the SDO sequence for the any element 
DataFactory dataFactory=DataFactory.INSTANCE;
DataObject arrayOfStruct = dataFactory.create(
"http://soapinterop.org/xsd","ArrayOfSOAPStruct");
Sequence sequence=arrayOfStruct.getSequence("any");
// Get the SDO property for sample element we want to use here to populate the sequence
// We have defined this element in an XSD file, see SampleElements.xsd
DataObject sampleElements=dataFactory.create("http://sample/elements", "DocumentRoot");
Property property = sampleElements.getType().getProperty("sampleStructElement");
//Add the elements to the sequence
DataObject item=dataFactory.create("http://soapinterop.org/xsd", "SOAPStruct");
item.setInt("varInt", 1);
item.setString("varString", "Hello");
item.setFloat("varFloat", 1.0f);
sequence.add(property, item);
item=dataFactory.create("http://soapinterop.org/xsd", "SOAPStruct");
item.setInt("varInt", 2);
item.setString("varString", "World");
item.setFloat("varFloat", 2.0f);
sequence.add(property, item);
//Invoke the echoStructArray operation
System.out.println("[client] invoking echoStructArray operation");
DataObject echoArrayOfStruct =
(DataObject)interopTest.invoke("echoStructArray", arrayOfStruct);
// Display the results
if (echoArrayOfStruct!=null)
{
sequence=echoArrayOfStruct.getSequence("any");
for (int i=0, n=sequence.size(); i<n; i++)
{
item=(DataObject)sequence.getValue(i);
// Create the input DataObject and get the SDO sequence for the any element
DataFactory dataFactory=DataFactory.INSTANCE;
DataObject arrayOfStruct =
dataFactory.create("http://soapinterop.org/xsd","ArrayOfSOAPStruct");
Sequence sequence=arrayOfStruct.getSequence("any");
// Get the SDO property for sample element we want to use here to populate the sequence
// We have defined this element in an XSD file, see SampleElements.xsd
DataObject sampleElements=dataFactory.create("http://sample/elements",
"DocumentRoot");
Property property = sampleElements.getType().getProperty("sampleStructElement");
//Add the elements to the sequence
DataObject item=dataFactory.create("http://soapinterop.org/xsd", "SOAPStruct");
item.setInt("varInt", 1);
item.setString("varString", "Hello");
item.setFloat("varFloat", 1.0f);
System.out.println("[client] item varInt = "+ item.getInt("varInt")+"
varString="+item.getString("varString")+" varFloat="+item.getFloat("varFloat"));
}

중복 네임스페이스를 사용하지 말 것

WebSphere Integration Developer에서, 같은 네임스페이스를 가진 두 개의 다른 WSDL 파일들을 반입할 수 없다. 복합 유형들(WSDL 또는 XSD)이 동일한 네임스페이스로 선언되면, 마이그레이션 마법사 프로세스를 통해 올바르게 마이그레이션 될 수 없다. IBM WebSphere Process Server v6에서는, 같은 이름과 대상 네임스페이스를 가진 두 개의 다른 WSDL/XSD 정의는 허용되지 않는다.Listing 6과 7은 같은 네임스페이스를 가진 두 개의 WSDL 정의이다.Listing 6. LoanRequest1.WSDL
<wsdl:definitions xmlns:tns="http://loanrequest/LoanRequest" ...... 
targetNamespace="http://loanrequest/LoanRequest">
<message name="processLoanRequest">
<part name="loanAmount" type="xsd:decimal"></part>
<part name="customerId" type="xsd:string"></part>
<part name="bankId" type="xsd:string"></part>
<part name="ssn" type="xsd:string"></part>
<part name="processConfig" type="tns:ProcessConfig"></part>
<part name="productId" type="tns:ProductId"></part>
</message>
Listing 7. LoanRequest2.WSDL
<wsdl:definitions xmlns:tns="http://loanrequest/LoanRequest" ...... 
targetNamespace="http://loanrequest/LoanRequest">
<message name="processLoanRequest">
<part name="loanAmount" type="xsd:decimal"/>
<part name="customerId" type="xsd:string"/>
<part name="bankId" type="xsd:string"/>
<part name="ssn" type="xsd:string"/>
<part name="configParams" type="tns:ConfigParams"/>
</message>

솔루션


  1. 네임스페이스를 수정하여 각자 고유한 것으로 바꾼다.
  2. 네임스페이스 수정으로 인한 부작용이 없는지 확인한다. 워크스페이스를 비우고, 모든 프로젝트를 재구현 한다. 어떤 에러도 WebSphere Integration Developer에 없다면, 업데이트 된 SCA 애플리케이션을 WebSphere Process Server에 전개하고 테스트 한다.
EJB에서 생성된 WSDL과 XSD의 경우, 대상 네임스페이스가 고유한 것인지를 확인하여(자바 클래스 이름과 패키지 이름은 대상 네임스페이스를 만드는데 사용된다.) WebSphere Process Server V6으로 마이그레이션 할 때 충돌이 생기지 않도록 한다.

XSD와 관련한 마이그레이션 문제

Loan 발생과 관련하여 이전에 언급한 같은 유스 케이스에서, 우리는 anyType 유형을 생성하는 Object 의 리턴 유형을 사용한다.

xsd:anyType을 사용하지 말 것

WSDL 인터페이스를 세밀하게 정의한다. xsd:anyType 을 참조하는 XSD complexTypes를 피한다. 이것은 WebSphere Integration Developer v6에서는 지원되지 않는다. 이 유형에 대한 값을 설정하려고 할 때 에러가 생길 것이다.아래 예제에서, SCA 모듈로 반입된 WSDL은 anyType 이 지정된 complexType을 갖고 있으며, 이 연산의 아웃풋으로 anyType 의 유형이 된다. (그림 3) 개발 시 WebSphere Integration Developer에 어떤 예외나 오류도 탐지되지 않더라도, 자바로 비즈니스 객체 데이터 아이템의 값을 얻거나 설정하려고 할 때 런타임 동안 "class cast exception"이 던져질 것이다.그림 3. xsd:anyType이 설정된 XML Type Definition
예를 들어, 자바에서 getVariableReturn 을 설정하기 위해 Boolean 값을 사용하려고 하면 WebSphere Process Server 런타임에서 예외가 던져진다. (그림 4)그림 4. anyType에서 생신 예외
//There will be a class cast error caused by the value item which type is anyType ; setDecisionVar.set("getVariableReturn",(Object)(new Boolean(true));

솔루션


  1. 상응하는 세션 빈 인터페이스를 수정하여 인풋/아웃풋 매개변수 유형으로 Object 를 사용하지 않도록 한다. (매개변수 유형을 Object 로 지정함으로써, 생성된 WSDL은 상응하는 XML 엘리먼트 유형으로서 xsd:anyType 을 지정한다.)
  2. 나중에 SCA 모듈로 반입될 수 있는 웹 서비스를 재생성 한다.
  3. 새로운 WSDL 마다 마이그레이션 된 BPEL 프로세스 내에 모든 관련 호출 포인트를 수정한다.

BPEL과 관련한 마이그레이션 문제

본 시리즈 Part 1의 대출 유스 케이스는 대출을 승인 또는 거부하기 위해 신용 평가 서비스를 사용한다. 이 서비스의 엔드포인트를 동적으로 설정해야 할 필요가 있다. 이 엔드포인트는 Business Process Engine (BPE) API로 원래 설정되었다. 하지만 WebSphere Integration Developer /WebSphere Process Server는 더 나은 메커니즘을 갖고 있다.

엔드포인트를 동적으로 설정하기 (첫 번째 문제)

WebSphere Application Developer-IE는 BPEL 프로세스에 삽입된 자바를 사용하여 엔드포인트를 동적으로 설정할 수 있다. 하지만, 이 코드는 더 이상 작동하지 않는다. BPE API가 WebSphere Process Server에서 수정되었기 때문이다. 따라서, 이 코드는 새로운 API에 맞게 업데이트 되어야 한다. 엔드포인트를 동적으로 설정하기 위해 사용되는 원래 코드는 Listing 8에 나와있다. Listing 9에서, 이 코드는 새로운 WebSphere Process Server BPE API를 사용하도록 마이그레이션 되었다.Listing 8. WebSphere Application Developer-IE의 동적인 엔드포인트 설정 코드
String ep = getApproveCheckRequest().getApprovalExtensionEP();
com.ibm.websphere.srm.bpel.wsaddressing.AttributedURI address = new AttributedURI();
com.ibm.ws.webservices.engine.types.URI addressValue = new URI(ep);
com.ibm.websphere.srm.bpel.wsaddressing.EndpointReferenceType
e = new EndpointReferenceType();address.setValue(addressValue);e.setAddress(address);
this.setPartnerLinkLoanApprovalExtension(e);
Listing 9. WebSphere Integration Developer의 동적인 엔드포인트 설정 코드
//Get the new address of approvalExtension parnter 
String ep = approveCheckRequest.getString("approvalExtensionEP");
System.out.println("Setting approval extension endpoint to: " + ep);if (ep != null && ep.length() > 0) {
ServiceManager sm = ServiceManager.INSTANCE;
Service s = (Service)sm.locateService("LoanApprovalExtension");
EndpointReference endPoint = s.getEndpointReference();//Update the endpoint address for the partner "LoanApprovalExtension"
endPoint.setAddress(ep);
}
레퍼런스 파트너용 엔드포인트를 설정하는 코드가 업데이트 되었지만, 파트너가 하나의 컴포넌트로 연결되었다면(런타임 동안 동적으로 리셋되기 전에 바인딩이 여기에 할당되었다면), 엔드포인트 변경은 효과가 없다. 런타임에서, 호출은 기본 엔드포인트로 가게 될 것이다.

엔드포인트를 동적으로 설정하기 (두 번째 문제)

SCA 모듈의 레퍼런스가 비어있다면(예를 들어, 어떤 SCA 컴포넌트와도 연결되지 않았다면), 위에서 설명했던 동적인 엔드포인트 설정 코드는 바인딩 정보를 비어있는 레퍼런스에 붙이는데 사용된다. 하지만, 다른 엔드포인트 바인딩을 사용하여 이것의 엔드포인트를 다시 업데이트 하려고 하면, 레퍼런스는 더 이상 작동하지 않고, "document root error" 예외가 던져질 것이다. 이것이 WebSphere Process Server v6의 한계이다.

솔루션

SCA 프로그래밍 모델은 WebSphere Integration Developer /WebSphere Process Server "selector" 메커니즘을 사용하여 런타임 시 엔드포인트를 동적으로 바꾼다. selector는 클라이언트 애플리케이션에서 여러 SCA 서비스 구현들 중 하나로 연산을 라우팅 하는데 사용될 수 있는 WebSphere Integration Developer /WebSphere Process Server에 의해 지원을 받는 SCA 컴포넌트이다. 따라서, 기능적 관점에서 볼 때, BPE API를 통해 엔드포인트를 동적으로 설정하는 것과 같은 일을 할 수 있는 것이다. 그림 5는 selector를 이용한 어셈블리 다이어그램이다.그림 5. selector 사용하기

결론

이 글에서는 WebSphere Application Developer-IE 비즈니스 통합 프로젝트를 WebSphere Integration Developer 비즈니스 통합 모듈로 마이그레이션 하는 동안 생기는 몇 가지 문제들을 짚어보았고, 이와 관련한 솔루션도 살펴보았다. 자바와 EJB 바인딩을 SOAP 바인딩으로 대체하는 것의 중요성도 설명했다. soapenc:Array 를 사용하지 않아야 하는 이유도 설명했다. soapenc:Array 를 사용하는 서비스와 상호 작동하는 방법도 설명했다. WSDL 정의에서 중복 네임스페이스를 피하는 것의 중요성과, XSD:anyType 정의를 피해야 하는 이유도 살펴보았다. 마지막으로, BPE API를 사용하는 대신 엔드포인트를 동적으로 변경하는 selector를 사용하는 부분에 대해서도 살펴보았다.

감사의 말

이 글에 사용된 실제 애플리케이션은 IBM Strategic Technology Architecture and Incubation (STAI) 팀원들이 WebSphere Application Developer-IE를 사용하여 디자인 및 개발한 것이다. 마이그레이션 작업은 베이징의 IBM China Software Development Lab 소속 Min Li, Zhi Gan, Yinchun Guo, Duowei Sun이 수행하였다.

필자소개

Javier G. Garcia는 20년 개발 경력을 지닌 소프트웨어 자문 엔지니어이다. 현재 SWG Strategy and Technology 부서에서 SOA와 합성 애플리케이션을 연구하고 있다.Qiang Wang은 China Technology Institute, China Software Development Laboratory의 소프트웨어 엔지니어이다. IBM 인큐베이터 프로젝트와 SOA 관련 토픽을 중점적으로 다루고 있다. J2EE, SOA, MDA/MDD, AOP, RUP 등에 관심을 갖고 있다. 현재 WBM, WebSphere Integration Developer, WPS와 관련된 개발 작업을 수행하고 있다.출처 : 한국 IBM제공 : DB포탈사이트 DBguide.net