블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 
 

Multiple row에 대한 리턴값 처리시에, FML 값의 순서에 대한 테스트

Tuxedo Transport에서
Transformation Style 설정에 따른 결과

입력 데이타
<FML>
  <ACCOUNT_ID>10</ACCOUNT_ID>
  <ACC_TYPE>A</ACC_TYPE>
  <ADDRESS>10</ADDRESS>
  <AMOUNT>10</AMOUNT>
  <ACCOUNT_ID>20</ACCOUNT_ID>
  <ACC_TYPE>B</ACC_TYPE>
  <ADDRESS>20</ADDRESS>
  <AMOUNT>20</AMOUNT>
</FML>

None일 경우

Ordered 를 적용한 경우

<FML>
<ACC_TYPE>B</ACC_TYPE>
<ACC_TYPE>C</ACC_TYPE>
<AMOUNT>10.0</AMOUNT>
<AMOUNT>20.0</AMOUNT>
<ADDRESS>10</ADDRESS>
<ADDRESS>20</ADDRESS>
<ACCOUNT_ID>10</ACCOUNT_ID>
<ACCOUNT_ID>20</ACCOUNT_ID>
</FML>

Grouped and Ordered


<FML>
<ACCOUNT_ID>10</ACCOUNT_ID>
<ACC_TYPE>A</ACC_TYPE>
<AMOUNT>10.0</AMOUNT>
<ADDRESS>10</ADDRESS>
<ACCOUNT_ID>20</ACCOUNT_ID>
<ACC_TYPE>B</ACC_TYPE>
<AMOUNT>20.0</AMOUNT>
<ADDRESS>20</ADDRESS>
</FML>




(FML인 경우)
1. Tuxedo에서 도메인 Config 설정을 한다.
2. FML 파일을 java weblogic.wtc.jatmi.mkfldclass fmldata 로 해서 JAVA 클래스를 생성한다.
3. WLS에서 WTC 설정을 하고 Resource 탭에서 위에서 설정한 JAVA 클래스를 적는다.
4. 2에서 작성한 클래스를 JAR로 묶어서 클래스 패스에 추가한다.
== 여기까지가 WLS의 WTC설정
5. SB에서 AnyXML로 비지니스 서비스를 만들고
6. JAR를 SB 프로젝트에 추가한후, CLASS에서 해당 JAR를 고른다.
7. 비지니스 서비스를 완성한후 테스트시에

FML이 다음과 같을때
#name           number          type    flags   comments
ACCOUNT_ID      10              long    -       -
ACC_TYPE        11              char    -       -
ADDRESS         12              string  -       -
AMOUNT          13              float   -       -

Input XML은 다음과 같아진다.
<FML>
  <ACCOUNT_ID>10</ACCOUNT_ID>
  <ACC_TYPE>10</ACC_TYPE>
  <ADDRESS>10</ADDRESS>
  <AMOUNT>10</AMOUNT>
</FML>


루트 엘리먼트가 <FML>이 된다.
만약 FML32를 사용할 경우에는 <FML32>로 명시하면 된다.

ALSB에서
SOAP 을 REST POX (Plain Old Xml)로 변환하는 XmlBeans 구현 예제. ALSB에서 Java Callout으로 사용이 가능함
==
import javax.xml.namespace.QName;

import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlCursor.TokenType;

public class RESTTransformer {
    public static XmlObject toREST(XmlObject soap){
       
        XmlCursor cur = soap.newCursor();
        cur.toFirstChild();
        cur.toChild(new QName("http://schemas.xmlsoap.org/soap/envelope/","Body"));

        traverse(cur);
        cur.dispose();
        return null;
    }
   
    public static void traverse(XmlCursor cur){
        if(cur.toFirstChild()){
            String name;
            do{
               
                name = cur.getName().getLocalPart();
                System.out.println("<"+name+">");
       
                traverse(cur);
                System.out.println("</"+name+">");

            }while(cur.toNextSibling());

            cur.toParent();
        }else{
            // is Leaf
            System.out.println(cur.getTextValue());
        }
    }
   
==
Mediation에서 Route To 추가하고
거기에 Dynamic Routing 추가한후에,
Expression에 다음과 같이 써줌
<ctx:route>
<ctx:service isProxy='true'>GeneralProxySampleProject/samplewebservice/localproxy/PersonService.local</ctx:service>
</ctx:route>
==
Route하고자 하는 destination이 Proxy일 경우 isProxy를 true로 해줄것.
service 경로는 "프로젝트명/폴더.../폴더/Proxy명"
예를 들어

default 프로젝트의 localproxy 폴더의 common.local.proxy의 경우
default/localproxy/common.local (.proxy를 뺀다.) 가 된다.

문제는 JMS Proxy에서는 Transaction start를 지원하지만
가장 많이 사용하는 WebService Proxy는 Global Transaction을 start하지 않기 때문에
Transactional EJB를 Composition하는 경우 분산 트렌젝션에 대한 구현 문제가 생긴다.

방법은 두가지 인데.
1) 단순하게 EJB를 하나 만들어서 ALSB(OSB)에 배포하여 Code로 Tx를 composition한후, 이 EJB를 Biz Service로 등록하고 WebService로 Expose하는 방법
2) 좀더 OSB 다운 방법은

WebService Proxy에서 JMS Q로 callout한후 JMS Proxy에서 읽어서 Tx 처리하고나서 Recv Q에 return하면 WebService Proxy에서 blocked wait하다가 response 받아서 처리하는 방식...
성능이 다소 떨어질테고, 클러스터에 고려해야할점도 있을테고, JMS Q를 관리해야 하는점, Tx Fail시 Hop이 늘어나는 점등이 풀어야할 문제이기는 한데, reference 아키텍쳐만 단단하게 만들어놓는 다면 가능할듯...

이럴때 그냥 WLI로 Service Enablement 시키고 Biz Service로 등록하면 얼마나 좋아.. ALINT가 그리워~~

1. OSB 설치시 Default로 하면 Eclipse를 인스톨 하기를 요청하기 때문에 Custom으로 선택하고 Workshop에서 Eclipse 모듈을 제외하고 설치할것.
2. Managed Server을 추가로 추가하기가 복잡하기 때문에, 아예 설치시부터 Managed Server를 추가하는 것이 좋다.
3. DBMS를 사용하기 때문에, 초반에 DB 설정을 해놓고 인스톨하는 것이 좋다.

Non Blocking Sync Call

엔터프라이즈 솔루션/BEA WebLogic | 2008.10.29 19:48 | Posted by 조대협
WebLogic에서 간만에 재미있는 기능을 찾아서 포스팅.
ESB나 EAI 제품과 같은 아키텍쳐에서 Sync Call의 구조를 보면 다음과 같다.
Request가 들어오면 특정 Thread가 그 request를 받아서 Backend의 Component에 보내고, 응답을 기다린다.
응답이 오면 Client에게 그 응답을 전달하는 구조이다.
그런데 이 경우 Client에서 요청을 받은 후 그 요청을 Component에 전달하고 나면 Component로 부터 응답이 오기까지는 Request Thread는 아무것도 하지 않고 단지 기다리기만 한다. 즉 하는 일없이 Thread만 점유하고 있는 것이다.
만약에 Component에서의 처리시간이 오래 걸리게 되면 Request Thread가 held 되는 시간이 늘어나게 되고 이런 요청이 많을 수록, 시스템 내의 Idle Thread는 기하급수적으로 줄어들게 되고, 이는 Thread 부족으로 인한 Slow down이나 hang현상을 유발하게 된다.

이를 해결하기 위한 아키텍쳐가 Non-blocking Sync Mode인데
개념은 다음과 같다. 
Client에서 요청이 들어오면 그 요청을 Request Thread가 처리하여 Backend의 Component로 전달을 하고 Request Thread는 Idle 상태로 전환된다.
그리고 나서 Component로 부터 응답이 들어오면 그 응답을 Idle Thread중에 한 Thread가 응답을 받아서 Client에게 전달을 한다. (Response Thread)
이런 구조에서는 Component로 일단 요청이 전달된후 Component에서 응답이 올때까지는 Thread가 release되어 있기 때문에 Working Thread의 수를 줄일 수 있다.
Server <--> Component 단을 Async/Callback처럼 구현해놓은것인데 EAI나 ESB와 같은 중계 시스템에서는 매우 유용한 아키텍쳐가 될거 같다.

이를 구현한 구현체가 WebLogic에 Future Response model for HTTP 라는 모델이다. (아래 참조)
이 모델은 Backend에서 수행 시간이 오래 걸릴 경우나 비지니스 로직이 JMS등을 이용하는 것과 같은 Async 구조에서는 매우 유용하지만 일반적인 WebApplication에서는 오히려 유용하지 않다. (하나의 Request를 수행하는데 Thread를 두개나 사용하게 되고 어짜피 Response를 만들기 위해서는 비지니스 로직을 처리해야할 쓰레드가 필요하기 때문에..)

이러한 구조는 ALSB 3.0 내부에서 사용하고 있다니 장애 예방이나, 리소스 효율 면에서 상당히 뛰어날듯하다.
간만에 재미있는 아키텍쳐를 봤더니.. 뿌듯하네..

==

A Future Response Model for HTTP Servlets

In general, WebLogic Server processes incoming HTTP requests and the response is returned immediately to the client. Such connections are handled synchronously by the same thread. However, some HTTP requests may require longer processing time. Database connection, for example, may create longer response times. Handling these requests synchronously causes the thread to be held, waiting until the request is processed and the response sent.

To avoid this hung-thread scenario, WebLogic Server provides two classes that handle HTTP requests asynchronously by de-coupling the response from the thread that handles the incoming request. The following sections describe these classes.

Abstract Asynchronous Servlet

The Abstract Asynchronous Servlet enables you to handle incoming requests and servlet responses with different threads. This class explicitly provides a better general framework for handling the response than the Future Response Servlet, including thread handling.

You implement the Abstract Asynchronous Servlet by extending theweblogic.servlet.http.AbstractAsyncServlet.java class. This class provides the following abstract methods that you must override in your extended class.

doRequest

This method processes the servlet request. The following code example demonstrates how to override this method.

Listing 9-3 Overriding doRequest in AbstractAsynchServlet.java
public boolean doRequest(RequestResponseKey rrk) 
      throws ServletException, IOException {
      HttpServletRequest req = rrk.getRequest();
      HttpServletResponse res = rrk.getResponse();

      if (req.getParameter("immediate") != null) {
            res.setContentType("text/html");
            PrintWriter out = res.getWriter();
            out.println("Hello World Immediately!");
            return false ;
      }
      else {
            TimerManagerFactory.getTimerManagerFactory()
            .getDefaultTimerManager().schedule
            (new TimerListener() {
                  public void timerExpired(Timer timer)
                        {try {
                              AbstractAsyncServlet.notify(rrk, null);
                        }
                        catch (Exception e) {
                              e.printStackTrace();
                        }
                  }
            }, 2000);
      return true;
      }
}

doResponse

This method processes the servlet response.

Note: The servlet instance that processed the doRequest() method used to handle the original incoming request method will not necessarily be the one to process the doResponse() method.

If an exception occurs during processing, the container returns an error to the client. The following code example demonstrates how to override this method.

Listing 9-4 Overriding doResponse() in AbstractAsyncServlet.java
public void doResponse (RequestResponseKey rrk, Object context)
   throws ServletException, IOException
      {
      HttpServletRequest req = rrk.getRequest();
      HttpServletResponse res = rrk.getResponse();

      res.setContentType("text/html");
      PrintWriter out = res.getWriter();
      out.println("Hello World!");
}

doTimeOut

This method sends a servlet response error when the notify() method is not called within the timeout period.

Note: The servlet instance that processed the doRequest() method used to handle the original incoming request method will not necessarily be the one to process the doTimeOut() method.
Listing 9-5 Overriding doTimeOut() in AbstractAsyncServlet.java
public void doTimeout (RequestResponseKey rrk)
      throws ServletException, IOException
{
      HttpServletRequest req = rrk.getRequest();
      HttpServletResponse res = rrk.getResponse();

      res.setContentType("text/html");
      PrintWriter out = res.getWriter();
      out.println("Timeout!");
}

Future Response Servlet

Although Oracle recommends using the Abstract Asynchronous Servlet, you can also use the Future Response Servlet to handle servlet responses with a different thread than the one that handles the incoming request. You enable this servlet by extending weblogic.servlet.FutureResponseServlet.java, which gives you full control over how the response is handled and allows more control over thread handling. However, using this class to avoid hung threads requires you to provide most of the code.

The exact implementation depends on your needs, but you must override the service() method of this class at a minimum. The following example shows how you can override the service method.

Listing 9-6 Overriding the service() method of FutureResponseServlet.java
  public void service(HttpServletRequest req, FutureServletResponse rsp)
throws IOException, ServletException {
if(req.getParameter("immediate") != null){
PrintWriter out = rsp.getWriter();
out.println("Immediate response!");
rsp.send();
} else {
Timer myTimer = new Timer();
MyTimerTask mt = new MyTimerTask(rsp, myTimer);
myTimer.schedule(mt, 100);
}
}

private static class MyTimerTask extends TimerTask{
private FutureServletResponse rsp;
Timer timer;
MyTimerTask(FutureServletResponse rsp, Timer timer){
this.rsp = rsp;
this.timer = timer;
}
public void run(){
try{
PrintWriter out = rsp.getWriter();
out.println("Delayed Response");
rsp.send();
timer.cancel();
}
catch(IOException e){
e.printStackTrace();
}
}
}