Microsoft Word - Enterprise Java Beans.doc

Similar documents
歯Writing_Enterprise_Applications_2_JunoYoon.PDF

목차 JEUS EJB Session Bean가이드 stateful session bean stateful sample 가이드 sample source 결과확인 http session에

교육2 ? 그림

Network Programming

歯Writing_Enterprise_Applications_7_JunoYoon.PDF

작성자 : 김성박\(삼성 SDS 멀티캠퍼스 전임강사\)

다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp");

쉽게 풀어쓴 C 프로그래밊

2장 변수와 프로시저 작성하기

14-Servlet

rmi_박준용_final.PDF

Chap12

Spring Boot/JDBC JdbcTemplate/CRUD 예제

(Microsoft PowerPoint - Chapter17 RMI.ppt [\310\243\310\257 \270\360\265\345])

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc

JavaGeneralProgramming.PDF

PowerPoint Presentation

Intro to Servlet, EJB, JSP, WS

JAVA PROGRAMMING 실습 08.다형성

J2EE Concepts

Interstage5 SOAP서비스 설정 가이드

Connection 8 22 UniSQLConnection / / 9 3 UniSQL OID SET

10.ppt

혼자서일을다하는 JSP. 이젠일을 Servlet 과나눠서한다. JSP와서블릿의표현적인차이 - JSP는 <html> 내에서자바를사용할수있는수단을제공한다. - 서블릿은자바내에서 <html> 을작성할수있는수단을제공한다. - JSP나서블릿으로만웹페이지를작성하면자바와다양한코드가

No Slide Title

PowerPoint Presentation

I T C o t e n s P r o v i d e r h t t p : / / w w w. h a n b i t b o o k. c o. k r

gnu-lee-oop-kor-lec06-3-chap7

q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2

PowerPoint 프레젠테이션

JAVA Bean & Session - Cookie

<4D F736F F F696E74202D20C1A63038C0E520C5ACB7A1BDBABFCD20B0B4C3BC4928B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

JAVA 프로그래밍실습 실습 1) 실습목표 - 메소드개념이해하기 - 매개변수이해하기 - 새메소드만들기 - Math 클래스의기존메소드이용하기 ( ) 문제 - 직사각형모양의땅이있다. 이땅의둘레, 면적과대각

Spring Data JPA Many To Many 양방향 관계 예제

뇌를 자극하는 JSP & Servlet 슬라이드

PowerPoint Presentation

PowerPoint Presentation

@OneToOne(cascade = = "addr_id") private Addr addr; public Emp(String ename, Addr addr) { this.ename = ename; this.a

歯JavaExceptionHandling.PDF

제11장 프로세스와 쓰레드

Microsoft PowerPoint - GUI _DB연동.ppt [호환 모드]

JUNIT 실습및발표

Microsoft PowerPoint - Java7.pptx

JAVA PROGRAMMING 실습 09. 예외처리

Microsoft PowerPoint - RMI.ppt

ISP and CodeVisionAVR C Compiler.hwp

서블릿의라이프사이클 뇌를자극하는 JSP & Servlet

PowerPoint Presentation

Microsoft PowerPoint - 18-DataSource.ppt

12-file.key

Design Issues

API STORE 키발급및 API 사용가이드 Document Information 문서명 : API STORE 언어별 Client 사용가이드작성자 : 작성일 : 업무영역 : 버전 : 1 st Draft. 서브시스템 : 문서번호 : 단계 : Docum

PowerPoint Presentation

슬라이드 1

PowerPoint Template

슬라이드 1

본 강의에 들어가기 전

목차 BUG DEQUEUE 의 WAIT TIME 이 1 초미만인경우, 설정한시간만큼대기하지않는문제가있습니다... 3 BUG [qp-select-pvo] group by 표현식에있는컬럼을참조하는집합연산이존재하지않으면결괏값오류가발생할수있습니다... 4

Data Provisioning Services for mobile clients

JAVA PROGRAMMING 실습 05. 객체의 활용

쉽게 풀어쓴 C 프로그래밍

Microsoft PowerPoint - Supplement-03-TCP Programming.ppt [호환 모드]

<4D F736F F F696E74202D20C1A63139C0E520B9E8C4A120B0FCB8AEC0DA28B0ADC0C729205BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

슬라이드 1

슬라이드 1

쉽게

- JPA를사용하는경우의스프링설정파일에다음을기술한다. <bean id="entitymanagerfactory" class="org.springframework.orm.jpa.localentitymanagerfactorybean" p:persistenceunitname=

C++ Programming

Microsoft PowerPoint - 04-UDP Programming.ppt

1. 자바프로그램기초 및개발환경 2 장 & 3 장. 자바개발도구 충남대학교 컴퓨터공학과

중간고사

Microsoft PowerPoint - 03-TCP Programming.ppt

Windows 8에서 BioStar 1 설치하기

PowerPoint 프레젠테이션

파일로입출력하기II - 파일출력클래스중에는데이터를일정한형태로출력하는기능을가지고있다. - PrintWriter와 PrintStream을사용해서원하는형태로출력할수있다. - PrintStream은구버전으로가능하면 PrintWriter 클래스를사용한다. PrintWriter

Install stm32cubemx and st-link utility

FileMaker ODBC and JDBC Guide

Spring Boot

PowerPoint 프레젠테이션

Cluster management software

PowerPoint Presentation

교육자료

Eclipse 와 Firefox 를이용한 Javascript 개발 발표자 : 문경대 11 년 10 월 26 일수요일

PowerPoint 프레젠테이션

쉽게 풀어쓴 C 프로그래밍

02 C h a p t e r Java

View Licenses and Services (customer)

(8) getpi() 함수는정적함수이므로 main() 에서호출할수있다. (9) class Circle private double radius; static final double PI= ; // PI 이름으로 로초기화된정적상수 public

Microsoft Word - windows server 2003 수동설치_non pro support_.doc

.

SQL Developer Connect to TimesTen 유니원아이앤씨 DB 기술지원팀 2010 년 07 월 28 일 문서정보 프로젝트명 SQL Developer Connect to TimesTen 서브시스템명 버전 1.0 문서명 작성일 작성자

(Microsoft PowerPoint - java1-lecture11.ppt [\310\243\310\257 \270\360\265\345])

C# Programming Guide - Types

<4D F736F F F696E74202D20B5A5C0CCC5CDBAA3C0CCBDBA5F3130C1D6C2F75F31C2F7BDC32E >

웹연동 } 웹 (Web) 환경에서데이터베이스시스템을연동하는방법은다음과같다 } Server Client 구조의통신 (2-Tier) } Server Middleware Client 구조의통신 (3-Tier) 2

PowerPoint Presentation

gnu-lee-oop-kor-lec10-1-chap10

개발문서 Oracle - Clob

아이콘의 정의 본 사용자 설명서에서는 다음 아이콘을 사용합니다. 참고 참고는 발생할 수 있는 상황에 대처하는 방법을 알려 주거나 다른 기능과 함께 작동하는 방법에 대한 요령을 제공합니다. 상표 Brother 로고는 Brother Industries, Ltd.의 등록 상

Transcription:

#1 작성자 : 김성박 ( 삼성 SDS 멀티캠퍼스전임강사 ) email : urstory@nownuri.net homepage : http://sunny.sarang.net - 해당문서는 http://sunny.sarang.net JAVA강좌란 에서배포합니다. 문서는계속버전업될수있습니다. 필자의허락없이수정, 삭제, 재작성, 이동등을할수없습니다. - 잘못된부분을발견하였거나, 추가할사항이있다면작성자에게메일보내주신다면감사하겠습니다. - 해당문서는 JAVA 기본, JSP, Servlet, RMI 등의기술에대하여알고있는분을대상으로합니다. 1. EJB 란무엇인가? EJB는 Sun Microsystem사 ( 이하 SUN) 에서제안한, 서버컴퓨터에서실행되는자바컴포넌트모델이며, EJB는 ORACLE, IBM 등의여러회사와수많은개발자들이참여하여만드는공통된표준규칙을말합니다. EJB를공부하고자하는분들에게는이렇게말합니다. EJB는자바의종합예술과같은분야이다. 그러므로무턱대고 EJB에도전하다가는좌절할수밖에없다고말합니다. 그이유는 EJB에는수많은자바기술이들어가있기때문입니다. 보통우리가말하는 EJB프로그래밍이라는것은사실, EJB 프로그래밍만을의미하지않습니다. 무슨소리지요? 라고물어볼분을위하여설명하자면, SUN에서는기업용에플리케이션을개발하기위한 API의묶음인 J2EE를발표합니다. J2EE를구성하고있는것들을보면, 핵심으로 JSP, 서블릿, EJB(Enterprise Java Beans) 등이있으며, 데이터베이스를위한 JDBC, 디렉토리를위한 JNDI(Java Naming and Directory Interface), 트랜잭션을위한 JTA(Java Transaction API), 메시징을위한 JMS(Java Message Service), 이메일시스템을위한 JavaMail 그리고 CORBA접속을위한 Java IDL(Interface Definition Language) 로구성되는것을알수있습니다. 1

이렇게여러가지 API로구성된 J2EE의가장중요한기능은비즈니스로직을담당하고있는 EJB에있다고말해도과언이아닙니다. 이렇게 EJB 기능을포함하고있는 J2EE와같은 API의묶음을 EJB 컨테이너라고도말을합니다. J2EE 자체만보아도훌륭한 EJB 컨테이너지만, 썬사에서는 J2EE를상업적용도로사용못하도록라이센스에표시해놓았습니다. 그러므로, 실제로상용으로이용할려면 J2EE가아닌다른 EJB 컨테이너를이용해야합니다. EJB는 JAVA로작성되어지기때문에, J2EE에서작성된프로그램은수정하지않고다른 EJB 컨테이너에서동작할수있습니다. 그렇게될수있는이유는여러종류의 EJB컨테이너가모두 EJB 스펙을준수하고있기때문입니다. J2EE 를구성하고있는기술들은각각하나씩보아도초보자들입장으로는어려울것입니다. 또한 J2EE의스펙자체가복잡하기때문에, J2EE를어렵다고말을합니다. 하지만반대로이러한스펙을잘알고있는사람이라면, 그스펙대로프로그래밍을작성하면쉽게프로그래밍을짤수도있다는말이기도합니다. 그러므로 J2EE를쉽게익히기위하여는스펙이어떻게되는지정확하게이해햐여야하는것입니다. 그런데, 여기에서스펙을이해할수있으려면자바의기본지식이필요합니다. 자바의기본지식으로는 JAVA 기초, JSP, Servlet, RMI등에대하여알고, 객체지향에대한확실한이해가있을경우 J2EE를이해할수있을것입니다. 특히 JAVA기초부분에서 Interface의기능과특징에대하여자유자재로쓸수있어야만됩니다. 그러한내용은본문서에서다루지않겠습니다. 참고 : EJB 와 JAVA Bean은모두 class이긴하지만개념자체는틀립니다. JAVA Beans는보통비쥬얼한개발환경에서재사용되기위한컴포넌트모델이며, EJB는미션크리티컬한서버쪽에서기업용애플리케이션에서사용될수있는분산객체를말합니다. ( 좀더여러가지로비교할수있지만생략합니다. ) 2. EJB 를왜사용하는가? EJB를사용하는이유는여러가지장점이있기때문일것입니다. EJB는작은작업을처리할때사용하지않습니다. 작은작업을웹상으로구현할려면 jsp나 servlet 만이용하고도쉽게작성할수있습니다. EJB는중요한기능을처리하는기업에서사용되도록작성되는것입니다. 2

a. 비즈니스관점으로본장점 - 빠른개발속도 : EJB가동작하는 EJB컨테이너는실제로개발자가비즈니스관련프로그램을작성하는데가장중요한트랜잭션, 보안, 패일오버등을자동으로처리해주기때문에오류가발생할가능성이적어집니다. 그러므로빠른시간안에개발될수있습니다 - 작업할내용의감소 : 앞에서말한장점과같은의미로, 개발자가직접작성해야될내용이이미구현되어있으므로, 직접모두구현하는것보다작업할내용이감소될수있습니다. - 코드재사용성증가 : EJB 자체가비즈니스단위로재사용되도록만들어지기때문에코드자체의재사용률이높아집니다. - 전문가의필요성감소 : 실제가장작성하기어려운부분인트랜잭션, 보안, 패일오보등의기능을자동으로처리해주기때문에스펙을확실하게이해하고있다면전문개발자가아니라도쉽게개발할수있습니다. b. 개발자관점의장점 A. 컴포넌트아키텍처도입 B. 트랜잭션보장 C. 이식성 D. 확장성 E. 유연성 위와같은장점이있으나단점은 EJB 컨테이너를구입해야하는비용적인부분과스펙자체가어렵다는것이있습니다. 3. EJB 아키택처의목표 EJB는다음과같은목표로만들어졌습니다. EJB가어떤목표를가지고있는지확실하게파악하고있어야, 알맞게 EJB를이용할수있을것입니다. - JAVA 언어로작성되는분산객체형태의비즈니스로직을구현하는애플리케이션을개발하기위한표준컴포넌트이다. - 한가지툴에종속적인것이아니라, 여러가지툴들을이용할수있으며툴들을통하여컴포넌트를조합하여애플리케이션을작성할수있다. - 트랜잭션, 보안, 패일오버, 멀티쓰레드, 커넥션풀링등과같은복잡하고어려운기능들을개발자가몰라도쉽게작성할수있다. - EJB는한번작성된후재컴파일없이재사용할수있다. 3

- EJB 컴포넌트를개발하는단계와 EJB컨테이너에배치하고실행하는단계는명확하게구분된다. - EJB 애플리케이션기존의 JAVA API등을이용할수있다. - 다른언어로개발된컴포넌트와함께동작할수있다. - CORBA 프로토콜을수용하며이용할수있다. 위와같은기능들은 EJB 아키텍처가지켜야할목적입니다. 반대로프로젝트에 EJB를사용할것인가? 라고결정할때개발자들이염두에둘부분이기도합니다. 4. EJB 의종류 EJB는세션빈 (Session Bean) 과엔티티빈 (Entity Bean) 으로구분됩니다. 각각의사용용도는아래와같습니다. 세션빈 실제로직을담당하는빈입니다. 예를들자면, 물품검색, 물품주문, 물품결재등의처리를해주는기능을컴포넌트화한것을의미합니다. - 실제로세션빈은상태를유지할수있는상태유지세션빈과무상태세션빈으로나뉩니다. 엔티티빈 일반적으로데이터베이스의테이블을의미합니다. 즉자료를나타내는집합을나타내는객체입니다. - 엔티티빈은 EJB 컨테이너가자동으로데이터베이스를관리하는 CMP(Container Managed Persistence) 엔티티빈과빈자체가데이터베이스를관리하는 BMP(Bean Managed Persistence) 엔티티빈으로나뉘어집니다. 5. EJB 개발순서 a. 홈인터페이스와리모트인터페이스의작성 - 홈인터페이스 (Home Interface) : 엔터프라이즈빈을클라이언트가사용할수있도록생성하고찾아주는기능 - 리모트인터페이스 (Remote Interface) : 엔터프라이즈빈이클라이언트에게제공하는서비스를메소드들로선언한인터페이스 b. Bean Class의작성 - 엔터프라이즈빈이실제로처리하는작업을내부코드로구체적으로작성하는클래스입니다. Remote Interface에서선언된비즈니스메소드를실제로구현해줘야합니다. 개발자입장으로보면가장할일이많은작업이기도합니다. - Bean Class를작성할때는 Remote Interface에서정의된메소드를실제로구현해주는것외에도 EJB 컨테이너의규약메소드를정의해야합니다. 규약메 4

소드는 EJB 컨테이너가특정한순간에호출하는메소드들로아주중요한기능을처리합니다. c. 디플로이먼트디스크립터 (Deployment Descriptor) 작성 - 디플로이먼트디스크립터는 XML파일로엔터프라이즈빈의이름, 트랜잭션처리방법, 보안, 자원관리방법등의정보를작성한파일 d. 엔터프라이즈빈과관련된모든클레스와디플로이먼트디스크립터의패키지화 (jar로묶음 ) 참고 : 위에서 c. d. 를합쳐서 디플로이먼트 라고합니다. e. 패키지를 EJB 컨테이너에설치함 - 참고로 EJB 컨테이너안에 EJB패키지를설치하는개발자를배치자 (deployer) 라고호칭합니다. - 컨테이너에설치하는과정을 플러그인 이라고말하며, 플러그인되는과정에서리모트인터페이스를구현한클래스, 홈인터페이스를구현한클래스, 각각의 RMI 스텁, 스켈레톤클래스가자동으로생성됩니다. 6. J2EE 의설치 SUN사에서제공하여주는 EJB 컨테이너인 J2EE를설치하도록하겠습니다. a. http://www.javasoft.com/j2ee/ 에서 J2EE 소프트웨어를다운로드받습니다. 윈도우용의경우파일명은 j2sdkee-1_3_01-win.exe 입니다. b. j2sdkee-1_3_01-win.exe를실행합니다. 아래의그림과같은방법으로설치합니다. 보통 next만누르면됩니다. 5

그림 1 환영메시지 그림 2 라이센스동의 6

그림 3 설치디렉토리지정 : 기본은 c: j2sdkee1.3 그림 4 설치프로그램선택 7

그림 5 설치진행화면 그림 6 설치종료화면 8

c. 설치가끝나면제어판의시스템등록정보에서환경변수를아래와같이설정합니다. - JAVA_HOME : jdk 설치된디렉토리입니다. 예 ) c: jdk1.3 - J2EE_HOME : J2EE가설치된디렉토리입니다. 예 ) c: j2sdkee1.3 - PATH : jdk와 J2EE의프로그램을실행할수있도록 path에추가합니다. 예 ) PATH=.;c: jdk1.3 bin;c: j2sdkee1.3 bin - CLASSPATH : J2EE의 클래스를 추가합니다. 예 ) set CLASSPATH=.;c: j2sdkee1.3 lib j2ee.jar; 참고. J2EE SDK 의중요한도구들 a. J2EE 서버중요옵션들 -verbose : J2EE서버를구동한후로그출력 -version : 현재 J2EE 버전출력 -stop : J2EE 서버중지 -singlevm : 하나의프로세스로 EJB컨테이너실행, 디플로이 -multivm : 배치된각각의애플리케이션에대하추가로가상머신이실행된다. 속도는빨라지지만메모리자원을많이사용하게됨 그림 7 j2ee 를 command 창에서실행한모습버전이 1.3_01 이라는것을알수있다. b. Deploytool 애플리케이션배치툴로 J2EE의컴포넌트나애플리케이션을작성, 배치할때사용됩니다. 실행은 deploytool.exe 파일을실행하면됩니다 9

그림 8 deploytool 을실행한모습으로기본적으로 GUI 를지원한다. c. CloudScape - J2EE에기본적으로포함되어있는데이터베이스서버 d. KeyTool - 공개키와개인키를생성하여 X.509 self-signed 인증서를생성하여주는도구입니다. e. Packager - J2EE의컴포넌트를패키지화할때이용됩니다. 해당파일을이용하여엔터프라이즈빈 file, 웹애플리케이션 WAR file, 애플리케이션클라이언트 JAR file, J2EE 애플리케이션 EAR file, 자원어댑터 (adapter) RAR file 등을만들수있습니다. f. Realm Tool - J2EE 사용자, 파일을추가삭제할수있는툴 g. RunClient - 애플리케이션클라이언트를실행하기위한툴 10

h. verifier - 컴포넌트의유효성을검사하는툴 i. CleanUp - J2EE 서버에배치된모든애플리케이션을삭제하는툴 7. 무상태세션빈만들기 실제로간단한무상태세션빈을만들어보도록하겠습니다. 5. EJB 개발순서 를참고하시기바랍니다. 어떤프로그램이든지 hello 를찍지않고서야.. 넘어갈수가없군요. a. 홈인터페이스의작성홈인터페이스는기본적으로 java.rmi 패키지와 javax.ejb 패키지를임포트하여야하며 javax.ejb.ejbhome은상속받아구현해줍니다. 인터페이스의이름은홈인터페이스인것을쉽게알아보도록하여주기위하여 Home이라는이름을보통붙여서작성합니다. 또한 create메소드를작성하여주는데무상태세션빈의경우인자가없는메소드를선언합니다. create메소드가리턴하여주는값은리모트인터페이스가됩니다. EJB컨테이너가트랜잭션, 패일오버등을자동으로처리해주기위하여는직접객체를생성하면안되기때문에 create 메소드를이용하여 interface를리턴하는것입니다. create 메소드는 CreateException과 RemoteException을 throws 할수있도록작성되야합니다. HelloHome.java 시작 ------------------------------------- import java.rmi.*; import javax.ejb.*; public interface HelloHome extends EJBHome{ public Hello create() throws CreateException, RemoteException; HelloHome.java 끝 --------------------------------------- b. 리모트인터페이스의작성리모트인터페이스는클라이언트가세션빈의메소드를이용할수있도록제공되는것입니다. 리모트인터페이스와마찬가지로 java.rmi 패키지와 javax.ejb 패키지를구현해주었습니다. 파일명은리모트인터페이스에서 create 메소드가리턴하는이름과같아야합니다. 여기에서는간단히문자열을지정한후, 지정된값을리턴할수있는기능을가진두개의메소드를선언하였습니다. 또한각각의메소드는 RemoteException 을 11

throws 해야합니다. Hello.java 시작 ----------------------------------------- import java.rmi.*; import javax.ejb.*; public interface Hello extends EJBObject{ public void sethello(string txt) throws RemoteException; public String gethello() throws RemoteException; Hello.java 끝 ------------------------------------------ c. 빈클래스작성빈클래스는실제로리모트인터페이스를구현해주는클래스입니다. 개발자에게는가장중요한부분이며, 세션빈일경우 javax.ejb.sessionbean을구현해줘야합니다. 또한 EJB컨테이너규약메소드도구현해줘야하는데, HelloEJB.java에서는선언만해주었고실제로구현하지는않았습니다. HelloEJB.java 시작 ---------------------------------------- import java.util.*; import javax.ejb.*; public class HelloEJB implements SessionBean{ public String txt; public void sethello(string txt){ this.txt = txt; public String gethello(){ return txt; public HelloEJB(){ public void ejbcreate(){ public void ejbremove(){ public void ejbactivate(){ public void ejbpassivate(){ 12

public void setsessioncontext(sessioncontext sc){ HelloEJB.java 끝 ----------------------------------- d. 홈인터페이스, 리모트인터페이스그리고빈클래스를컴파일합니다. J2EE의설치와환경변수를제대로설정하였다면아래와같이도스창에서실행합니다. ( 물론파일이있는디렉토리여야겠지요? ) 그림 9 홈, 리모트인터페이스, 빈클래스의컴파일 e. 디플로이먼트를합니다. 먼저 J2EE의서버를실행한후 deploytool을실행합니다. 그림을보고차례대로따라하도록합시다. 13

그림 10 j2ee 서버를 verbose 옵션을주어실행 그림 11 deploytool 을실행한모습 14

그림 12 File 메뉴에서 Application 을선택합니다. 그림 13 다이얼로그창이뜨면저장될어플리케이션파일이름을지정합니다. 예제에서는 Hello.ear 라고주었습니다. 15

그림 14 새로운어플리케이션이작성이되면왼쪽메뉴에 Hello 라는이름의어플리케이션이추가된것을알수있습니다. 16

그림 15 엔터프라이즈빈을새롭게생성합니다.. 그림 16 엔터프라이즈생성을누르면정보가나옵니다. 잘읽고나서 Next 를누릅니다. 17

그림 17 그림과같이이름을지정합니다. 그후에 Edit 버튼을클릭합니다. 그림 18 Hello.jar 파일안에포함될 class가담긴디렉토리를상단트리에서선택한후 add 버튼을클릭합니다.. 18

그림 19 디렉토리안에포함된내용이 jar 파일에추가되는것을비쥬얼하게알수있습니다. 이때디렉토리안까지들어가 HelloEjb.class HelloHome.class Hello.class 만추가해도됩니다. ok 버튼을클릭합니다. 그림 20 화면상단에보면 jar 파일안에들어갈자료목록이보입니다. Next버튼을클릭합니다. 19

그림 21 파일들에대한설정하는창입니다. 그림 22) 와같이설정하여줍니다. 그림 22 무상태새션빈이므로 Stateless 를선택하였으며빈클레스, 홈인터페이스, 리모트인터페이스를지정합니다. Next 버튼을클릭합니다. 20

그림 23 무상태세션빈에서는보통이용하지않는부분입니다. Finish버튼을클릭하여작업을종료합니다. 그림 24 Hello Application에 Hello.jar 가포함되어있고 EJB 빈이추가된것을알수있습니다. 21

그림 25 Hello Application을선택한후 JNDI Names 항목에서 JNDI name을설정합니다. 해당이름은 JNDI를이용하여빈을찾을때사용되는중요한이름입니다. 그림 26 이제모든설정이끝났습니다. plugin 을하기위하여 tools 메뉴의 Deploy를선택합니다. 22

그림 27 Object to Deploy에서는 Hello를선택한후 Return Client Jar 옵션을체크합니다. 해당 jar 파일은 client를실행할때필요한내용이될것입니다. next 버튼을클릭합니다. 그림 28 JNDI Name 을지정하는항목입니다. 이미지정하였으니 Next 버튼을클릭합니다. 23

그림 29 Deploy 될준비가끝났습니다. Finish 버튼을클릭합니다. 그림 30 디플로이먼트작업이진행됩니다. 이부분에서실폐하는경우가많습니다. 물론잘못작성된경우겠지요? 24

그림 31 디플로이작업이끝난화면입니다. ok 버튼을클릭합니다. 25

그림 32 왼쪽트리메뉴에보면 Hello 라는내용이 deploy 된것을알수있습니다. 26

그림 33 그림32) 까지작업을하고클라이언트에서엔터프라이즈빈을이용할려고하면 Permission Exception이발생할것입니다. 그림33) 처럼 HelloEJB 엔터프라이즈빈을선택한후 Security탭에서 Deployment Settings 를클릭합니다. 그림 34 원래는 Password로지정되어있을것입니다만, Support Client Choice로바꿉니다. Deploy 되어있는 EJB 를해제하고다시 Deploy시킵니다. 27

f. EJB 클라이언트의작성 실제로 EJB컨테이너에있는 HelloEJB객체를이용하는간단한어플리케이션입니다. 설명은소스의주석문으로대신합니다. HelloClient.java 시작 -------------------------------------------- import javax.naming.*; import javax.rmi.portableremoteobject; public class HelloClient{ public static void main(string args[]){ try{ Context initial = new InitialContext(); // 세션빈의객체레퍼런스를가지고옵니다. Object obj = initial.lookup("myhello"); // 홈객체레퍼런스를가지고옵니다. HelloHome home = (HelloHome)PortableRemoteObject.narrow(obj, HelloHome.class); if(home == null) System.out.println("null -_-;"); // EJB 객체를생성합니다. Hello h1 = home.create(); Hello h2 = home.create(); // 비지니스메소드호출 h1.sethello(" 안녕하세요. EJB의세계에온것을환영해요."); System.out.println(" 메아리 :" + h1.gethello()); h2.sethello(" 무상태세션빈을처음연습합니다."); System.out.println(" 메아리2 :" + h2.gethello()); catch(exception e){ e.printstacktrace(); HelloClient.java 끝 ---------------------------------------------- 28

그림 35 첫번째문장은컴파일하는방법입니다. classpath 옵션을잘보면, DeployTool이자동으로만들어준 HelloClient.jar 를지정한것을알수있습니다. 두번째문장은 HelloClient 를실제로실행하는것입니다. 결과가여러분들이예상하는것처럼나왔는지요? HelloClient.java 에서다음과같이한줄을추가한후에결과를확인하면어떤값이출력될까요? h2.sethello(" 무상태세션빈을처음연습합니다."); System.out.println(" 메아리2 :" + h2.gethello()); System.out.println(" 메아리2 :" + h1.gethello()); 진한글씨로된부분을추가한후다시컴파일하여실행하여봅시다. 무상태빈의특징에대하여확실히알수있을것입니다. ( 궁금한분은결과를실행해보시기바랍니다. ) 8. 무상태세션빈과 JSP 이번에는간단한덧셈을계산하여주는 EJB 와 jsp 의연동에대하여알아보도록하겠습니다. 차례대로따라하면서익혀보시기바랍니다. 29

a. Home Interface 의작성 AddHome.java 시작 ------------------------------------------- import java.rmi.*; import javax.ejb.*; public interface AddHome extends EJBHome{ public Add create() throws CreateException, RemoteException; AddHome.java 끝 --------------------------------------------- b. Remote Interface 의작성 Add.java 시작------------------------------------------------- import java.rmi.*; import javax.ejb.*; public interface Add extends EJBObject{ public int getadd(int num1, int num2) throws RemoteException; Add.java 끝 -------------------------------------------------- c. Bean class 의작성 AddEJB.java 시작 --------------------------------------------- import java.util.*; import javax.ejb.*; public class AddEJB implements SessionBean{ public int getadd(int num1, int num2){ return num1 + num2; public AddEJB(){ public void ejbcreate(){ 30

public void ejbremove(){ public void ejbactivate(){ public void ejbpassivate(){ public void setsessioncontext(sessioncontext sc){ AddEJB.java 끝 ----------------------------------------------- 그림 36 홈인터페이스, 리모트인터페이스, 빈클래스를함께컴파일합니다. d. 디플로이먼트하기 앞의예제와같은방법으로현재만들어진 class들을디플로이먼트합니다. 그림을잘보고따라하시기바랍니다. 31

그림 37 j2ee 서버를실행합니다. 그림 38 deploytool 실행한후 File new Application 을선택한후 add.ear 파일을생성합니다. 32

그림 39 File-new-Enterprise Bean 항목을선택한후, Add Application엔터프라이즈빈을추가할내용을선택합니다. 그림 40 컴파일된 Add, AddEJB, AddHome 클래스를선택한화면입니다. 33

그림 41 무상태세션빈이므로 Stateless 를선택한후각각의값을그림과같이지정합니다. 그림 42 엔터프라이즈빈이추가가된것을확인하고 Security 탭을그림과같이선택합니다. 34

그림 43 보안설정을 Support Client Choice 로변경합니다. 그림 44 Tools- deploy 를선택한후에그림과같이셋팅합니다. 35

그림 45 JNDI Name 을 MyAdd 로선택합니다. 그림 46 finish 버튼을누릅니다. 36

그림 47 deploy 되는과정이그래프와함께표시됩니다. 그림 48 Deploy 가성공한화면입니다. 이제 Add EJB 를사용할수있게되었습니다. 37

그림 49 서버에설치된 Add 객체입니다. e. HTML파일과 JSP 파일의작성실제로 EJB객체를이용하는 HTML과 JSP파일을작성합니다. 설명은주석문으로대신합니다. addform.html 시작 --------------------------------------------- <html> <head> <title>ejb 와덧셈 </title> </head> <body> <! post 방식으로 add.jsp 를호출합니다. add.jsp 는 EJB객체를이용하는 jsp 파일입니다. > <form method="post" action="add.jsp"> 값 1: <input type="text" name="num1"><br> 값 2: <input type="text" name="num2"><br> 38

<input type="submit" value=" 계산 "> </form> </body> </html> addform.html 끝 ------------------------------------------------ add.jsp 에서중요한점은홈인터페이스와리모트인터페이스를 import 하엿다는것입니다. 패키지로컴파일하지않았지만반드시 import 하여야 jsp 파일이서블릿으로변환되면서오류를발생시키지않습니다. add.jsp 시작 ------------------------------------------------- <%@ page contenttype = "text/html; charset=euc-kr" %> <%@page import="javax.naming.*" %> <%@page import="javax.rmi.portableremoteobject" %> <%@page import="addhome" %> <%@page import="add" %> <html> <head> <title>ejb 와덧셈 </title> </head> <body> <% /* addform.html로부터 2개의문자열로구성된숫자값을전달받아 Integer 클래스를이용하여정수화하는부분입니다. */ int num1 = 0; int num2 = 0; try{ num1 = Integer.parseInt(request.getParameter("num1")); catch(exception e){ num1 = 0; try{ num2 = Integer.parseInt(request.getParameter("num2")); catch(exception e){ 39

num2 = 0; Context initial = new InitialContext(); // 세션빈의객체레퍼런스를가지고옵니다. Object obj = initial.lookup("myadd"); // 홈객체레퍼런스를가지고옵니다. AddHome home = (AddHome)PortableRemoteObject.narrow(obj, AddHome.class); // EJB 객체를생성합니다. Add a1 = home.create(); out.println(" 결과값 :" + a1.getadd(num1, num2)); %> </body> add.jsp 끝 --------------------------------------------------- f. Web Componenet 만들기 (WAR 파일생성 ) EJB를실제로이용하는 JSP파일과값을입력받는 HTML을포함하는 Web Componenet 를작성하도록하겠습니다. 그림을보고잘따라하세요. 그림 50 File New Web Component 를선택합니다. 40

그림 51 설명을잘읽은후 Next 버튼을클릭합니다. 그림 52 그림과같이설정한후 Edit 버튼을클릭합니다. 41

그림 53 추가할 html 과 jsp 를선택한후 Add 버튼을클릭합니다. 그림 54 확인후 Next 버튼을클릭합니다. 42

그림 55 jsp 파일로구성되어있으므로 jsp 를선택한후 Next 버튼을클릭합니다. 그림 56 그림과같이설정한후 Next 버튼을클릭합니다. 43

그림 57 Next 버튼클릭. 그림 58 Next 버튼클릭 44

그림 59 Next 버튼클릭 그림 60 Next 버튼클릭 45

그림 61 Next 버튼클릭 그림 62 그림과같이설정후 Next 버튼을클릭합니다. 46

그림 63 Next 버튼을클릭합니다. 그림 64 Next 버튼을클릭 47

그림 65 Next 버튼을클릭 그림 66 Next 버튼을클릭 48

그림 67 Next버튼을클릭하면 WAR 파일이애플리케이션에추가가됩니다. 이제다시 deploy를실행하여갱신을합니다. 그림 68 Tool-Deploy 를선택한후그림과같이설정한후 Next 버튼을클릭합니다. 49

그림 69 Next 버튼을클릭합니다. 그림 70 Context Root 를지정합니다. 50

그림 71 Finish 버튼을누릅니다. 그림 72 Deploy 되는모습이그래프와함께보여집니다. 51

그림 73 Deploy 가끝났습니다. 이제 JSP 파일로테스트를합니다. 그림 74 기본적으로 J2EE의 JSP컨테이너는 8000번포트를이용합니다. URL을보면 ContextRoot가적혀있는것을볼수있습니다. 52

그림 75 입력된값을전달받아계산결과를출력합니다. JSP파일에서 EJB를이용하였습니다. 서블릿에서 EJB 객체를이용할려면어떻게해야할까요? 53

9. 상태유지세션빈 상태유지세션빈은무상태세션빈과는다르게한클라이언트에종속적인특징을가집니다. 그렇기때문에상태유지세션빈은클라이언트의생명주기와같은생명주기를가집니다. 또한상태유지세션빈은활성화와비활성화라는상태를가질수가있습니다. 상태유지세션빈은클라이언트와생명주기가같기때문에잘못사용하게되면자원을계속하여점유하고있을수가있습니다. 그렇기때문에사용되지않을때에는하드디스크등의저장장치에저장되어진상태로요청이올때까지비활성화상태로유지될수있습니다. 물론, 요청이있다면다시사용가능한상태인활성화상태로바뀌게됩니다. 이번단락에서는간단한계산기능을가지고있는상태유지세션빈을작성하는방법에대하여알아보도록하겠습니다. a. Home Interface의작성상태유지세션빈은정보를유지할수있기때문에 create 메소드에서인자를지정할수있습니다. CalculatorHome.java 시작-------------------------------------------- import java.io.serializable; import java.rmi.remoteexception; import javax.ejb.*; public interface CalculatorHome extends EJBHome{ Calculator create() throws RemoteException, CreateException; Calculator create(int number) throws RemoteException, CreateException; CalculatorHome.java 끝 -------------------------------------------- b. Remote Interface의작성상태유지세션빈의리모트인터페이스는무상태세션빈의리모트인터페이스와작성하는방법이동일합니다. Calculator.java 시작 ------------------------------------------------- import javax.ejb.*; import java.rmi.remoteexception; public interface Calculator extends EJBObject{ // 값을추가하는메소드 void add(int number) throws RemoteException; 54

void multiply(int number) throws RemoteException; void minus(int number) throws RemoteException; void divide(int number) throws RemoteException; int getnum() throws RemoteException; Calculator.java 끝 --------------------------------------------------- c. 빈클래스의작성무상태세션빈에서작성하지않았던 ejbcreate() 메소드를구현합니다. 또한활성화메소드 ejbactivate() 메소드와비활성화메소드 ejbpassivate() 메소드를구현합니다. CalculatorEJB.java 시작 ---------------------------------------------- import java.util.*; import javax.ejb.*; public class ENameEJB implements EntityBean{ public String id; public String txt; private EntityContext context; public void setname(string txt){ this.txt = txt; public String getname(){ return txt; public String ejbcreate(string id,string txt) throws CreateException{ if(id == null){ throw new CreateException("id is required."); this.id = id; this.txt = txt; return null; 55

public void setentitycontext(entitycontext context){ this.context = context; public void ejbactivate(){ id = (String)context.getPrimaryKey(); public void ejbpassivate(){ id = null; txt = null; public void ejbremove(){ public void ejbload(){ public void ejbstore(){ public void unsetentitycontext(){ public void ejbpostcreate(string id, String txt){ CalculatorEJB.java 끝 ------------------------------------------------ d. 디플로이먼트그림을보며잘따라하도록합시다. 그림 76 홈인터페이스, 리모트인터페이스, 빈클래스를함께컴파일합니다. 56

그림 77 deploytool 을실행합니다. 그림 78 File-New-Application 을선택한후그림과같이셋팅합니다. 57

그림 79 File new EnterpriseBean 을선택한후 Next 를누릅니다. 그림 80 그림과같이셋팅한후 Next 버튼을클릭합니다. 58

그림 81 상태유지빈이므로 stateful 을선택한후그림과같이셋팅합니다. 그림 82 Finish 버튼을클릭합니다. 59

그림 83 그림과같이 Application 과 Enterprise Bean 이등록된것을알수있습니다. 그림 84 Enterprise Bean 의 Security Tab 에서 Deployment Setting 을설택합니다. 60

그림 85 Client Authentication 을 Support Client Choice 로바꿉니다. 그림 86 Tools Deploy 를선택합니다. 61

그림 87 그림과같이셋팅한후 Next 버튼을클릭합니다. 그림 88 JNDI Name 을그림과같이셋팅한후 Next 버튼을클릭합니다. 62

그림 89 Finish 버튼을클릭합니다. 그림 90 Deploy 되는과정이그래프와함께보여집니다. 63

그림 91 디플로이가종료한화면입니다. 그림 92 Server 에 Calculator 가등록된것을알수있습니다. e. 상태유지세션빈을이용하는서블릿프로그래밍의작성과 WAR 작성상태유지세션빈은클라이언트와함께운명을같이합니다. 그렇기때문에 servlet 의 init 에서한번초기해준후맴버변수로지정을하여놓았습니다. CalculatorServlet.java 시작 ----------------------------------------- import java.io.*; 64

import javax.servlet.*; import javax.servlet.http.*; import javax.rmi.*; import javax.naming.*; import CalculatorHome; import Calculator; public class CalculatorServlet extends HttpServlet{ Calculator calc; public void init() throws ServletException{ try{ // Initialcontext 생성 InitialContext initial = new InitialContext(); // 세션빈의레퍼런스획득 Object obj = initial.lookup("mycalculator"); CalculatorHome home = (CalculatorHome)PortableRemoteObject.narrow(obj, CalculatorHome.class); // EJB 객체생성 calc = home.create(0); catch(exception e){ e.printstacktrace(); // end init public void doget(httpservletrequest req, HttpServletResponse res) throws ServletException, IOException{ String snum = req.getparameter("num"); String symbol = req.getparameter("symbol"); if(snum == null) snum = "0"; if(symbol == null) symbol ="+"; int inum = 0; try{ inum = Integer.parseInt(snum); catch(exception e){ 65

inum = 0; if(symbol.equals("*")){ calc.multiply(inum); else if(symbol.equals("+")){ calc.add(inum); else if(symbol.equals("-")){ calc.minus(inum); else if(symbol.equals("/")){ calc.divide(inum); int total = calc.getnum(); res.setcontenttype("text/html; charset=ksc5601"); PrintWriter out = res.getwriter(); out.println("<html><head><title> 계산기 </title></head><body>"); out.println("<h1> 계산기 </h1>"); out.println("<form method='get' action='calculatorservlet'>"); out.println(" 덧셈 <input type='radio' name='symbol' value='+' checked> "); out.println(" 뺄셈 <input type='radio' name='symbol' value='-'> "); out.println(" 곱셈 <input type='radio' name='symbol' value='*'> "); out.println(" 나눗셈 <input type='radio' name='symbol' value='/'> "); out.println(" 값 : <input type='text' name='num'>"); out.println("<input type='submit' value=' 계산하기 '><br>"); out.println(" 계산결과 : " + total); out.println("</form></body></html>"); // end doget CalculatorServlet.java 끝 ------------------------------------------ 66

아래의과정은해당서블릿을 WAR파일로만드는과정입니다. 그림을잘보고따라하도록합시다. 환경변수로 J2EE_CLASSPATH 를만들고오라클 JDBC드라이버인 classes12.zip 파일을지정하여줍니다. 그림 93 File New Web Component 를선택합니다. 그림 94 설명문을잘읽은후 Next 버튼을클릭합니다. 67

그림 95 WAR 파일에추가할 Servlet 파일을선택합니다. 그림 96 Servlet파일이추가된모습입니다. 그림과같이셋팅한후 Next버튼을클릭합니다. 68

그림 97 추가할내용이 Servlet 이므로 Servlet 을선택 Next 버튼을클릭합니다. 그림 98 그림과같이셋팅 Next 버튼을클릭합니다. 69

그림 99 Next 버튼을클릭합니다. 그림 100 Aliases 에서별명을등록합니다. 70

그림 101 Next 버튼을클릭합니다. 그림 102 Next 버튼을클릭합니다. 71

그림 103 Next 버튼을클릭합니다. 그림 104 그림과같이셋팅합니다. 72

그림 105 Next 버튼을클릭합니다. 그림 106 Next 버튼을클릭합니다. 73

그림 107 Next 버튼을클릭합니다. 그림 108 Next 버튼을클릭합니다. 74

그림 109 Finish 버튼을클릭합니다. 그림 110 그림과같이 WAR 파일이추가가된것을알수있습니다. 75

그림 111 추가된 WAR 파일과함께 deploy 를합니다. 그림 112 그림과같이셋팅한후 Next 버튼을클릭합니다. 76

그림 113 EJB 객체에대한 JNDI name 을지정합니다. 그림 114 ContextRoot 를그림과같이지정합니다. 77

그림 115 Finish 버튼을클릭합니다. 그림 116 디플로이과정이화면에보여집니다. 78

그림 117 디플로이결과화면입니다. f. 서블릿의실행 그림 118 서블릿을처음실행한모습입니다. 79

그림 119 메모리상에있는결과값과계속하여계산되는것을알수있습니다. 상태유지세션빈을 init에서이용하지않고 doget에서이용한다면결과는어떻게나올까요? 10. CMP(Container Managed Persistence) 엔티티빈 CMP 엔티티빈은 EJB 컨테이너가자동적으로데이터의영속성을유지시켜줍니다. 데이터베이스에서추가, 삭제, 변경등의작업등을자동으로처리해줍니다. CMP 엔티티빈을이용하게되면대부분의기능들을자동으로처리해주기때문에코드의길이가짧아지고개발이쉬워질수있습니다. 개발자는데이터베이스등에대한내용은신경쓰지않고비즈니스로직부분만신경을쓰면됩니다. 하지만단점은앞으로배울 BMP(Bean Managed Persistence) 에비해정교함이떨어지며, BMP보다성능상떨어질수있다는데있습니다. ( 여기에서알아두어야할것은 BMP를작성하는사람이자동으로관리해주는 CMP보다프로그래밍적인능력이뛰어난사람일경우입니다. ) 이제 CMP 엔티티빈을그림을보며따라해보도록합시다. 지금만드는엔티티빈은 id를가지고이름을관리하는것입니다. a. Home Interface의작성엔티티빈의 Home Interface는 javax.ejb.ejbhome을상속받으며, 0또는 1개이상의 create 메소드와하나이상의 find 메소드를정의해주어야합니다. 모든 create 메소드는 java.rmi.remoteexception과 javax.ejb.createexception을 throws 해줘야합니다. Home Interface의 create 메소드와 1:1로대응되도록빈클래스에서는 ejbcreate메소드를구현해줘야합니다. find 메소드는빈클래스에있는 find 메소드와 1:1로대응됩니다. find메소드는 80

java.rmi.remoteexception과 java.ejb.finderexception을 throws 해줘야합니다. ENameHome.java 시작 ------------------------------------------------- import java.util.*; import java.rmi.*; import javax.ejb.*; public interface ENameHome extends EJBHome{ public EName create(string id, String txt) throws RemoteException,CreateException; public EName findbyprimarykey(string id) throws FinderException, RemoteException; ENameHome.java 끝 --------------------------------------------- b. Remote Interface의작성 Remote Interface는 javax.ejb.ejbobject를반드시상속받아야하며, 모든비즈니스메소드를정의하여줍니다. 또한반드시 java.rmi.remoteexception을 throws 해주어야합니다. 또한전달되는값과리턴하는값은몽땅마샬링 ( 직렬화 ) 될수있는객체이어야합니다. 즉 RMI 호환형변수이어야한다는의미입니다. EName.java 시작 -------------------------------------------------- import javax.ejb.ejbobject; import java.rmi.remoteexception; public interface EName extends EJBObject{ public void setname(string txt) throws RemoteException; public String getname() throws RemoteException; EName.java 끝 ---------------------------------------------------- c. Bean Class의작성 ENameEJB.java 에서보면아래와같은내용이있습니다. public String id; public String txt; 해당변수들은단순한멤버변수들이아닙니다. 위에적혀져있는 id와 txt라는변수는자동으로데이터베이스에저장될필드로구성이됩니다. 실제로 Deploy Tool을실행하여디 81

플로이먼트를실행하는과정에서데이터베이스에저장될변수를정할수가있게됩니다. 이러한변수들을컨테이너관리필드 (Container-managed field) 라고부릅니다. 컨테이너관리필드로올수있는변수는자바기본자료형, 마샬링 ( 직렬화 ) 될수있는객체, 리모트인터페이스나홈인터페이스에대한레퍼런스만이올수있습니다. 디플로이먼트하는과정에서는반드시프라이머리키필드의역할을해주는변수가있어야합니다. CMP 엔티티빈은반드시 EntityBean을상속받아서구현해줘야하며, 홈인터페이스에서선언한 create와 find 메소드에 1:1로대응되도록메소드를구현해줘야합니다. 또한리모트인터페이스에서선언한메도드를구현해줘야합니다. 그리고파라미터가없는생성자를가지고있어야합니다. ENameEJB.java 시작 ------------------------------------------------- import java.util.*; import javax.ejb.*; public class ENameEJB implements EntityBean{ public String id; public String txt; private EntityContext context; public void setname(string txt){ this.txt = txt; public String getname(){ return txt; public String ejbcreate(string id,string txt) throws CreateException{ if(id == null){ throw new CreateException("id is required."); this.id = id; this.txt = txt; return null; 82

public void setentitycontext(entitycontext context){ this.context = context; public void ejbactivate(){ id = (String)context.getPrimaryKey(); public void ejbpassivate(){ id = null; txt = null; public void ejbremove(){ public void ejbload(){ public void ejbstore(){ public void unsetentitycontext(){ public void ejbpostcreate(string id, String txt){ ENameEJB.java 끝 --------------------------------------------------- d. 디플로이먼트하기 CMP 엔티티빈의디플로이먼트과정을그림을잘보면서따라하기바랍니다. 그림 120 홈인터페이스, 리모트인터페이스, 빈클래스를컴파일합니다. 83

그림 121 그림과같이 EName 이라는 Application 을생성합니다. 그림 122 그림과같이설정한후 Next 버튼을클릭합니다. 84

그림 123 그림과같이 Bean Type 을 Entity 로지정한후 Next 버튼을클릭합니다. 그림 124 CMP 1.0 방식을선택합니다. 그리고나서 id와 txt필드를선택합니다. Primary Key의역할을해주는 id 가 String 형이기때문에 Primary Key Class를 java.lang.string 으로변경해준후 Primary Key Field Name으로 id를지정하여줍니다. 85

그림 125 Finish 버튼을클릭합니다. 그림 126 그림과같이 Enterprise Bean 이추가된것을알수있습니다. 86

그림 127 Enterprise Bean 의보안설정을그림과같이바꿉니다. 그림 128 Tools Server Configuration 을선택합니다. 87

그림 129 오라클데이터베이스에연결하기위하여 JDBC Driver와 JNDI Name, JNDI URL 을설정합니다. 각각의값은 oracle.jdbc.driver.oracledriver, jdbc/oracle, jdbc:oracle:thin:@host:1521:sid 로선언합니다. 그림 130 Entity tab을누른후 Deployment Settings버튼을누르면그림과같은윈도우가뜹니다. Create table on deploy, Delete table on undeploy를 check 한후 Database Settings 버튼을클릭합니다. 88

그림 131 그림과같이화면이나오면그림과같이지정합니다. 이때 User Name과 Password는사용하는 Oracle계정의아이디와암호입니다. 그후에 Generate SQL Now 버튼을클릭합니다. 그림 132 그림과같이 SQL Generation complete 라는창이뜰것입니다. 89

그림 133 Method 부분을클릭해보면자동으로 SQL문장이만들어진것을알수있습니다. 이때여러분들은 table이름등을변경할수있습니다. 이때테이블명을유심히보면큰따옴표로묶여있는것을알수있습니다. ENameEJBTable 과 ENameEJBTable 은서로가다른이름의테이블입니다. 그림 134 Tools Deploy를선택하여 Deploy를합니다. 그림과같이셋팅한후 Next버튼을클릭합니다. 90

그림 135 Application에대한 JNDI Name을그림과같이설정한후 Next버튼을클릭합니다. 그림 136 Finish 버튼을클릭합니다. 91

그림 137 deploy 되는과정이그래프와함께보여집니다. 그림 138 deploy 가끝났습니다. 92

e. 클라이언트애플리케이션의작성 CMP 엔티티빈을테스트하기위한클라이언트프로그램을작성합니다. ENameClient.java 시작 ----------------------------------------------- import java.util.*; import javax.naming.*; import javax.rmi.*; import ENameHome; import EName; public class ENameClient{ public static void main(string args[]){ try{ Context initial = new InitialContext(); Object obj = initial.lookup("myename"); ENameHome home = (ENameHome)PortableRemoteObject.narrow(obj, ENameHome.class); EName e1 = home.create("2"," 안녕하세요오늘도즐거운날이되길바래요."); System.out.println(e1.getName()); EName e2 = home.findbyprimarykey("2"); System.out.println(e2.getName()); catch(exception e){ e.printstacktrace(); // end main ENameClient.java 끝 ------------------------------------------------- f. 클라이언트프로그램의실행 93

그림 139 CMP 엔티티빈을테스트하는 ENameClient.java 를컴파일합니다. 그림 140 CMP 엔티티빈을실행한결과입니다. 데이터베이스에는어떤값이저장되었을까요? 94

11. BMP(Bean Managed Persistence) 엔티티빈 BMP 엔티티빈은 EJB 컨테이너가자동으로처리하도록하는것이아니라, 프로그래머가데이터베이스관련메소드, SQL구문등을모두처리해주어야합니다. 그렇기때문에 CMP 엔티티빈보다 BMP 엔티티빈이프로그래밍하기에더욱까다롭습니다. 하지만, 수공예품이더욱세밀하게만들어져서팔리는것처럼 BMP 엔티티빈은좀더세밀한작업처리를할수있도록해줍니다. 또한 BMP 엔티티빈은 CMP에서는자동으로작성되던 find 메소드를모두구현해주어야하며, 특정한데이터베이스에종속적으로작성되어질수있습니다. 그말은, CMP 엔티티빈과비교하여재사용성이떨어질수있다는이야기입니다. 은행의잔고를확인하는 BMP엔티티빈을작성하면서 BMP 엔티티빈에대하여알아보도록하겠습니다. a. Home Interface의작성 Home Interface는엔티티빈의생명주기에관련된메소드들을구성합니다. Home Interface 에는 0개혹은 1개이상의 create메소드와 1개이상의 find메소드로이루어집니다. create 메소드는 java.rmi.remoteexception과 javax.ejb.createexception을 throws하여야합니다. create 메소드는빈클래스에서 ejbcreate 메소드와 1:1로대응됩니다. 매칭되는 ejbcreate메소드는인자의형식과수가같아야합니다. find메소드는 find로시작합니다. find메소드도 create메소드와같이빈클래스에서 ejbfind로시작하는메소드와 1:1로대응되어야합니다. find는매소드는또한 javax.ejb.finderexception과 javax.rmi.remoteexception을 throws하여야합니다. AccountHome.java 시작 ----------------------------------------------- import java.util.*; import java.rmi.*; import javax.ejb.*; public interface AccountHome extends EJBHome{ public Account create(string id, String name, double balance) throws RemoteException,CreateException; public Account findbyprimarykey(string id) throws FinderException, RemoteException; public Collection findbyname(string name) throws FinderException, RemoteException; 95

public Collection findinrange(double low, double high) throws FinderException, RemoteException; AccountHome.java 끝 ------------------------------------------------- b. Remote Interface의작성리모트인터페이스는비즈니스로직을처리하는메소드를정의합니다. Account.java 시작 ---------------------------------------------------- import javax.ejb.*; import java.rmi.*; public interface Account extends EJBObject{ // 인출하다 public void drawout(double amount) throws AccountException, RemoteException; // 예금하다 public void credit(double amount) throws RemoteException; // 이름을가져오다. public void getname() throws RemoteException; // 잔액을가져오다. public double getbalance() throws RemoteException; Account.java 끝 ------------------------------------------------------ c. 사용자정의 Exception 사용자정의 Exception은 Exception을처리하고자사용됩니다. AccountException.java 시작 -------------------------------------------- public class AccountException extends Exception{ public AccountException(){ super(); public AccountException(String msg){ super(msg); 96

AccountException.java 끝 ---------------------------------------------- d. Bean Class 작성하기실제로 BMP 엔티티빈에서가장중요한것은 Bean class의작성부분입니다. CMP 엔티티빈과는달리개발자가신경써야할부분이많기때문일것입니다. 일단 BMP 엔티티빈에서가장먼저만들어야할메소드는홈인터페이스에서정의된 create메소드와 find메소드에 1:1로대응되는 ejbcreate메소드와 ejbfind메소드입니다. ejbcreate메소드는데이터베이스에엔티티상태를삽입하고, 빈인스턴스속성을초기화하고, 프라이머리키를반환하는과정을처리합니다. CMP 엔티티빈은반환되는값이무시되므로 null값을리턴하도록프로그래밍하면되지만, BMP 엔티티빈일경우에는반드시프라이머리키값이리턴되도록하여야합니다. 또한 ejbcreate 메소드는반드시 public 메소드이어야하며, 전달되는인자가마샬링될수있어야하고메소드지정자가 final이나 static으로올수없습니다. find메소드는 CMP 엔티티빈일경우컨테이너가자동으로생성하여주지만, BMP 엔티티빈일경우에는개발자가모두구현해줘야합니다. find관련메소드중 findbyprimarykey메소드는반드시구현되어야할메소드입니다. 이렇게 ejbcreate메소드와 find메소드를구현하였다면, 아래와같은메소드를추가로구현해줘야합니다. - ejbpostcreate메소드 - ejbremove메소드 - ejbload메소드 - ejbstore메소드 - setentitycontext메소드 - unsetentitycontext메소드 - ejbactivate메소드 - ejbpassivate메소드각각의메소드의설명은아래와같습니다. ejbpostcreate메소드는 ejbcreate메소드가호출된뒤바로다음으로실행되는메소드이며보통은선언만하고구현은하지않습니다. ejbpostcreate메소드는 EntityContext인터페이스의 getprimarykey와 getejbobject메소드를호출할수있습니다.ejbpostcreate메소드는 ejbcreate메소드와대응되며 ejbcreate메소드가가지는파라미터의개수와형태와일치해야합니다. ejbpostcreate메소드의접근제어자는반드시 public이어야하며메소드지정자는 final이거나 static일수없습니다. 메소드의반환형은반드시 void 형이어야합니다. ejbremove 메소드는클라이언트가 remove 메소드를호출할경우호출되는메소드입니다. 97

ejbremove메소드가실행될경우컨테이너는해당레코드를삭제하게됩니다. 만약엔티티빈이삭제될경우처리할내용을작성하고싶다면 ejbremove메소드에서작성해주면됩니다. ejbload메소드와 ejbstore메소드는엔티티빈의인스턴스속성값과데이터베이스에저장된값의동기화를맞출때사용되는메소드입니다. EJB 컨테이너는동기화를맞춰야할경우 ejbload와 ejbstore메소드를호출하게됩니다. 이두개의메소드는클라이언트에서호출할수는없고, EJB가호출하는메소드입니다. ejbload메소드는데이터베이스로부터값을읽어와엔티티빈의상태값을재설정하기위한메소드이고, ejbstore는반대로데이터베이스에엔티티빈의상태값을저장하는메소드입니다. 이두개의메소드는사용하기에따라서아주유용하게사용될수있습니다. ( 어떤경우일까요? ) setentitycontext메소드는빈의 JNDI컨텍스트와데이터베이스에대한연결을설정하는메소드입니다. unsetentitycontext 메소드는데이터베이스에대한연결설정을해제합니다. ejbactivate메소드는 bean인스턴스를활성화시킬때이용되는메소드로 CMP 엔티티빈과 BMP 엔티티빈모두동일한기능을수행합니다. ejbpassivate메소드는 bean인스턴스를비활성화시킬때이용되는메소드로 CMP 엔티티빈과 BMP 엔티티빈모두동일한기능을수행합니다. 위에서설명한메소드를모두구현하였다면, 마지막으로리모트인터페이스에서정의한비즈니스로직을담당하고있는메소드를구현합니다. AccountEJB.java를보며각각의메소드에서어떻게정의하고있는지살펴보시기바랍니다. AccountEJB.java 시작 -------------------------------------------------- import java.sql.*; import javax.sql.*; import java.util.*; import javax.ejb.*; import javax.naming.*; public class AccountEJB implements EntityBean{ private String id; private String name; 98

private double balance; private EntityContext context; private Connection con; private String dbname = "jdbc/oracle"; public void drawout(double amount) throws AccountException{ if(balance - amount < 0){ throw new AccountException(" 잔고가부족합니다."); balance -= amount; public void credit(double amount){ balance += amount; public String getname(){ return name; public double getbalance(){ return balance; public String ejbcreate(string id, String name, double balance) throws CreateException{ if( balance < 0.00 ){ throw new CreateException(" 잔고가 0보다작을수는없습니다."); try{ insertrow(id, name, balance); catch(exception e){ throw new EJBException("create exception: " + e); this.id = id; 99

this.name = name; this.balance = balance; return id; public String ejbfindbyprimarykey(string primarykey) throws FinderException{ boolean result; try{ result = selectbyprimarykey(primarykey); catch(exception e){ throw new EJBException("ejbFindByPrimaryKey exception: " + e); if(result){ return primarykey; else{ throw new ObjectNotFoundException(primaryKey + " 값을발견할수없습니다."); public Collection ejbfindbyname(string name) throws FinderException{ Collection result; try{ result = selectbyname(name); catch(exception e){ throw new EJBException(" 이름을찾을수가없습니다."); // 결과가없을경우 if(result.isempty()){ throw new ObjectNotFoundException("No rows found"); else{ 100

return result; public Collection ejbfindinrange(double low, double high) throws FinderException{ Collection result; try{ result = selectinrange(low, high); catch(exception e){ throw new EJBException("Range Exception: "+ e); if(result.isempty()){ throw new ObjectNotFoundException("No rows found"); else{ return result; public void ejbremove(){ try{ deleterow(id); catch(exception e){ throw new EJBException("ejbRemote: " + e); public void setentitycontext(entitycontext context){ this.context = context; try{ makeconnection(); catch(exception e){ throw new EJBException("setEntityContext : " + e); 101

public void unsetentitycontext(){ try{ con.close(); catch(sqlexception e){ throw new EJBException("unsetEntityContext: " + e); public void ejbactivate(){ id = (String)context.getPrimaryKey(); public void ejbpassivate(){ id = null; public void ejbload(){ try{ loadrow(); catch(exception e){ throw new EJBException("ejbLoad: " + e); public void ejbstore(){ try{ storerow(); catch(exception e){ throw new EJBException("ejbStore: " + e); public void ejbpostcreate(string id, String name, double balance){ /***************** 데이터베이스핸들링부분 ***********************************/ 102

private void makeconnection() throws NamingException, SQLException{ InitialContext initial = new InitialContext(); DataSource ds = (DataSource)initial.lookup(dbName); con = ds.getconnection(); private void insertrow(string id, String name, double balance) throws SQLException{ String inserts = "insert into account values (?,?,? )"; PreparedStatement insertps = con.preparestatement(inserts); insertps.setstring(1, id); insertps.setstring(2, name); insertps.setdouble(3, balance); insertps.executeupdate(); insertps.close(); private void deleterow(string id) throws SQLException{ String deletes = "delete from account where id =?"; PreparedStatement deleteps = con.preparestatement(deletes); deleteps.setstring(1, id); deleteps.executeupdate(); deleteps.close(); private boolean selectbyprimarykey(string primarykey) throws SQLException{ String selects = "select id from account where id =?"; PreparedStatement selectps = con.preparestatement(selects); selectps.setstring(1, primarykey); ResultSet rs = selectps.executequery(); boolean result = rs.next(); rs.close(); selectps.close(); return result; 103

private Collection selectbyname(string name) throws SQLException{ String selects = "select id from account where name =?"; PreparedStatement selectps = con.preparestatement(selects); selectps.setstring(1, name); ResultSet rs = selectps.executequery(); ArrayList a = new ArrayList(); while(rs.next()){ String id = rs.getstring(1); a.add(id); rs.close(); selectps.close(); return a; private Collection selectinrange(double low, double high) throws SQLException{ String selects = "select id from account where balance between? and?"; PreparedStatement selectps = con.preparestatement(selects); selectps.setdouble(1, low); selectps.setdouble(2, high); ResultSet rs = selectps.executequery(); ArrayList a = new ArrayList(); while(rs.next()){ String id = rs.getstring(1); a.add(id); rs.close(); selectps.close(); return a; private void loadrow() throws SQLException{ String selects = "select name, balance from account where id =?"; PreparedStatement selectps = con.preparestatement(selects); 104

selectps.setstring(1, this.id); ResultSet rs = selectps.executequery(); if(rs.next()){ this.name = rs.getstring(1); this.balance = rs.getdouble(2); selectps.close(); else{ selectps.close(); throw new NoSuchEntityException( this.id + " 를찾을수가없군요.(loadRow)"); =?"; private void storerow() throws SQLException{ String updates = "update account set name =?, balance =? where id PreparedStatement updateps = con.preparestatement(updates); updateps.setstring(1, this.name); updateps.setdouble(2, this.balance); updateps.setstring(3, this.id); int updatecount = updateps.executeupdate(); updateps.close(); if(updatecount == 0){ throw new EJBException(" 수정된데이터가없습니다."); // end class AccountEJB.java 끝 ---------------------------------------------------- e. 디플로이먼트하기 105

그림 141 홈인터페이스, 리모트인터페이스, 빈클래스, 사용자정의 Exception을컴파일합니다. 그림 142 deploytool을실행한후 File New Application 에서 account를생성한화면입니다. 106

그림 143 File-New-Enterprise Bean을선택합니다. 그림과같이설정한후 Next버튼을클릭합니다. 그림 144 그림과같이설정한후 Next 버튼을클릭합니다. 107

그림 145 Bean Managed Persistence를선택한후 Primary Key Class를 java.lang.string 으로변경합니다. 그림 146 그림과같이설정한후 Next 버튼을클릭합니다. 108

그림 147 Next 버튼을클릭합니다. 그림 148 Next 버튼을클릭합니다. 109

그림 149 그림과같이설정합니다. 데이터베이스에접속하기위한설정이므로중요합니다. UserName 과 Password는사용하고있는오라클의 username과 Password를작성해주시면됩니다. 설정하였다면 Finish버튼을클릭합니다. 그림 150 그림과같이엔터프라이즈빈이추가된것을알수있습니다. 110

그림 151 Security tab 에서보안설정을그림과같이합니다. 그림 152 Tools deploy 를선택합니다. 그림과같이셋팅한후 Next 버튼을클릭합니다. 111

그림 153 JNDI Name 을설정한후 Next 버튼을클릭합니다. 그림 154 Finish 버튼을클릭합니다. 112

그림 155 디플로이되는과정이그래프와함께표시됩니다. 그림 156 디플로이가끝났습니다. 113

그림 157 Server 에 Account 가추가된것을알수있습니다. f. 클라이언트프로그램의작성과실행 AccountClient.java는 BMP엔티티빈을이용하기위한클라이언트소스입니다. AccountClient.java 시작 ------------------------------------- import javax.naming.*; import javax.rmi.*; public class AccountClient{ public static void main(string args[]){ try{ Context initial = new InitialContext(); Object obj = initial.lookup("myaccount"); AccountHome home = (AccountHome)PortableRemoteObject.narrow(obj, AccountHome.class); Account kim = home.create("1", "kim", 0.00); kim.credit(200.00); kim.drawout(100.90); double balance = kim.getbalance(); 114

System.out.println("kim의잔고 :" + balance); catch(exception e){ e.printstacktrace(); // end main // end class AccountClient.java 끝 ---------------------------------------------- 그림 158 AccountClient 의컴파일 그림 159 AccountClient 의실행 AccountClient 에서 BMP 엔티티빈이가지고있는다른메소드는어떻게실행할까? 115

12. 마치며 자바는역시쉽지는않은것같다. 라는생각이듭니다. 다만단순하다. 라는표현이알맞을까요? 너무복잡하게생각하면 왜이렇게해야만되지? 라는생각만머리에서맴돌뿐입니다. 하지만, 단순하게이렇게하라니이렇게하자. 라고생각한다면문제는의외로쉽게풀립니다. JAVA를공부하고 EJB공부를처음시작하는사람은, EJB를소개하고있는문서에먼저압도되는것이사실입니다. 그리고나서예제도제대로실행하지못하고포기하고맙니다. 어떤분은상용 EJB 컨테이너인웹로직같은소프트웨어를설치하다가포기하는경우도보았습니다. 그렇게실패하고포기하는이유는전체적인모습을한번도본적이없어서그렇다. 라고말해도과언이아닙니다. EJB는썬사에서발표한표준입니다. 그리고 J2EE는모든 EJB컨테이너가참고로하는소프트웨어입니다. EJB를이해하기위하여는 J2EE로먼저공부하는것이가장좋다. 라는것이저의생각입니다. 그리고나서나중에상용 EJB컨테이너를이용하는것이알맞을것같습니다. 해당문서만보아서는 EJB에대하여자세히알수는없습니다. 꼭 EJB참고서적을구입하신후함께보시기바랍니다. 물론책을사기전에똑같이따라해볼수는있습니다. EJB를만드는과정을꼼꼼하게그림으로모두표시해놓았으니직접실행하지않아도이해하리라생각합니다. 내공이깊으면연공이자유롭다고합니다. 사실 EJB를올바르게공부할려면 EJB에대하여체계적으로공부해야합니다. 하지만해당문서는귀납적인방법을택하였습니다. 먼저결과를보고, 스스로공부하도록만든것입니다. 그래서먼저 아! EJB라는것은이런것이구나. 스펙이이런것이구나! 라는것을깨닫게만들고싶었습니다. 빠른시간에작성한문서라틀린부분이있을수도있습니다. 틀린부분을발견한다면저에게메일 (urstory@nownuri.net) 을보내주십시오. 꼬랑지말 ; 해당문서의제목은 Enterprise Java Bean #1 입니다. #2 는언제쯤작성할까요? 김성박. 2002년 1월 17일목요일. 하나님은당신을사랑하십니다. 116