ProgEJB :: 2008/06/02 10:47

J2EE based EJB Programming – 삼성멀티캠퍼스(20080526 ~ 20080530)

 

WAS(Web Application Server)

J2EE 스펙을 따르는 서버로써, Java 진영에서 관용적으로 부르고 있다.

이름만 보면 Java 랑 전혀 관계가 없지만 그렇게 주로 부른다.

 

 

사용자 삽입 이미지

 

RMI(Remote Method Invocation)

원격 객체 사이의 통신을 말한다. 보통 객체 사이의 통신을 해서 프로그램을 하려면 소켓을 이용한 프로그래밍을 생각해볼 수 있다. 그러나 소켓을 통한 프로그래밍이 어려운 것은 서버와 클라이언트 사이에 어떻게 메시지를 주고 받을 건지 모두 정의를 해야 하기 때문에 간단한 프로그램의 경우는 상대적으로 간단하게 끝나지만 규모가 커질수록 프로그램이 엄청 힘들게 된다. 그래서 생각해낸 것이 다른 서버에 있는 객체를 마치 같은 시스템 안에 있는 객체처럼 접근하고 메소드를 호출할 수 있게 한 것이 RMI 이다. 이렇게 되면 소켓을 이용할 필요도 없고(당연히 Row Level 에서는 사용이 되고 있지만 High Level 에서는 몰라도 된다.) 단순히 객체의 레퍼런스를 얻어서 호출하기만 하면 된다.

 

RMI 의 장점

클라이언트가 서버의 위치를 알 필요가 없다. 클라이언트와 서버 사이에 네이밍 서버가 있기 때문에 가능하다.

 

RMI 의 단점

오버헤드가 많다는 점. 클라이언트가 서버에게 서비스 요청하려면 네이밍 서버를 참조해야 하며, 서비스 요청 전달 과정에서 마샬링과 언마샬링이 필요하기 때문에 오버헤드가 많게 된다.

마샬링(Marshalling) : 메소드와 매개 변수를 스트림으로 변환하는 과정

언마샬링(Unmarshalling) : 전달받은 스트림을 분석하는 과정

마샬링과 언마샬링 과정에서 객체 직렬화(Serialization)가 사용된다.

 

 

 

사용자 삽입 이미지

 

RMI 사용의 단계

1. 인터페이스를 정의한다.

2. 인터페이스를 구현하는 클래스를 정의한다

3. 서버와 클라이언트 클래스를 정의한다.

4. 스텁과 스켈레톤을 생성한다.

5. 네이밍 서버를 실행한다.

6. 서버를 실행한다

7. 클라이언트를 실행한다.

 

예제

1. 인터페이스 정의하기

RMI 의 인터페이스는 다음 규칙을 지켜야 한다.

원격 인터페이스는 java.rmi.Remote 인터페이스를 상속받아야 한다.

원격 인터페이스에 선언된 메소드는 throws RemoteException 으로 선언되어야 한다.

Hello.java

package rmi;

import java.rmi.Remote;

import java.rmi.RemoteException;

 

public interface Hello extends Remote {

        String hi() throws RemoteException;

        Info getInfo() throws RemoteException;

}

 

 

2. 원격 객체 클래스 정의하기

생성자는 throws RemoteException 으로 표현되어야 한다.

원격 인터페이스를 구현해야 한다.

UnicastRemoteObject 클래스를 상속받아야 한다.

HelloImpl.java

package rmi;

 

import java.rmi.RemoteException;

import java.rmi.server.UnicastRemoteObject;

 

public class HelloImpl extends UnicastRemoteObject implements Hello {

       private Info info = new Info("ByeongChan Gwak","KSD");

      

       public HelloImpl() throws RemoteException {

       }

       public String hi() throws RemoteException {

             return "반가워요";

       }

       public Info getInfo() throws RemoteException {

             return info;

       }

}

 

 

3. 서버 클래스와 클라이언트 클래스 정의하기

서버 클래스에서는 분산 객체를 생성하여 네이밍 서버에 등록하고, ‘bound’ 되었다는 메시지를 출력한다.

클라이언트 클래스에서는 네이밍 서버에서 원격 객체를 찾아 레퍼런스를 가져온 후 원격 객체의 메소드를 호출하고 결과를 활용한다.

HelloServer.java

package rmi;

 

import java.rmi.Naming;

 

public class HelloServer {

       public static void main(String[] args) throws Exception {

             Hello hello = new HelloImpl();

             Naming.rebind("hello",hello);

            

            

             System.out.println("등록되었습니다.");

       }

}

 

HelloClient.java

package rmi;

 

import java.rmi.Naming;

import rmi.Hello;

 

public class HelloClient {

       public static void main(String[] args) throws Exception {

             Hello hello = null;

             hello = (Hello) Naming.lookup("hello");

             System.out.println("result=" + hello.hi());

            

             System.out.println("new result = " + hello.getInfo().getName() + hello.getInfo().getCompany());

             System.out.println("done");

       }

}

 

 

 

4. 스텁과 스켈레톤 생성

rmic 를 사용하여 스텁 클래스와 스켈레톤을 생성한다. 다음을 실행해보면 스텁만 생기는데 스켈레톤은 JDK 1.2 부터 명시적으로 만들지 않게 되었기 때문에 생성되지 않는다.

C:\Java\ejb\03_RMI_Hello\src>rmic -classpath ../bin rmi.HelloImpl

 

5. 네이밍 서버 실행하기

C:\Java\ejb\03_RMI_Hello\bin>start rmiregistry

 

6. 서버 실행하기

 

7. 클라이언트 실행하기

 

 

RMI-IIOP

RMI를 이용하면 분산 프로그래밍을 쉽게 구현할 수 있으나, 클라이언트와 서버를 모두 자바로 프로그래밍해야 한다는 단점이 있다. 또한 CORBA-IIOP 프로토콜을 사용하지 않기 때문에 다른 언어로 작성된 프로그램과 통신할 수 없다는 단점이 있다.

CORBA를 활용하면 프로그래밍 언어에 중립적인 시스템을 개발할 수 있으나, 플랫폼 중립적인 IDL 언어를 학습해야 하며, 프로그래밍 하기가 RMI 와 비교하여 상대적으로 어렵다. 그러나 RMI-IIOP 프로토콜을 사용하면 분산 객체 서버는 IIOP 프로토콜을 이용할 수 있으므로 다른 언어로 작성된 CORBA 객체와 통신할 수 있다. RMI-IIOP 를 이용하려면 원격 객체 클래스가 상속 받아야 하는 클래스를 달리해야 하며, rmic 컴파일러의 옵션을 사용하여 컴파일해야한다.

 

 

JNDI

자바 어플리케이션에서 사용할 수 있는 자바 API이며, 네이밍과 디렉토리 기능을 제공한다.

 

네이밍이라는 것은 클라이언트가 원격 객체를 찾을 수 있도록 원격 객체에 이름을 부여하는 것이다.

디렉토리 기능은 네이밍 서비스뿐만 아니라 검색과 디렉토리 등의 부가적인 기능까지도 제공하는 것을 의미한다.

EJB JNDI 를 이용하여 네이밍과 디렉토리 서비스를 이용하며, JMS JDBC2.0 에서도 JNDI 를 이용한다.

 

 

EJB

XML

EJB 를 개발하는 과정에서 인터페이스와 빈 클래스 그리고 빈의 배치 정보를 기술할 XML 파일이 생성된다. EJB 에서 XML 를 학습하려는 이유는 빈의 배치 정보를 파악하기 위해서이다.

JNDI

EJB 는 클라이언트와 RMI 로 통신하기 때문에, 클라이언트에서 EJB 에게 서비스를 요청하려면 JNDI의 네이밍 서비스를 활용해야 한다.

 

EJB 종류

세션 빈

비즈니스 로직을 수행하는 빈이다.

엔티티 빈

데이터를 표현하는 빈이다.

메시지 드리븐 빈

비동기 메시지를 처리하는 빈이다.

 

 

EJB 개발 절차

1. 빈이 제공하는 메소드가 선언된 원격 인터페이스를 정의한다.

2. 빈을 생성하고 찾기 위한 메소드가 선언된 홈 인터페이스를 정의한다.

3. 원격 인터페이스에 선언된 메소드를 구현한 빈 클래스를 정의한다.

4. 빈의 배치정보, 실행 정보 등이 기록된 XML 파일 형식의 배치 디스크립터(Deployment Descriptor)를 생성한다.

5. 인터페이스와 빈 클래스 그리고 배치 디스크립터를 jar 파일로 압축한다.

6. EJB 서버에 배포하여 서비스 한다.

다시 한번 정리하자면, 세션 빈이나 엔티티 빈은 두 개의 인터페이스와 하나의 빈 클래스를 정의하고, EJB 의 배치정보를 XML 파일로 작성하여 jar 파일로 압축한 후, WAS 서버에 배포하여야 비로소 서비스 할 수 있다.

 

세션 빈

세션 빈 소개

세션 빈은 비즈니스 로직을 수행하는 빈이다. 예를 들어, 호텔예약이나 카드 결제, 전자 결제를 하는 일들은 세션 빈에서 수행되도록 한다. 이러한 세션 빈을 클라이언트가 요청할 때마다 생성하고 삭제하는 것은 오버 헤드가 많이 발생하기 때문에 객체 풀(Pool)과 활성화/비활성화 메커니즘을 사용한다. 객체 풀이란 객체를 미리 생성해 두고 클라이언트의 요구 사항을 처리하는 메커니즘이다. 클라이언트의 요구사항 처리가 끝나면 다시 풀로 돌아가게 되며, 객체를 매번 생성할 필요가 없으므로 훨씬 효율적이다.

 

세션 빈의 실행 메커니즘

세션 빈은 EJB 서버(Web Application Server를 말하며, 웹 로직이나 웹 스피어 등이 있음)에 세 가지의 객체가 생성되어 서비스된다. , 홈 객체와 EJB 객체 그리고 빈 객체이다. 클라이언트에서 세션 빈에게 서비스를 요청하려면 먼저 JNDI 서비스를 통하여 홈 객체를 찾아야 하며, 홈 객체의 create() 메소드를 실행 요청한다. 그러면 EJB 객체를 참조할 수 있게 되며, 비즈니스 로직 메소드를 실행 요청 할 수 있게 된다.

 

 

사용자 삽입 이미지

 

1. JNDI 를 이용하여 원격 객체를 찾아서 Home 객체로 받아온다.

2. 클라이언트가 홈 객체의 create() 메소드를 호출한다.

3. EJB 객체가 생성된다.

4. 클라이언트는 EJB 객체의 레퍼런스를 참조할 수 있게 된다.

5. 비즈니스 메소드를 호출한다.

6. 빈 객체의 비즈니스 메소드가 실행된다.

7. 클라이언트는 실행 결과를 활용할 수 있게 된다.

 

위의 과정을 클라이언트의 소스 코드를 통하여 살펴보면 다음과 같다.

Context ctx = new InitialContext();

HelloHome home = (HelloHome)ctx.lookup(“HelloEJB”);

Hello hello = home.create();

String result = hello.hi(“Kim”);

 

 

XML(eXtensible Markup Language)

1996 W3C(World Wide Web Consortium) 에서 제정한 태그를 확장하여 사용할 수 있는 마크업(Markup) 언어이다. XML을 사용하면 정보를 구조적으로 표현할 수 있으며, 문서 정보의 구조를 임의로 정하여 사용할 수 있다.

XML HTML 과 달리 태그를 확장하여 사용할 수 있고, 정보를 구조적으로 표현할 수 있기 때문에 정확하고 효율적인 정보 검색이 가능하다. 이러한 특징 때문에 XML은 여러 분야의 데이터를 구조화하여 표현하는 곳에 사용된다.

 

‘Well-formed XML 문서‘Valid XML 문서

Well-formed XML 문서

한 개 이상의 요소가 있어야 한다.

단 한 개의 루트 요소를 가져야 한다.

태그가 서로 겹쳐져 있지 말아야 한다.

시작 태그가 있으면 반드시 종료 태그가 있어야 한다.

Valid XML 문서

Well-formed XML 문서여야 한다.

문서의 구조를 정의한 DTD나 스키마가 있어야 한다.

만일 문서의 구조를 DTD 로 정의했다면, DTD 가 정한 구조(Structure) 와 요소 사용에 대한 규칙(문법)을 따라야 한다.

 

XML 문서의 구조

XML 문서는 선언부(Prolog)와 내용부(Body)로 구성된다.

선언부의 예는 다음과 같다

<?xml version=”1.0” encoding=”euc-kr”?>

<?xml version=”1.0” encoding=”euc-kr”=standalone=”yes” ?>

XML 표준에서는 XML 선언을 다음과 같이 정의한다.

‘<?xml’ 뒤에 반드시 버전 정보가 하나 있고 다음에 선택적으로 인코딩 정보와 standalone 정보가 올 수 있으며, ‘?>’ 로 종결한다.

XML 선언은 XML 버전 1.0에서는 생략할 수 있지만 선언하는 것이 바람직하며, 선언하는 경우에는 반드시 버전 정보가 있어야 한다. <?xml … ?> 이건 안 써도 되지만 만약 쓸 거라면 반드시 공백이 없게 처음에 바로 나오게 써야 한다.

 

DTD(Document Type Definition)

DTD‘XML 문서의 구조를 정의하는 것이며, XML 문서 내에서 사용된 태그를 정의하는 것이다.’ 이러한 DTD XML 문서 내부에 선언할 수도 있으며, 외부 파일로 존재하게 할 수도 있다. 이렇게 정의된 문법을 XML에 적용하기 위해서는 XML 문서에서 어떤 DTD 를 사용할 것인지 선언해 주어야 한다.

 

배치 디스크립터

EJB 의 배치 정보를 알리는 XML 파일이며, 배치 디스크립터 내부에 다음과 같은 정보를 기술한다.

1. 구조정보(Structual Information)

ejb-jar

최상위 태그이다.

description

애플리케이션이나 EJB 에 대한 설명을 기술한다.

enterprise-beans

여러 EJB 의 정보가 하위 태그로 기술된다.

session

세션 빈의 구조 정보가 하위 태그로 기술된다.

ejb-name

빈의 이름을 기술한다.

ejb-class

빈 클래스의 이름을 기술한다.

home

홈 인터페이스의 이름을 기술한다.

remote

원격 인터페이스의 이름을 기술한다.

session-type

Stateful 또는 Stateless 를 기술한다.

2. 실행정보(Runtime Information)

3. 보안정보(Security Information)

4. 관계정보(Relationship Information)

 

구조정보를 나타내는 XML 파일

<ejb-jar>

 <enterprise-beans>

  <session>

       <ejb-name>HelloEJB</ejb-name>

       <home>hello.HelloHome</home>

       <remote>hello.Hello</remote>

       <ejb-class>hello.HelloEJB</ejb-class>

       <session-type>Stateless</session-type>

       <transaction-type>Container</transaction-type>

  </session>                     

 </enterprise-beans>

 

 

 


Trackback Address :: http://kbckbc.mireene.co.kr/tatter/kbckbc/trackback/350
Name
Password
Homepage
Secret