달력

12

« 2017/12 »

  •  
  •  
  •  
  •  
  •  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  •  
  •  
  •  
  •  
  •  
  •  

이 글은 하얀말님의 2009년 4월 27일의 미투데이 내용입니다.

신고
Posted by 하얀 말

Java Business Integration

JBI(Java Business Integration)란 Java 기반 통합 도구, 특별히 ESB에 적용하는 표준에 기반한 architecture, 더 자세히 말씀드리면 JBI 환경에 끼울 수 있는(pluggable) component들을 조합함으로써 system 통합을 이루게 하는 기반 architecture를 정의하는 규격으로, JCP(Java Community Process)에서 JSR-208로 표준화를 진행한 결과입니다.

JBI-Overview-simple.png

이들 component는 어떤 기능이나 service를 제공하거나(일례로 XML <-> Java POJO 변환 기능을 제공한다거나), 다른 component의 service를 사용/소비하거나(일례로 앞의 변환 component를 써서 Java POJO를 얻어오는 component), 혹은 둘 다(예를 들자면 앞의 변환 component를 써서 XML을 얻은 후 이를 HTTP에 실어 다른 곳에 보내는 component) 할 수도 있겠습니다. 그리고 이러한 JBI 환경에 적용할 수 있는 component들은 JBI 환경이 무엇이든 적용 가능한 것이죠(표준의 힘이랄까요).

 

JBI를 이해하기 위해서는 JBI 명세서에서 다루는 기본 개념에 대한 이해가 필요합니다. 아래 그림은 좀 더 상세한 JBI 명세에 대한 개괄을 보여줍니다.

JBI-Overview.png

BC(Binding Component), SE(Service Engine), DC(Delivery Channel), NMR(Normalized Message Router)라는 것을 보실 수 있는데, 이들 각각을 하나씩 자세히 알아보기로 하겠습니다.

Service Engine & Binding Component

SE는 간단하게 말씀드리면, 어떤 Service의 실 구현체로 자신이 구현한 service를 다른 component에 제공합니다. 예를 들어 어떤 XML을 XSLT를 써서 다른 형태로 변환하는 Service를 구현하여 제공하는 JBI component가 있다면, 이는  SE에 해당한다고 볼 수 있겠습니다.

 

BC는 JBI 환경과 외부와의 연결점으로, 기존 EAI 용어에 익숙하신 분들은 Adapter라고 보시면 되겠습니다. 예를 들어 JBI 환경과 HTTP로 교신하고 싶으면 HTTP 통신을 가능하게 하는 BC가, JBI 환경과 JMS로 교신하고자 하면 JMS에 대한 BC가 필요한 것이죠.

 

Consumer, Provider

 

Consumer, Provider는 JBI 환경에서 동작하는 Component들이 가질 수 있는 두 가지 역할입니다. 어떤 component가 다른 component의 기능(service)를 이용하면 consumer, 어떤 component가 다른 component들이 불러 쓸 수 있는 기능(service)을 가지면 provider입니다. Client / Server model의 client가 consumer, Server가 provider, 어떤 객체가 다른 객체의 method를 불러쓸 경우 불리는 쪽이 provider, 부르는 쪽을 consumer라 볼 수도 있겠습니다.

 

BC는 또 하나의 기능을 하는데(사실은 하게 되었는데), SE의 기능은 JBI 환경 외부에 BC를 통해 노출된다는 것입니다. 예를 들자면 원->달러 변환 SE를 JBI 환경 외부에서 쓰기 위해 HTTP BC를 통해 SE에 접근, 그 결과를 다시 HTTP BC를 통해 받는 것을 들 수 있겠습니다. 동일한 XSLT 변환 SE를 JMS를 통해 쓰고 싶다면 JMS BC가 동원되겠지요?

 

그러다보니 BC는 주로 통신 protocol 등의 기술적인 문제를 다루는 구현이 주를 이루고, SE는 업무 구현이 주를 이루게 됩니다. BC와 SE를 나누는 Architecture를 잡음으로써, 기술 구현과 업무 구현을 분리할 수 있게 된 것이죠.

JBI-Overview-detailed.png

위 그림은 JBI 환경에 올라간 BC와 SE들의 예를 표현한 것입니다. 각 BC를 통해 HTTP, JMS, File을 접근할 수 있고, XSLT나 BPEL, Rule Service를 제공하는 SE들이 존재함을 할 수 있습니다.

Service & Endpoint

SE.png

 

JBI 환경은 JBI component를 담을 수 있는 일종의 container이지만, 사실 SE나 BC도 container입니다. 무슨 말이냐고요?

 

예를 들면 옆 그림에는 네 개의 Service가 하나의 Service Engine에 올라가 있습니다. 옆 그림의 SE가 위에서 언급한 XSLT SE라고 가정해 보면, S1은 미리 정해진 XSLT file을 가지고 XML file을 변환하고, S2는 message header에 있는 어떤 property 값을 읽어, 그 property 값에 땨라 변환해 적용할 XSLT를 적용하는 변환 service, 이런 식이죠.

 

그리고 이러한 Service들은 직접 불러쓸 수 없습니다. 이러한 Service를 불러쓰려면 Endpoint가 필요합니다. 각 service는 최소 한 개 이상의 endpoint를 가져야 합니다. 그래서 JBI component가 제공하는 service를 쓰려면 service의 이름 및 호출할 endpoint의 이름을 알아야 합니다. 이러한 service 및 그 service에 대한 특정 endpoint의 조합을 service endpoint라고 부릅니다.

Normalized Message Router

위 그림들을 보시면 BC와 SE 사이에 Normalized Message Router(NMR)라는 것이 있음을 보실 수 있습니다. 이는 BC와 SE가 직접 교신한지 않는다는 뜻입니다. BC와 SE는 NMR을 통해 교신하는 것이지요. 심지어 이들 BC나 SE도 NMR과 직접 붙지 않고 Delivery Channel(DC)을 경유합니다. message가 여러 JBI component를 올바로 돌아다니게 하는 것이 바로 NMR의 임무입니다.

 

NMR은 여러 방식이나 pattern으로 교환합니다. 아래 목록은 JBI 구현체가 지원하는 messge 교환 pattern입니다(Provider 입장에서 붙여진 이름임을 주의하세요).

 

  • In-Only: Consumer가 request를 보내지만 response를 기대하지는 않는 pattern. error가 나도 consumer에게 그 error 발생을 전달하지 않습니다.
  • Robust-In-Only: In-Only와 비슷하지만, 무언가 잘못되면 consumer에게 fault message가 갑니다.
  • In-Out: 이는 전통적인 request / response message 교환 pattern입니다. error가 생겨도 fault message를 consumer에게 보내지는 않습니다.
  • In-Optional-Out: In-Out과 비슷하나, 꼭 response를 보내야 하는 것은 아니고 provider / consumer 모두 fault message를 보낼 수 있습니다.

 

이들 message 교환 pattern은 JBI에만 나오는 것이 아니라 WSDL 2.0 명세에도 정의하고 있습니다(기실 WSDL 2.0에는 몇 개 pattern이 더 있습니다).

Service 서술, 호출 및 message exchange

consumer가 provider의 service를 쓰려고 하는데, provider에 있는 service에 대한, cosumer가 호출 시 사용할 이름은 무엇인지, message는 어떤 형태를 취해야 하는지, 어떤 error가 발생할 수 있는지에 대한 기술은 어떻게 하면 될까요? JBI 명세에는 이 문제를 어떻게 하라고 할까요? JBI 명세에서는 각 provider는 반드시 WSDL 1.0/2.0 명세를 준수하는 service 서술을 NMR에 등록해야 한다고 되어 있습니다. NMR에 WSDL을 등록시키는 행위가 Service 발행(publication)입니다.

 

어떤 provider 상의 service 호출은 어렵지 않습니다. 단순이 어떤 service나 interface에 대한 MessageExchangeFactory를 만들기만 하면 됩니다. 이 Factory를 써서, 특정 operation과 message exchange를 만들 수 있습니다. message exchange를 만든 다음엔 그냥 message를 NMR에 보내버리면 됩니다. 이후엔 NMR이 원하는 service로 그 message를 전달할 것입니다.

Service Unit, Service Assembly

 

SA.pngBC와 SE는 어떤 자원들을 담을 수 있는 container가 될 수 있다고 말씀드렸습니다. 예를 들면, 검증(validation)을 수행하는 SE에 검증에 쓰일 XML Schema를 배포할 수도 있죠.

 

이런 식으로, 어떤 container에 배포할 수 있는 자원을 SU(Service Unit)라 합니다. 이 SU를 한데 묶으면 다음 그림에서처럼, SA(Service Assembly)가 됩니다. 이 그림에 오는 Service Assembly는 다양한 SU를 담고 있습니다. SA를 JBI container에 배포하면, 각 SU는 특정한 SE나 BC에 배포됩니다.

 

JBI 명세는 SU나 SA의 format을 따로 지정하고 있지는 않으며, 따라서 SE나 BC는 이들을 알아서 다루면 됩니다.

 

요약 정리

component 설명
SE 다른 JBI component에 service를 제공하거나 소비하는 JBI component
BC JBI Container 외부와의 교신을 담당하는 JBI Component
NMR component 사이의 messgae 전달을 담당하는 JBI component
DC SE나 BC 등을 NMR에 붙여줌
SU SE나 BC에 배포될 수 있는 자원
SA SU의 모임


실 구현체

  1. ServiceMix : Apache에서 구현하는 JBI 구현체입니다. ServiceMix는 IONA가 파는 'FUSE ESB'라는 상업용 ESB 제품의 근간입니다.
  2. Open ESB : Sun Microsystems가 운영하는 Open Source project hosting site인 http://www.java.net에서 활동 중인 JBI 구현체. JBI 명세의 공식 참조 구현체(Reference Implementation)입니다.

 cf) Mule : 유명한 Open Source ESB. JBI 구현체는 아니고, JBI 구현체와의 연결을 지원합니다.

 

참조 Site 및 참고 문헌

  1. JSR 208
  2. Open Source ESBs in Action 2장 2절

이 글은 스프링노트 에서 작성되었습니다.

저작자 표시 비영리 변경 금지
신고
TAG EAI, ESB, Java, jbi
Posted by 하얀 말

이 글은 하얀말님의 2009년 1월 10일에서 2009년 1월 11일까지의 미투데이 내용입니다.

신고
Posted by 하얀 말

이 글은 하얀말님의 2009년 1월 2일에서 2009년 1월 3일까지의 미투데이 내용입니다.

신고
Posted by 하얀 말

이 글은 하얀말님의 2008년 12월 23일의 미투데이 내용입니다.

신고
Posted by 하얀 말

이 글은 하얀말님의 2008년 12월 12일의 미투데이 내용입니다.

신고
Posted by 하얀 말
스프링과 아파치 CXF를 이용해 POJO 웹 서비스를 디자인하고 구현하기, Part 2: RESTful 웹 서비스 만들기의 예제(예제도 위 site에서 받을 수 있다) 따라 하다 된통 걸렸다... -.-

HTTP POST method로 request를 날려 Order(주문)를 하나 추가하려고 했는데 다음과 같은 알도살도 못하는 Exception이 발생하였다.

2008. 12. 10 오후 1:55:57 org.apache.cxf.binding.http.interceptor.DispatchInterceptor handleMessage
정보: Invoking POST on /orders
2008. 12. 10 오후 1:55:57 org.apache.cxf.binding.http.interceptor.URIParameterInInterceptor handleMessage
정보: URIParameterInterceptor handle message on path [/orders] with content-type [application/x-www-form-urlencoded]
2008. 12. 10 오후 1:55:57 org.apache.cxf.phase.PhaseInterceptorChain doIntercept
정보: Interceptor has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: Unexpected EOF in prolog
 at [row,col {unknown-source}]: [1,0]
    at org.apache.cxf.binding.http.interceptor.URIParameterInInterceptor.mergeParams(URIParameterInInterceptor.java:120)
    at org.apache.cxf.binding.http.interceptor.URIParameterInInterceptor.handleMessage(URIParameterInInterceptor.java:103)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:220)
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:78)
    at org.apache.cxf.transport.servlet.ServletDestination.invoke(ServletDestination.java:92)
    at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:285)
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:131)
    at org.apache.cxf.transport.servlet.AbstractCXFServlet.invoke(AbstractCXFServlet.java:175)
    at org.apache.cxf.transport.servlet.AbstractCXFServlet.doPost(AbstractCXFServlet.java:153)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:619)
Caused by: com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog
 at [row,col {unknown-source}]: [1,0]
    at com.ctc.wstx.sr.StreamScanner.throwUnexpectedEOF(StreamScanner.java:686)
    at com.ctc.wstx.sr.BasicStreamReader.handleEOF(BasicStreamReader.java:2134)
    at com.ctc.wstx.sr.BasicStreamReader.nextFromProlog(BasicStreamReader.java:2040)
    at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1069)
    at org.apache.cxf.staxutils.StaxUtils.readDocElements(StaxUtils.java:746)
    at org.apache.cxf.staxutils.StaxUtils.read(StaxUtils.java:605)
    at org.apache.cxf.binding.http.interceptor.URIParameterInInterceptor.mergeParams(URIParameterInInterceptor.java:118)
    ... 22 more

이 뭥미? 해결책을 찾을 수 있길 바라며, 일단 오류를 남긴다. 관련 오류가 Apache CXF Issue Tracker에도 있어서 좀 불길하긴 하다만...(https://issues.apache.org/jira/browse/CXF-1863)

  • 사용 JDK: Sun JDK 1.6.0_11 for Windows
  • 사용 library: Apache CXF 2.1.3
  • 사용 Servlet/JSP Engine: Apache Tomcat 6.0.18

----------- 해결 -----------

문제는 client였다. 기본 예제의 client인 Client.java는 아래와 같이 단순히 java.net.URL을 기반으로 작성되었다.

package demo.order.client;

import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.net.URL;
import java.net.HttpURLConnection;

public final class Client {

    public static void main(String[] args) throws Exception {
        String xml = null;
        try {
            // Make a HTTP connection to the server
            URL u = new URL("http://localhost:8080/orderapp_rest/orders");
            HttpURLConnection httpCon = (HttpURLConnection) u.openConnection();
            // Set the request method as POST
            httpCon.setRequestMethod("POST");
            httpCon.setDoOutput(true);

            OutputStream os = httpCon.getOutputStream();
            // XML are encoded in UTF-8 format
            OutputStreamWriter wout = new OutputStreamWriter(os, "UTF-8");
            wout.write("<?xml version=\"1.0\"?>\r\n"); 
            // Add customer name as XML fragment
            wout.write("<order xmlns=\"http://demo.order\"><name>Rajeev</name></order>r\n");
            wout.flush();

            // Make implicit connection to the server
            httpCon.getContentLength();
            httpCon.disconnect();
  
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

혹시나 하는 마음에 화끈하게 Apache HttpClient library를 써서 아래와 같이 다시 만들어 보았다.

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;

public class Client {
  public static void main(String... args) throws Exception {
    String strURL = "http://localhost:8080/orderapp_rest/orders";
    String reqData = "<?xml version=\"1.0\"?>\r\n<order xmlns=\"http://demo.order\"><name>Rajeev</name></order>\r\n";

    PostMethod post = new PostMethod(strURL);
    post.setRequestEntity(new StringRequestEntity(reqData));
    HttpClient httpclient = new HttpClient();

    try {
      int result = httpclient.executeMethod(post);

      if (200 == result)
        System.out.println(post.getResponseBodyAsString());
    } finally {
      post.releaseConnection();
    }
  }
}

이랬더니 정상적으로 동작하였다. 하기사 java.net.URL이 잘 동작했으면 Apache HttpClient가 있을 필요가 있겠어?

설마허니, 예제 code 돌려보지도 않은 것은 아니겠지? 혹시 Web site에서 배포하는 예제에서 동일한 문제를 겪으시는 분들은 위 Client.java로 다시 해 보시길...

그런데 둘 차이는 뭘까? 한 번 파보고 싶은데... 싶은데싶은데싶은데싶은데싶은데... 젠장.
저작자 표시 비영리 변경 금지
신고
Posted by 하얀 말

이 글은 하얀말님의 2008년 12월 9일의 미투데이 내용입니다.

신고
Posted by 하얀 말

이 글은 하얀말님의 2008년 11월 19일의 미투데이 내용입니다.

신고
Posted by 하얀 말

이 글은 하얀말님의 2008년 10월 27일에서 2008년 10월 28일까지의 미투데이 내용입니다.

신고
Posted by 하얀 말


티스토리 툴바