자바스터디 네트워크 [www.javastudy.co.kr]
조대협 [bcho_N_O_SPAM@j2eestudy.co.kr]
1. WebLogic Class Loader
EJB와 웹애플리케이션을 디플로이하기 위해서는 효과적인 패키징이 필요하다. 효과적인 패키징을 위해서는 먼저 WAS의 ClassLoader의 구조에 대해서 알필요가 있는데, 먼저 WebLogic의 ClassLoader에 대해서 살펴보도록 하자.
○ Class Loader란?
Class Loader란 자바의 큰장점중의 하나로, Compile Time이 아닌 Run Time에 Class를 로딩할 수 있게 해주는 기술이다. 예를 들어, ClassA = new ClassA(); 라는 코드를 최초로 실행할때, JVM은 ClassA라는 Class를 Class Loader를 통해서, ClassA.class의 바이트 코드를 최초로 메모리에 로드하게 된다. Class Loader는 이처럼, Class의 바이트 코드를 FileSystem이나,Jar와 같은 Archieve또는, network socket(Applet and RMI)를 통해서 동적으로 로딩할 수 있도록 지원해준다.
이 Class Loader는 기술적으로 몇가지 특징을 가지고 있는데 그 내용을 살펴보면 다음과 같다.
- Hierarchical
: Class Loader는 Hierarchical 하게 생성이 가능하다. Parent class loader에서, child class loader를 갖는것과 같이 Class Loader간의 계층형 구조를 갖게 되며, 최상위의 Class Loader는 "bootstrap" Class Loader가 위치하게 된다.
- Delegate load request
: 위와 같이 Class Loader가 계층형 구조를 가지고 있기 때문에, Class 로딩상에 몇가지 규칙이 필요한데, 일정 시점에 Class Loading 요청을 받았을때, 상위 Class Loader가 Loading한 Class가 그 우선권을 가진다.
예를 들어 설명하면, Class Loader가 parent부터, CL1-CL2-CL3 순서로 생성되어 있다고 가정하자, 애플리케이션이 Class Loader CL3로 Class를 요청하면, CL3는 그 요청을 CL2로, CL2는 CL1으로 요청을 전달한다. 즉, Class 로딩의 우선 순위는 parent class가 가지고 있고, 만약에 요청받은 Class가 없을 경우에만 아래 레벌 Class Loader가 Class를 로딩하게 된다.
- Have visibility constraint
: 상위 Class Loader를 먼저 참조하는것에 이어서, Class Loader는 일종의 scope rule을 제공하는데, Child Class Loader는 Parent Class Loader의 Class를 Delegation load request를 이용하여 찾을 수 있지만, 그 반대로 Parent가 Child가 Loading한 Class를 사용할 수 는 없다. 또한 Parent의 같은 Level의 Child Class Loader는 서로 로딩한 Class를 사용할 수 없게 되어 있다.
- Cannot unload classes
: Class Loader에 의해서 Loading된 Class들은, unload될 수 없다.. Class Loader에는 Class Unloading기능이 없다. 그래서 이 unloading 기능을 우회적으로 구현하는 방법은 Class를 로드한 Class Loader 자체를 삭제하고, 새로운 Class Loader를 만들어서 다시Class 를 로드하면, reload되는 것처럼 작동하는것이 된다.
내용이 좀 어려울 수 도 있겠지만, WLS의 뒤에 나올Class Loader의 내용을 읽어보면 이해가 될것이다. Deploy 개념을 이해하는데 중요한 내용이니 이해하도록 하자.
○ WebLogic의 Class Loader
그럼 이제 WebLogic의 Class Loader에 대해서 알아보도록 하자. 이 feature는 단지 WebLogic뿐 아니라, J2EE 표준을 따르는 WAS는 모두 준수하고 있는 내용이다.
일단 WebLogic이 기동되면 JVM Level의 Class Loader가 Loading된 후에, WebLogic의 Application에 따라 각각의 Class Loader가 그 Child로 Loading된다.
JVM Class Loader
먼저 JVM이 가동될때, Loading되는 Class Loader는 parent부터 순서대로, Bootstrap, Extensions, System Class Loader가 올라가게 된다. 그 내용을 살펴보자
- Bootstrap Class Loader
: JVM이 실행될때 맨 처음 실행되는 Class Loader로, 가장 기본적인 JAVA실행에 필요한 가장 기본적인 Class들을 (rt.jar, i18n.jar 와 같은 기본적인 Archieve) 로딩한다.
- Extensions Class Loader
: BootStrap Loading후, 기본적으로 Loading되는 Class로 $JAVA_HOME/lib/ext에 있는 Class들이 Loading된다. 이 Class들은 별도로 classpath에 잡혀 있지 않아도 Loading된다.
- System Class Loader
: 다음으로, CLASSPATH에 정의되거나 JVM option에서 -cp, -classpath에 지정된 Class들이 로딩된다.
기본적으로 WebLogic은 이 JVM Level의 Class Loader에서 작동을 하게 되고, Application을 Deploy할때 마다 별도의 Class Loader를 System Class Loader의 Child로 Invoke하게 된다.
JVM Class Loader
WebLogic에서 Invoke되는 Class Loader는 종류에 따라 EJB-JAR,WAR,EAR 3가지로 구분이 된다. 각자의 Class Loader에 대해서 체크해야할 사항을 짚고 너머가 보자.
- EJB-JAR
: 각 EJB-JAR 파일은 디플로이가 되면, JAR파일당 각각의 Class Loader를 생성하게 된다. 그래서, 다른 JAR파일에 있는 Class들은 참조를 할 수 가 없고, 오로지 Parent Class Loader인, JVM Level의 CLASSPATH에 적용된 CLASS들만 참조를 할 수 있다. 그래서, 다른 EJB JAR파일내에 있는 EJB를 사용하기 위해서는 그 EJB의 Client class들(Remote Interface,Home Interace)을 같이 JAR로 묶어주어야 한다.물론 같은 JAR파일내에 있는 EJB나 다른 Class를 사용하는 것은 같은 Class Loader상에 Load된것이기 때문에, 가능하다.
- WAR
: Servlet이나 JSP를 패키징하는 WAR파일 역시 EJB-JAR와 같은 특성을 갖는데, 집고 넘어가야할점은 웹로직에서는 WAR에 대해서 우선순위 변경이 가능한데,일반적인 Class Loader의 우선순위를 따르는것 이외에, WEB-INF/classes와, WEB-INF/lib 디렉토리가 우선순위를 갖것이 가능하다. 이 디렉토리안에 class가 있을 경우에는 parent class loader에 load된 Class보다 우선순위를 갖게 설정할 수 있다.이설정은 웹로직 콘솔에서 PreferWebInfClasses 라는 옵션을 true로 설정(default는 false이다.)을 하면 가능하며, 자세한 내용은 (http://e-docs.bea.com/wls/docs61/programming/packaging.html 에Using PreferWebInfClasses in J2EE Applications 부분을 참고하기 바란다.)
- EAR
: 위의 EJB-JAR와 WAR는 각각 하나의 Class Loader를 갖는데 반해서, EAR을 두개의 Class Loader를 갖게 된다. EJB-JAR를 위한 Class Loader와 WAR를 위한 Class Loader 두개가 Invoke되고, 그 관계는 EJB-JAR Class Loader가 WAR Class Loader의 Parent관계가 되서, Servet/JSP는 당연히 EJB Class를 참조해서 사용이 가능해지게 되는것이다. (JSP는 WAR Class Loader에 의해 Loading되었기 때문에, 그 Parent인 EJB-WAR Class Loader에 의해 Loading된 EJB Class를 사용할 수 있게 되는것이다.)
<그림 1. WebLogic Class Loader 구조>
그럼 <그림 1>을 보자. 그림 1의 EJB JAR5는 EAR1이나 WAR4, EAR2의 Class Loader와 다른 Class를 사용하기 때문에, 다른 패키지의 Class를 참조할 수 없다.
EAR1의 WAR1은, EAR로 같은 Class Loader상에 있는 EJB JAR1,EJB JAR2,EJB JAR3에 있는 Class를 참조할 수 있다. 그러나 EAR2의 Class는 참조할 수 없다. 그러나 역으로, EJB Class Loader가 WAR Class Loader의 Parent이기 때문에, EJB JAR 1.2.3는 WAR1,2의 Class를 참고할 수 없다.
여기서 한가지 집고 넘어가야할것은 모든 EJB JAR가 참조하는 Class들은 CLASSPATH내에 있는 Class가 우선시 된다. (JVM Class Loader가 모든 WebLogic Class Loader의 parent이기 때문에.) 그래서, EJB의 Client Class나, Common Class들을 CLASSPATH와 JAR양쪽에 넣으면 CLASSPATH내에 있는 CLASS가 참조가 된다. (이런식의 패키징은 권장하지 않는다. 상세한 내용은 다음에 나올 EJB 패키징 부분에서 알아보도록 하자)
※ WLS 8.1에서부터는 개발환경을 위해서 Class Loader의 계층구조를 임의로 지정할 수 있게 되어 있다. 자세한 내용은 (http://e-docs.bea.com/wls/docs81/programming/classloading.html#1083313) 를 참고하기 바란다.
JVM Class Loader
J2EE에서, WAS가 하나의 Class Loader를 이용하지 않고, 각 WAR,EJB-JAR,EAR별로 별도의 Class Loader를 사용하는것은 다음과 같은 이유를 가지고 있다.
- Isolation
: 개발그룹 A가 Application app-A에 대해서 개발과 deploy를 할때, 다른 Application에 대해서 신경쓸 필요없이 작업 수행이 가능하게 된다. 만약 모든 Applilcation이 하나의 Class Loader를 사용하게 된다면, 하나의 애플리케이션을 deploy할때마다, Class Loader가 restruct되는등 영향을 받을 수 있다.
- Singleton
: 이렇게 Class Loader를 따로 사용하기 때문에, Application 별로, 당연히 Singleton Pattern이 따로 적용된다. 만약 Class Loader가 전역적으로 하나만 사용되었다면, 다른 Application에 의해서, Singleton이 오작동할 수 도 있을것이다. (Singleton은 GoF의 Design Pattern중의 하나이다. 자세한 내용은 Design Patterns-Addison Wesley를 참고하기 바란다.)
- Namespace
: Namespace의 확장도 가능하게 되는데, webApp1.war와 webApp2.war 파일에 똑같이 index.jsp 라는 파일이 있을때, WAS는 각 Class의 Name space를 Class Loader + File Name이라는 Namespace를 사용하기 때문에, 다른 Application안의 컴포넌트들을, 어떻게 naming 하느냐는 것은 문제가 되지 않는다.
- Hotdeploy
: Hotdeploy는 J2EE의 중요한 feature중의 하나인데, WAS가 가동중에, 컴포넌트를 redeploy할 수 있는 기능을 Hotdeploy라고 한다. 위에서도 설명했듯이, redeploy를 하는 기능은 Class Loader에는 없기 때문에, redeploy를 하기 위해서는 기존의 Class Loader를 unload하는 동시에, 새로운 Class Loader를 Loading하여, Class 를 reloading하게 된다. 이렇게 Class Loader를 나누어 놓음으로써, 효과적이고 빠르게 redeploy가 가능하게 된다.
- Deploy
: Application의 배포역시, Application 단위로, Class Loader를 이용하기 때문에, Application 단위로 배포가 가능해진다. Class Loader를 하나만 사용했다면, 일부만 변경이되더라도 Application 전체를 redeploy해야 됐을것이다.
이제까지, 간단하나마, JVM Class Loader와, WebLogic Class Loader의 내용에 대해서 살펴보았다. 그러면 이 특성에 따라서 각각의 애플리케이션과 컴포넌트들을 어떤식으로 패키징하는가에 대해서 알아보도록 하자.
2.Packaging Component
J2EE 패키징을 하는데 있어서 가장 큰 이슈는 EJB의 Client Class(Home Interface,Remote Interface)와, Common Class들일 것이다.. 이 Class들을 Deploy하는 방법이 어떤것이 있는지, 그리고 그 장단점에 대해서 알아보도록 하자.
○ WEB-INF/classes
Servlet,JSP에서 사용하는 EJB Client Class와, Common Class를 classes 디렉토리에 풀어서 배포하는 방법인데, 수정과 삭제가 편하다는 장점은 있으나, Web Application 마다, classes 디렉토리에 배포를 해야하기 때문에, Version 관리 문제나 Sync 문제가 발생할 수 있고, 파일단위로 관리하기때문에, 번거롭다. 소규모가 Application이 아닌경우에는 권장하기 어려운 방법
○ WEB-INF/lib
Servlet,JSP에서 사용하는 EJB Client Class와, Common Class를 jar로 묶어서, lib 디렉토리에 위치시킬 수 있다. Jar단위로 묶어서 패키징하기 때문에, 관리가 간편하다는 장점이 있다. 단점은 WEB-INF/classes에 배포하는것과 같다.
○ Class files within EJB JAR
EJB에서 사용하는 Common Class와, 참고하고 있는 외부 EJB-JAR의 EJB Client Class를 하나의 jar파일에 패키징하는 방법. 이 방법은 EJB-JAR 파일 단위로,독립성이 뛰어나고 핸들링하기 편하다는 장점은 있으나, 각각의 EJB-JAR에 Class들이 직접 패키지되기 때문에, 변경 사항이 있을때마다 다시 패키징을 해야한다.
○ Class files on system CLASSPATH
EJB Client Class와, Common Class들을 아예 System CLASSPATH에 넣어버리는 방법도 있다. 이렇게 할경우에는 CLASS를 사용하는것이 매우 간편해지기는 해지고, common class의 경우에는 중복하여 배포할 염려없이, CLASSPATH내에 있는 것만 바꾸면 되기 때문에, 일관성을 유지하기가 좋다
그러나 그 CLASS들을 바꾸거나 할경우에는 WAS를 restart해야하는 제약 사항이 따르게 되구. Hotdeploy와 같은 기능을 사용하는것은 불가능하게 된다
○ jar on system CLASSPATH
바로 앞의 방법에 Class files을 jar로 묶어서 CLASSPATH에 배포하는 방식으로, 위와 같은 단점을 가지지만, jar 단위로 묶어서 관리를 하기 때문에, 앞의 방법보다는 Class 관리가 편리하다.
○ jar in EAR
가장 일반적인 배포 방법으로client class와 common class을 jar로 묶어서, Application ear 안에 함께 묶어서 배포하는 방식으로, ear단위로 application 관리와 배포가 가능해진다.
그러나 두개 이상의 application이 공통된 common class 파일들을 참조하는 경우에는 각각의 ear에 common class를 넣어서 패키징해야 하기 때문에, 이런 경우에는 일관성의 문제가 발생할 수 도 있다.
○ MANIFEST.MF
JDK1.2의 "extension mechanism" 이라는 이름으로 등장한 기능으로, JAR파일이 다른 JAR파일의 Class들을 참조할 수 있게 해주는 기능이다.일단 사용법부터 살펴보면
/META-INF/MANIFEST.MF 라는 파일로 정의가 되고
Manifest-Version: 1.0
Class-Path: commonclasses.jar ./account/account_ejb_client.jar
./com/bea/
식으로 사용된다.
이렇게 정의되어 패키징된 jar파일내의 Class들은 commonclasses.jar와./account/account_ejb_client.jar 그리고./com/bea/ 에 있는 Class들을 사용할 수 있게 된다.
여기서 꼭 주의해야할 점은 Class-Path의 디렉토리 경로는 상대 경로만 지정이 가능하며, 이 상대경로의 기준 디렉토리는 해당 JAR파일의 Class들이 실행되는 디렉토리 이다. 그런데, 이 실행디렉토리라는 것이, WAS에 디플로이된 jar파일의 경로가 아니다.WLS의 경우 해당 jar가 $WLS_HOME/config/mydomain/applications에 위치하고 있더라도, 그 디렉토리를 기준으로 하지 않는다는 이야기이다. 대부분의 WAS가 실행시에, 그 jar를 컴파일하거나 캐슁해서 사용하는 staging 디렉토리에 그 class들을 위치해놓고 수행을 하기 때문에, staging 디렉토리가 어디가 될지는 WAS의 종류와 환경에 따라서 다르다.
이런 이유로 MANIFEST.MF를 사용하는 경우는 EAR안에 같이 패키징된 JAR파일간의 reference를 결정하는데만 사용해야하며, 그중에서도 deploy order를 정의하는데 사용된다. 즉jar in EAR 의 경우, common class가 그 Class를 사용하는 EJB보다 늦게 deploy가 되면 Class NotFound 상태가 될 수 있기 때문에, common class를 먼저 deploy 시킬때, 그 common class를 사용하는 EJB의 EJB-JAR에 MANIFEST.MF를 이용하여, common class가 먼저 로딩되게하는데 사용을 한다.
꼭 기억해야 할것은 위와 같은 이유로 MANIFEST.MF는 EAR안에서만 사용해야 한다는 것이다.
지금까지 common class와, ejb-client-class들을 패키징하는 몇가지 정책에 대해서 알아보았다. 어떤것이 절대적으로 좋고 나쁘다는 정석은 없다. 개발 상황과, 정책에 따라서 알맞은 패키징 정책을 선택하는 것이 올바른 길일것이다. 단. 패키징 정책을 결정하지 않고, 개발을 진행하다가는 추후에 낭패를 볼 수 있으니, 패키징 전략을 수립한후에, 개발을 진행하도록 하자.
○ APP-INF/lib or APP-INF/classes (WLS 8.1 이상)
WLS 8.1부터 새로 등장한 방법으로, common class들을 APP-INF/classes나, lib 디렉토리에 배치하면, 그 ear안에서 자유롭게 사용할 수 있게 된다
NOTE!
좀더 효율적인 패키징 전략 수립을 위해서는 Component간의 Dependency와 패키징 구조를 파악하는 것이 중요한데, 이는 UML을 이용한 OOAD(Objected Oriented Analysis and Design) 단계에서 Class 간의 Dependency Diagram을 통해서 파악하고, 이를 Deployment Diagram을 통해서 형상화 하면 좀더 논리적이고 체계적으로 패키징 전략을 수립하는것이 가능하다.
※ Call by reference and Call by value.
잘알고 있겠지만, Java의 Call 방식에는 Call by reference와, Call by value 두가지 방법이 있다. 당연히 Call by reference가 속도나 효율면에서는 뛰어나겠지만, EJB와 같은 Remote Call의 경우에는 사용되는 Object나, Call Method의 인자전달을Call by value를 사용한다.
WLS 에서는 같은 EAR안에 패키징을 할경우에는 WLS가 RMI call을 optimize하여, call by reference로 하도록 조정해주고, local interface를 사용할 경우에도, call by refrerence를 사용하도록 한다.
이런 이유로, 같은 EJB를 어떤식으로 Packaging하느냐에 따라서도 Performance차이가 날 수 있다는것을 참고하도록 하자.
3. EJB Packaging Order
지금까지는 Application이 어떻게 패키징 되는지, 패키징 된 Class들이 어떤 방식으로 Loading되는지 알아보았다. 그럼 WebLogic Server에서, 어떤 과정을 거쳐서, EJB를 Packaging 하여 war,jar,ear등을 만들어내는지에 대해서 알아보도록 하자
○ MANIFEST.MF
1) develop ejb component
2) compile ejb component
개발한 EJB를 class로 컴파일 한다.
3) define EJB deployment descriptor
WebLogic에서는 3개의 Deployment descriptor를 필요로한다.
ejb-jar.xml
weblogic-ejb-jar.xml
weblogic-cmp-rdbms-jar.xml (optional, for CMP only)
EJB의 Deployment Descriptor를 만들어야 되는데, 이 부분은 WebLogic에서 어느정도 자동화가 가능하다.
EJB class가 있는 디렉토리에서 다음 명령어를 이용하면, Deployment Descriptor (ejb-jar.xml weblogic-xxx.xml) 파일을 자동으로 생성해준다.
WLS6.1
(EJB 1.1) java weblogic.ant.taskdefs.ejb.DDInit [dir]
(EJB 2.0) java weblogic.ant.taskdefs.ejb20.DDInit [dir]
(Web App) java weblogic.ant.taskdefs.war.DDInit [dir]
(App) java weblogic.ant.taskdefs.ear.DDInit [dir]
WLS 7.0
(EJB) java weblogic.marathon.ddinit.EJBInit [dir]
(App) java weblogic.marathon.ddinit.EarInit [dir]
(Web App) java weblogic.marathon.ddinit.WebInit [dir]
이를 통해서 생성된 EJB DD들은 완전한것이 아니기 때문에, 직접 에디터를 통해서 수정하도록 하자.
아래 그림은 각각의 EJB deployment descriptor가 어떻게 시스템과 맵핑이 되는지를 나타내주는 그림이다.
4) packaging EJB to jar file
이렇게 개발된 EJB class파일들과, deployment descriptor를 jar 유틸리티를 이용해서 jar파일로 패키징 한다.
5) generate EJB stub (* important !!)
4)단계까지는 대부분의 사용자가 잘 진행을 하지만, 시중의 많은 서적이나, 초보 가이드 문서에 빠져있는 부분이 EJB stub을 만드는 부분이다.
우리가 코딩하는 EJB 부분은 EJB의 로직부분이다. EJB는 분산객체이기 때문에, 아랫단에서 네트워크 환경을 위한 RMI 등의 통신 메커니즘을 제공하는데, 이 통신 메커니즘에 해당하는 부분이 EJB의 stub class들이다. 요즘의 WAS들은 이 stub Class들을 EJB deploy과정에서 자동으로 생성해주는 경우가 많은데, 이 과정은 server에 upload되는 순간에, EJB의 내용을 분석하여, stub의 java source 파일을 생성하고, javac 컴파일러를 invoke하여, stub class를 generation 하게 된다. 이 기능은 개발시에 매우 편리하니, 개발과정에서 사용하도록 하자.
그러나 운영시에는 deploy하는 과정에 많은 EJB stub을 만들고 컴파일하는데 많은 resource가 소요된다. 결과적으로, 한꺼번에 많은 EJB를 deploy할때는 이 stub을 생성하는 과정에서 동시에 많은 resource가 사용되서 시스템이 느려지거나, boot up 시간에 영향을 주는 경우가 많다.
이런 이유로, ejb를 서버에 deploy하기 위해서, ejb stub을 미리 생성해서 패키징하여 deploy하는것이 좋다. 다음과 같은 방법으로, ejb stub을 포함한 jar파일을 생성할 수 있다.
% java weblogic.ejbc [ejb-jar-file-name] [result-file-name]
example)
% java weblogic.ejbc account_manager.jar account_manager_stub.jar
여기까지 진행하면, deploy를 하기 위한 하나의 완벽한 ejb-jar 파일이 작성된것이다.
6) packaing EJBs into ear files
앞에서 작성한 ejb-jar파일과 war파일들을 적정한 디렉토리에 배치하고, META-INF/application.xml 파일을 작성한후 jar 유틸리티를 이용하여 ear로 생성하면 최종 deploy를 위한 준비가 끝난것이다.
○ Specifying ejb-client.jar
EJB를 클라이언트에서 사용하려면 위에서 설명하였듯이, ejb client class들이 필요하다.
EJB Client class들은 EJB Home Interface,Remote Interface,Primary Class Interface나, 기타 인자가 되는 Class들로 구성이 되는데, 이 Class들만 묶어서, 해당 EJB를 사용하기 위한 jar파일로 구성하게 된다.
(※ 이때, EJB Implementation Class들과, stub Class들을 같이 묶는 경우가 있는데, 이는 deploy 방법이나 CLASSPATH 설정등에 따라서 심각한 문제를 발생시킬 수 있으니, 절대로 같이 패키징하지 말자.)
이 파일들을 일일이 골라내서 패키징하는것도 여간 번거로운 작업이 아닐 수 없다. 이것을 좀 더 편리하게 하기 위해서, J2EE spec에서는 자동으로 ejb-client.jar Class를 생성해주는 기능을 제공하는데, 간단하게 ejb-jar.xml을 수정하고, java weblogic.ejbc xxx를 실행해주면된다.
구체적인 순서는 다음과 같다.
- ejb-jar.xml에
- ejb-jar 파일을 java weblogic.ejbc [ejb-jar-file-name] [result-file-name] 를 실행하면, 해당 디렉토리에 ejb-client-class.jar라는 파일 이름으로, client Class만 추출되어진 jar파일이 생성된다.
이렇게 생성된 jar파일들은, Servlet/JSP에서 사용할 경우 WEB-INF/lib 에 위치하거나, Client Application의 classpath내에 적용되어 사용된다.
○ Deploying Pinned EJB
특히 Cluster에 EJB를 Deploy할때는 특별한 주의가 필요한데, Cluster의 경우에는 EJB를 하나의 서버에만 deploy하고, targeting을 통하여, Cluster내의 다른 서버에, EJB를 배포할 수 있다.
이경우, ejbc를 거치지 않은 EJB의 경우에는 upload한 서버의 경우에는 자동으로 ejbc를 실행하여, stub을 생성하지만, targeting에 의해 ejb가 복제된 다른 서버의 경우에는 stub이 없는 파일이 복제 되기 때문에, client에서 그 EJB를 호출할 경우, RMI Layer에서 Assertion error가 발생하게 된다.
○ Ant utility
지금까지 EJB를 배포하기 위한 패키지를 생성하는 순서에 대해서 살펴보았다. 과정이 길고 복잡하기 때문에, 개발도중 매번 일일이 실행하기에는 매우 복잡하기 때문에, J2EE에서는 예전 Unix시절의 make와 같은 유틸리티를 제공한다. Ant라는 이름의 유틸리티로, build.xml이라는 스크립트를 만들어서 위의 과정을 자동화할 수 있다. 거의 EJB 개발에서는 표준으로 사용하고 있는 유틸리티이니 한번 체크해놓도록 하자.
좀더 자세한 정보는http://ant.apache.org/ 를 참고하시 바란다.
4. EJB deploy in WebLogic Server
이렇게 만들어진 Archieve file들(war,ear,jar)을 WebLogic에서 EJB를 Deploy하는 방법은 크게 3가지 방법이 있다.
- Console deploy
- Command line deploy
- Auto deploy
○ Console deploy
WebLogic 콘솔을 이용하여, 웹브라우져에서 디플로이 하는 방법이다. 간단한 방법이므로 본 문서에서는 따로 설명하지 않는다. http://edocs.bea.com 의 WLS deploy 문서를 참고하기 바란다.
○ Command line deploy
웹브라우져를 사용할 수 없는 command line 환경에서 사용할 수 있는 방법이다.
%java weblogic.deploy ?port port_number ?host host_name deploy password name source
example)
%java weblogic.deploy ?port 7001 ?host localhost deploy weblogicpassword CMP_example c:\weblogic\CMP_example\
%java weblogic.deploy ?port 7001 ?host localhost deploy weblogicpassword bean_jar c:\weblogic\bean.jar
source 부분에는 EJB Beans의 jar 파일의 Full 경로가 들어가거나 또는 Directory 명이 들어간다.
○ Auto deploy
WebLogic의 $WL_HOME/config/$DOMAIN_NAME/applications (WLS6.1 기준) 디렉토리에 jar 파일이나, EJB 디렉토리를 복사해놓으면, WebLogic이 Boot up시에, 자동으로 디플로이되거나 또는 그 EJB의 내용이 변경되었을때, 자동으로 redeploy를 한다.
Boot up시에 deploy되는 기능은 언제나 사용이 가능하지만, WebLogic 기동중에, ejb-jar 파일을 바꿔서 redeploy하는 기능은, WebLogic을 Development Mode로 부팅했을때만 가능하다. Development Mode로 WebLogic을 부팅하는 방법은 startWebLogic.sh 에서 java 옵션에, -Dweblogic.ProductiobModeEnabled=false 로 해주면 Development로 부팅이 된다.
○ Partial upgrade (only WLS 8.1 이상)
WLS8.1에서는 Class Loader모델이 변경되어, 좀더 향상된 deploy가 가능하다. EJB는 Interface를 통해서 호출이 되기때문에, Interface가 변경되지 않은 상태에서, implemtation class 하나만 변경하여 redeploy하는 기능이 추가되었다.
이는 예전버전에서는 각각의 application 단위로, EJB Class를 Loading하였다. (JAR 파일의 경우, 하나의 Application Class Loader가, JAR안의 모든 EJB를 Loadinig했고, EAR의 경우에도, 하나의 Application Class Loader가 모든 EJB Class를 Loading했었다.) 그러나, 8.1 에서부터는 아래 그림과 같이 각각의 Application Class Loader아래에, 각각의 EJB Implemetation Class마다 별도의 Class Loader가 가동되게 됨으로써 가능해진 기능이다.
각각의 EJB Implementation Class를 redeploy하기 위해서는
java weblogic.Deployer ?adminurl url ?user user ?password password ?name myapp ?redeploy myejb/foo.class
을 해주게 되면, myapp application의 myejb jar 패키지에서 foo.class라는 EJB implementation file만 redeploy를 해준다.
여러개의 파일들을 한꺼번에 업데이트 할 수 도 있는데, 이는, redeploy 옵션뒤에, 다음과 같이 파일명들을 정의해주면 된다.
java weblogic.Deployer ?adminurl url ?user user ?password password ?name myapp ?redeploy myejb/foo.class mywar anotherejb
위의 명령의 경우에는 myapp의 myejb jar의 foo.class, 그리고 mywar.war 웹애플리케이션과, anotherejb EJB 패키지를 redeploy를 해준다. 이때, 이 3개의 파일로 인해서 redeploy를 해줘야하는 dependency 관계가 있는 다른 컴포넌트들도 자동으로 redeploy를 해주게 된다.
5. Programming Tip
이번 기사를 정리하는 기분으로, 한가지 Class Loader의 팁을 소개한다.
해당 Class가 어느 Class Loader를 통해서 Loading 됐는지를 쉽게알 수가 있다.
해당 CLASS에 다음과 같은 코드를 삽입하면 된다.
ClassLoader loader = null;
loader = this.getClass().getClassLoader();
System.out.println("This class is :"+this.getClass().getName());
while(loader != null){
System.out.println(loader.getClass().getName());
loader = loader.getParent();
}//while
(EJB Class 안에 넣고 이 코드를 수행했을때 수행결과는 다음과 같다. WLS6.1 기준.)
This class is :com.bea.examples.simpleEJB.AccountManagerEJB_fsrjh9_Impl
weblogic.utils.classloaders.GenericClassLoader
sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$ExtClassLoader
[참고 자료]
http://java.sun.com/docs/books/tutorial/ext/basics/load.html
http://e-docs.bea.com/wls/docs61/ejb/EJB_deployover.html#1011066
http://e-docs.bea.com/wls/docs81/programming/classloading.html#1083313
http://dev2dev.bea.com/articles/musser.jsp