Thursday, July 02, 2009

Weblogic-EJB 연동에서의 문제

EJB Local Interface사용시 참고용 ^^
 
출처 : 자바서비스넷
 
제목 : Tomcat-JSP, Weblogic-EJB 연동에서의 문제
글쓴이:
한덕희(duckheehan) 2002/07/25 14:52:12 조회수:1390 줄수:66
@ 현재 시스템은 이렇습니다.

JSP engine : tomcat 4.0 (OS - Linux)
EJB engine : Weblogic 6.1 with Servicepack 2 (OS - NT)


@ 상황은 이러합니다.

Tomcat에서 a.jsp라는 jsp가 돌아가고 있고 이 a.jsp에서는 Weblogic의
ejb를 사용합니다. 그런데 a.jsp는 ejb의 Remote Interface까지 잘 
얻어오는데 실제로 ejb의 method 호출에 있어서 ejb method의 parameter로
사용자가 만든 클래스의 instance를 넘기면 ejb engine으로 잘 넘어갑니다.
(parameter의 값을 찍어봐서 확실히 tomcat의 a.jsp에서 parameter가
Weblogic쪽으로 넘어왔다는 것을 확인하였습니다.) 그리고 이 넘어온 
instance를 변경하면 그 내용은 원래 parameter로 넘긴 jsp code 에서는
반영이 안되는데요. 이것을 반영되게 하고 싶은데 어떻게 해야하는지 
모르겠습니다. 보통 parameter로 객체의 reference를 넘기게 되잖아요.
그래서 넘어온 parameter를 수정하면 a.jsp에서 parameter로 넘긴 것 
역시 변화가 있어야하는 것이 아닌가요? 
이것은 같은 JVM에서 실행될때만 그런것인가요?



@ 질문을 정리하자면 이렇습니다.

1. Serializable하지 않은 class의 object를 parameter로 하여서 ejb 
   method를 call하는데 원래 ejb method를 call할때 tomcat linux 
   server에서 weblogic NT server로 object를 보내야 하므로
   writeObject() method에서 NotSerializableException이 떠야 하지 
   않나요?
   Exception이 안뜨고 Tomcat에서 Weblogic으로 잘 전달 됩니다. 
   이 점이 매우 이상합니다.
   (제가 추측하는 바로는 tomcat에서 알아서 Serializable하게 만들어
   보낸다는 생각밖에 안드네요.)


2. a.jsp에서 parameter로 넘긴 것을 ejb method 내에서 수정하면 그것을 
   a.jsp에서 넘긴 parameter도 그 수정내용이 반영되게 하고 싶은데
   방법이 없나요? 그냥 Weblogic server에서 jsp도 돌리고 ejb도 돌리면 
   같은 JVM에서 실행되니까 무언가 그냥 바로 바뀔것 같은데 지금 제 
   경우는 네트웍을 통해서 서로 instance가 참조되는것이니까 무언가 
   다른점이 있는것 같습니다. (즉 jsp에서 ejb method call할때 넘기는데
   OUT변수를 사용하고 싶다는 말입니다.)

3. 그리고 한가지 더 질문이 있는데 jsp 내에서 참조되는 request라는 
   implicit한 객체는 vender별로 implemention하는 것으로 알고 있는데요.
   (Weblogic에서 만든 request와 Tomcat에서 만든 request는 다릅니다. 
   Sun에서는 interface만 제공하고 업체별로 그것을 구현하죠.)  
   tomcat에서 만든 이 request객체는 네트웍을 통해서 ejb method의 
   parameter로 넘길수 없는 것입니까? 이부분에서 MarshalException 이
   나는데요 StackTrace를 쫒아가 보면 결국 writeObject에서 
   NotSerializableException이 나네요. Weblogic의 경우는 jsp 에서 
   만들어진 request는 항상 ejb engine과 같은 JVM에서 실행되므로 
   request가 그냥 넘어 갈꺼 같은데요 (Network를 사용하지 않고도 
   말이죠.) 과연 저 request가 제대로 넘어가지 않는 이유를 알고
   싶구 이문제를 해결하고 싶습니다. 


이쪽에 먼저 경험이 있으신 분들의 조언 부탁드립니다. 제가 일하고 있는 
회사의 프로젝트중에 이 문제가 아주 critical한 문제가 되었습니다. 
그냥 지나치지 마시고 조금만 더 생각해 봐주세요. 이 문제에 목매고 
있는 사람도 있답니다. ^^;

그럼 미리 감사드립니다.
제 연락처는 duckheehan@yahoo.com 입니다. 
제목 : Re: EJB Remote Method에 전달 가능한 타입 및 이슈
글쓴이:
차의중(prof21) 2002/07/26 17:02:26 조회수:899 줄수:81
1. Serializable하지 않은 class의 object를 parameter로 하여서 ejb  method를 call하는데
  원래 ejb method를 call할때 tomcat linux server에서 weblogic NT server로 object를
  보내야 하므로 writeObject() method에서 NotSerializableException이 떠야 하지 않나요?
  Exception이 안뜨고 Tomcat에서 Weblogic으로 잘 전달 됩니다. 이 점이 매우 이상합니다.
 (제가 추측하는 바로는 tomcat에서 알아서 Serializable하게 만들어 보낸다는 생각 밖에
  안드네요.)

=> 리모트 메소드의 파라메터로 전달될 수 있는 타입은 아래와 같습니다.
1. 리모트 인터페이스(리모트 인터페이스,리모트 홈 인터페이스...)
2. java.io.Serializable 을 직/간접적으로 구현한 클래스
3. 자바 기본형(primitive type : int, boolean, short....)


*파라메터의 타입을 다시 한 번 확인해보시기 바랍니다. 톰캣이 알아서 Serializable 하게
만들어주지는 않습니다.분명, 상위 클래스에서 java.io.Serializable 을 구현했거나, 상위
인터페이스에서 java.io.Serializable 을 상속했을 가능성이 가장 높습니다.

*그렇지 않다면, 1 또는 3의 조건을 만족시키는 녀석일것입니다.

2. a.jsp에서 parameter로 넘긴 것을 ejb method 내에서 수정하면 그것을 a.jsp에서 넘긴
 parameter도 그 수정내용이 반영되게 하고 싶은데 방법이 없나요? 그냥 Weblogic
 server에서 jsp도 돌리고 ejb도 돌리면 같은 JVM에서 실행되니까 무언가 그냥 바로 바뀔것
 같은데 지금 제 경우는 네트웍을 통해서 서로 instance가 참조되는것이니까 무언가 다른
 점이 있는것 같습니다. (즉 jsp에서 ejb method call할때 넘기는데 OUT변수를 사용하고
 싶다는 말입니다.)

=> 원격호출에서, 리모트 메소드의 파라메터나 리턴은 call-by-value 에 의해 전달됩니다.
즉, 객체의 레퍼런스가 아닌 객체의 복사본이 전달된다는 것입니다.
따라서, 이 경우, 리모트 메소드 내에서 객체가 가진 속성값을 변경시킨다 해도
클라이언트의 객체에는 이 사항이 반영되지 않습니다. 
따라서, 님이 처한 상황은 아주 당연한 상황입니다.
님이 원하시는 상황을 구현하기 위해서는 파라메터로 님이 원하는 객체의 리모트 레퍼런스를
전달하셔야 합니다. 즉, 파라메터로 넘어가는 객체는 리모트 인터페이스를 가진 엔터프라이즈
빈이거나, RMI객체이어야 합니다. 이 경우도, 하부에서 실제로는 call-by-value에 의해 리모트
객체의 스텁이 전달됩니다만, 그 객체가 rmi 스텁이라는 특수성을 가지고 있으므로, 리모트
메소드 내에서, 파라메터로 전달된 레퍼런스를 통해 객체에 가한 행위(메소드 호출)가
클라이언트에 반영됩니다. 


그리고, 님이 오해하고 계신 부분이 있습니다. 리모트 인터페이스를 통해 메소드를 호출하면,
그 메소드의 파라메터로 전달되는 객체는 반드시 위 1번 질문의 답으로 드린 타입의
객체들만이 전달가능합니다. 그렇지 않으면, 동일한 JVM에서 서로를 호출한다고 해도
NotSerializableException이 발생하게 됩니다. 리모트 인터페이스를 구현하는 EJB의
스텁에서는, 항상 파라메터를 직렬화하려고 시도하기 때문입니다.

동일 JVM상에서 실행되는 엔터티 빈과 클라이언트간에도 원격 호출 메커니즘이 사용 되는
단점을 해결하기 위해, EJB2.0에서는 로컬 인터페이스라는 것을 제안하고 있습니다. 로컬
인터페이스를 통해 빈의 메소드를 호출하는 것은 일반적인 자바의 지역호출(메모리 주소를
참조하는)을 이용하여 빈의 메소드를 호출하는 것입니다. 이 경우는 일반적인 자바의 메소드
호출이므로 call-by-reference가 사용됩니다.
즉, 파라메터로 넘어온 레퍼런스플 통해 객체의 내용을 변경시키면, 클라이언트가 가진
원래의 객체에도 반영됩니다. 

3. 그리고 한가지 더 질문이 있는데 jsp 내에서 참조되는 request라는 implicit한 객체는
 vender별로 implemention하는 것으로 알고 있는데요. (Weblogic에서 만든 request와
 Tomcat에서 만든 request는 다릅니다. Sun에서는 interface만 제공하고 업체별로 그것을
 구현하죠.)  tomcat에서 만든 이 request객체는 네트웍을 통해서 ejb method의 parameter로
 넘길수 없는 것입니까? 이부분에서 MarshalException이 나는데요 StackTrace를 쫒아가 보면
 결국 writeObject에서 NotSerializableException이 나네요. Weblogic의 경우는 jsp 에서 
 만들어진 request는 항상 ejb engine과 같은 JVM에서 실행되므로 request가 그냥 넘어 갈꺼
 같은데요 (Network를 사용하지 않고도 말이죠.) 과연 저 request가 제대로 넘어가지 않는
 이유를 알고 싶구 이문제를 해결하고 싶습니다. 


=>그렇다면  분명 request 를 구현한 객체는 직렬화가 가능하지 않은 객체일 것입니다.
  

그리고, request 의 구현객체 및 그것이 가진 멤버변수들이 직렬화가 가능하지 않다면, 님이 
하시고자 하는 일은 결코 이루어질 수가 없습니다. (톰캣의 소스를 뜯어서 바꾸지 않는이상)

그러니, request 객체를 바로 넘기려 하지 마시고, 그것이 가진 내용 중 필요한 
것들만을 꺼내어 그것들을 넘기도록 하십시요.



-----------------------------------------------------------------
본 문서 및 첨부파일은 자유로이 복사/배포가 가능하나 반드시 저자의
이름과 연락처를 명시해주시기 바랍니다.

차의중
prof21@empal.com
제목 : Re: transient를 사용하는 것은 어떤 가요?
글쓴이:
정진욱(bpdesign) 2002/08/01 01:40:08 조회수:634 줄수:66
안녕하세요 bpdesign 정진욱 입니다.

정말 오랜만에 글을 올려봅니다. 솔루션 개발이 마무리 단계라 요즘 겨우 시간이나서
jsn에 글을 보고 있으면 점점 시대에 뒤쳐지는 듯한 느낌이 드는 군요...

마침 저도 매니저단을 ejb stateless sessionbean으로 구현중인 데, 
실제로 jsp단에서의 파라메타들을 받아서 매니저쪽에서 처리해야 하는 문제가 있어서
질문하신 분내용에 관련되는 부분이 있어서 고심하고 있는 의견을 함 말씀드릴 까 합니다.

마지막 부분의 질문에 젤 많이 해당되는 내용이라 한번 적어 봅니다.

먼저 차의중님이 말씀하신 대로, ejb 빈에서 request를 직접 사용하는 것보다
request에서 필요한 파라메타들을 꺼내서, 
직렬화 가능한 타입으로 ejb 빈에서 파라메타로 처리하는 것이 가장 나은 방법인 것
같습니다.(직렬화 에러를 처리하는 데 있어서요)

반면 다른 방법을 찾아보고 있었는 데, ejb design pattern 책에서 transinet를 사용하는
방법이 나오더군요

즉 j2ee pattern중 business delegate 디자인 패턴을 사용하는 경우
business delegate 클래스는 ejb bean을 감싸는 래퍼 클래스로 구현하는 것으로 압니다.
또한 business delegate 클래스의 인스턴스가 생성될 때
멤버변수인 해당 ejb bean의 remote interface 객체가 생성되게 되죠.
따라서 business delegate 클래스의 모든 메소드는 ejb 빈의 메소드에 delegation하는 형태가
됩니다.

jsp에서 직접 ejb빈을 lookup해서 메소드를 콜하는 것보다는
해당 ejb 빈에 대한 business delegate 클래스를 래퍼로 만들어서
useBean으로 business delegate 클래스의 객체를 생성하면
일반 javabean으로 jsp에서 콜하는 것과 동일하게 코딩할 수 있습니다.

(물론 여기서 서로 다른 jvm에 있을 경우, ejb 빈이랑 business delegate 클래스가 같은 jvm에 
있어야 한다고 생각됩니다만... 이부분은 좀 명확하진 않네요.)

이때 질문하신 분처럼 request나 session을 파라메타로 넘기는 경우
request,response는 serializable되어 있지 않으면 NotSerializableException이 나게 되죠...

ejb design pattern 책에서는 이에 대해서, 

Business delegate 클래스에서 멤버 변수로 가지는 ejb bean의 Remote Interface 변수를
transient로 하는 방법을 말하고 있습니다.
반면
Business delegate 클래스 자체는 serializable을 구현하구요...

사실 이부분에 대한 test는 끝나지는 않았습니다만.
request객체를 메소드의 파라메타로 local scope로 하지 않고
클래스 변수로 해서 transient로 하면 직렬화를 하지 않고서 해결할 수도 있으리라 생각됩니다.

제가 추측성 어조로 쓰는 이유는 아직 명확하게 test를 하지 못했기 때문입니다.
일단 이부분이 저희 개발에서 해결할 부분이니 만치, 파라메타 추출이냐,
아님 transient이냐의 방법을 정해서 하게 될텐 데 더 자세하게 test를 해보고 향후 다시
글을 올리도록 하겠습니다.
(물론 세번째로 ejb bean에서 사용하는 모든 클래스를 풀로 serializable하게 하는 방법도
 있습니다만 jwsdp에서 servlet api로 확인해 본 바로는 HttpServletRequest와
 HttpServletResponse는 serializable을 구현하고 있지 않았습니다.
따라서, request나 response를 serializable하려고 한다면 이는 WAS에 종속적인 
개발이 될것으로 생각되네요...)

ejb design pattern 책에서 transient로 찾아보시면 예제 코드를 확인하실 수 있을 것입니다.

-------------------------------------------------------  
JavaCraft.Net(http://www.freechal.com/ejbstudy)
EJB Design Pattern group(프로자바)
================================================
E-Mail: bpchung@ihanyang.ac.kr 
        bpdesign@freechal.com  
제목 : Re: EJB Remote Method에 전달가능한 타입 및 이슈
글쓴이:
차의중(prof21) 2002/08/01 13:55:59 조회수:388 줄수:28
답변에 감사드립니다.

단, 제시해주신 방법은 어떤 경우에는 사용이 가능하고, 어떤 경우에는 사용이 불가능할것입니다.
아시다시피, 어떤 클래스, 즉 예를 들어 HttpServletRequest 클래스가 Serializable 하지 않다면,
그 클래스의 인스턴스는 rmi를 통해 전송될 수 없습니다.

또한, 해당 클래스가 Serializable하다고 해도 그 클래스의 멤버 변수들이 가리키는
인스턴스들이 Serializable하지 않다면 이 경우도 역시 rmi를 통해 전송될 수 없습니다.

그렇다고 해서 Serializable하지 멤버변수들을 transient로 선언한다면,
NotSerializableException은 발생하지 않겠지만, 해당 멤버변수가 가리키는 인스턴스는
rmi를 통해 전송되지 않습니다. 만일, 해당 멤벼변수가 가리키는 인스턴스를
rmi를 이용하여 전송해야 할 필요가 있을 경우에는 말씀하신 방법은 사용할 수가 없을것입니다.

ps : 질문하신 분께서는 정진욱 님과 저의 답변을 곡해하지 마시기를 바랍니다.

질문 중 리모트에 위치하는 EJB내에서 변경시킨 HttpServetResponse
의 인스턴스의 내용이 클라이언트쪽의 원래 인스턴스에 반영될 수 있느냐 하는 부분은
직렬화 가능/불가능의 문제가 아닌 call-by-reference/call-by-value에 관한 문제입니다.
rmi는 항상 call-by-value에 의해 인스턴스를 전달하므로, 리모트에서 변경시킨
인스턴스의 내용이 클라이언트측의 인스턴스에 반영될 수는 없습니다.

-----------------------------------------------------------------
본 문서 및 첨부파일은 자유로이 복사/배포가 가능하나 반드시 저자의
이름과 연락처를 명시해주시기 바랍니다.

차의중
prof21@empal.com

No comments: