J2EE, EJB, Struts notes

J2EE, 특히 EJB와 Struts 프레임웍, 보안, 웹로직 서버에 관련된 팁들을 정리하고 있습니다.
J2EE 1.4와 Sun Java System AS에 관련된 내용은 별도의 페이지에서 다룰 예정입니다.
1. EJB reference problems
EJB가 다른 EJB를 참조할 때, 혹은 다른 클래스들을 참조할 때 상호 참조 문제나 클래스 경로 참조 문제가 발생한다.
일반적인 J2EE 프로젝트는 여러 티어로 구성되기 때문에 웹 티어와 EJB 티어, 그리고 중간 티어를 구성하는 자바 클래스들 간의 참조 관계(의존 구조)를 명확하게 해야 한다.
웹로직 서버의 경우, EJB jar 파일에서 Manifest의 Class-Path 항목을 사용하여 EJB가 참조하는 클래스들이 포함된 jar 파일 목록을 지정할 수 있는데 ear 파일로 deploy되는 경우에만 동작한다.

2. Emacs JDE를 사용한 EJB 지원
이맥스를 사용하여 자바 프로그래밍을 하는 사람이라면 대부분 JDE for Emacs를 사용할 것이다.
현재의 JDE 버전은 EJB를 지원한 많은 기능이 포함되어 있지만, EJB 2.x 스펙에 맞는 EJB 스켈레튼 버퍼를 생성하지 않고 EJB 1.1 스펙에 따른 버퍼들을 생성해준다. (M-x jde-ejb-session-bean-buffer 혹은 M-x jde-ejb-entity-bean-buffer 명령 참조)
임시로 이 기능들을 EJB 2.x 스펙에 맞는 버퍼를 만들도록 JDE 2.3.2 버전의 jde-ejb.el을 변경하여 보았다.
수정한 jde-ejb.el

3. Ant build.xml - 멀티 티어 J2EE 프로젝트
웹 티어, 여러 개의 EJB, Data Transfer Object가 포함된 중간 티어 등 여러 티어로 구성되는 J2EE 프로젝트를 빌드하는 Ant의 빌드 파일을 작성할 때에는 각 티어에 대한 의존을 고려해야 한다.
각 티어의 요소가 실행 시에 상호 클래스 참조에 대한 의존을 deploy 시에 고려하여 jar, war, ear 파일을 구성해야 하는 것처럼, Ant로 빌드할 때에도 각 타겟별로 이와 유사한 고려를 해야 한다.
다음은 웹 application을 포함한 다중 티어 구조를 위한 Ant의 build.xml 파일 예제이다.
예제 파일에서는 web hot deploy 모드를 지원하기 위해 EJB를 사용하지 않는 별도의 테스트용 비즈니스 티어를 사용하고 있다.
또다른 방법으로는 war의 내용은 디렉토리에 풀어서 배포하고 war의 내용을 뺀, 즉 EJB와 라이브러리만으로 구성된 ear 파일을 배포하는 것이다. 이 방법을 사용하면 별도의 비즈니스 티어 없이 web hot deploy 모드를 개발 때 사용 가능하다.
다중 티어 J2EE 프로젝트를 위한 Ant 빌드 파일 예

4. Jakarta Struts framework 적용 팁
Struts 1.1 가이드(PDF 문서)
MVC 웹 아키텍처인 스트럿 프레임웍을 적용할 때 자주 만나게 되는 몇 가지 문제들에 대한 해결책.
[여기에 bean:define를 사용하여 정의한 값을 logic:iterate 등의 태그에서 참조하는 예제가 들어와야 함]
[여기에 모델(ActionForms)/뷰(jsp and tags)/컨트롤러(Actions)를 사용하는 기본 흐름과 전형적인 관계들에 대한 설명이 추가될 것임]

5. Weblogic Security SPI 구현 팁
JAAS 기반 위에서 J2EE Security를 구현하기 위한 웹로직 서버의 보안 SPI 구현에서의 문제점과 해결책
문제점해결책
JAAS LoginContext를 사용할 경우, 인증된 Subject가 웹로직 서버의 컨테이너로 전파되지 않는다. weblogic.security.services.Authentication.login(CallbackHandler) 메소드를 사용하여 얻은 Subject에 인증된 Principal들과 Credential들을 저장한다.
웹로직의 AuthenticationProvider를 사용할 경우(authentication provider나 identity asserter 모두 해당) 커스텀 CallbackHandler를 LoginModule에 넘겨줄 수 없다. 웹로직 서버의 컨테이너가 로그인 모듈을 호출하기 때문이다. weblogic.security.services.Authentication.login(CallbackHandler) 메소드를 직접 호출한다. JAAS에서 LoginContext를 생성하여 login() 메소드를 호출하는 것과 유사하며, 웹로직에 등록된 authentication providers들의 LoginModule들이 호출되어, Authentication.login() 메소드에 인자로 지정한 커스텀 콜백 핸들러가 로그인 모듈에 넘겨진다.
웹로직 서버 컨테이너가 user와 group으로 각각 인식하는 Principal을 만들 필요가 있다. weblogic.security.spi.WLSUser와 weblogic.security.spi.WLSGroup 인터페이스를 각각 상속하는 Principal을 정의하면 된다. weblogic.security.SubjectUtils 클래스는 Subject로부터 사용자 정보나 그룹 정보를 가져오는 유틸리티 메소드들을 제공한다.


[여기에 웹로직 security SPI 관련]

6. HTML input form charset tip

7. 유니코드로 된 파일 이름을 인터넷 익스플로러에서 저장하는 방법
이것은 자바 팁이라기보다는 마이크로소프트 사의 인터넷 익스플로러 사용 팁이라고 봐야겠네요.
파일 다운로드할 때 인터넷 익스플로러가 자동으로 다운로드 대화상자를 띄우도록 하려면 Content-Disposition HTTP 헤더를 사용하면 된다는 것이 많이 알려져 있는 것 같습니다.
이 경우
 Content-Disposition: attachment; filename=myfile.txt;
뭐 이런 식으로 처리하면 되는데 문제는 파일 이름이 myfile.txt가 아니라 현재의 인코딩(한글 윈도우라면 자바의 MS949)에서 표현할 수 없는 글자일 경우입니다.
다음 URL에서 실용적인 해법을 제시하고 있습니다. 실제 표준이라고 보기에는 아직 무리가 있습니다. 아직 unicode 파일 이름을 이 헤더에서 처리하는 표준은 명확하지 않은 것 같습니다.

이 내용과 관련된 RFC는 입니다.
그런데 이렇게 처리하면 UTF8로 escape되면서 너무 길어지게 되는데 IE가 헤더 길이에 한계를 두고 있어서 긴 파일 이름은 잘못 보여줄 수 있답니다.
그래서 항상 이 방법을 사용하기보다는 현재 인코딩으로 못 보여주는 유니코드 글자가 있는지 검사를 해서 그 경우에만 이 방법을 쓰는 게 좋겠습니다.
다음은 테스트를 위한 서블릿 부분 코드로, tomcat 5.0에 input/output 인코딩 모두를 ISO-8859-1로 가정하고 있습니다.
input/output 인코딩이 MS949나 EUC-KR인 경우에는 약간 수정이 필요할 것입니다.
이 방식을 사용하면 한글 윈도우에서 MS949 밖의 일본어나 중국어 글자를 가진 파일 이름도 인터넷 익스플로러 다운로드 대화상자에서 표현할 수가 있습니다.
    // 사용 인코딩을 MS949로 생각하고 상수 선언합니다.
    private static final String MY_ENCODING = "MS949";

... (생략)
{
... (생략)

    String fileName = request.getParameter("fileName");

    // 1바이트짜리라고 생각하고 톰캣이 읽어들인 것을 UTF8로 바로 잡습니다.
    // 실제 IE가 UTF8로 post해야 하겠지요.
    fileName = new String(fileName.getBytes("8859_1"), "UTF8");
    String agentType = request.getHeader("User-Agent");

    response.setContentType("application/octet-stream;");

    // 톰캣이 이해할 수 있는 RESPONSE HEADER로 바꿔주기 위해 MS949에 따른 바이트
    // 배열로 바꾸고 이것을 다시 1바이트짜리 String인 ISO-8859-1 인코딩으로
    // 해서 String 객체를 다시 만듭니다. 만약 MS949를 기본 인코딩으로 인식하는
    // 환경이라면 그냥 문자열을 사용하면 되겠지요.
    // String header = "attachment; filename=" + fileName + ";";
    String header = "attachment; filename=" + new
	String(fileName.getBytes(MY_ENCODING), "8859_1") + ";";

    // 현재 인코딩으로 다 표현할 수 있는지 여부를 검사해서, 다 표현할 수 없을
    // 경우에만 RFC 2047에서 정의한 것과 유사한 방식으로 escape을 합니다.
    if (!fileName.equals(new String(fileName.getBytes(MY_ENCODING),
				    MY_ENCODING))) {
	header = "=?UTF-8?Q?attachment; filename="
	    + java.net.URLEncoder.encode(fileName, "UTF-8") + ";?=";
    }
    response.setHeader("Content-Disposition", header);
}

8. J2EE 1.4
See Notes on J2EE 1.4 AS Developer Release and Features.
[Class Loader, Dynamic Proxy, XML, JDBC, JNDI, LDAP, Transaction, Security, Cryptography, SSL, Authentication, Login, Authorization, CORBA, RMI, RMI-IIOP, ... 본격적인 자바 개발자로 가기 위한 (책) 자바 2 SDK 1.4 시작 그리고 완성]

Yoon Kyung Koo <yoonforh at yahoo dot com>
이 페이지는 2003년 1월 18일에 처음 만들어졌습니다.
Last modified: Sat Dec 20 12:00:25 KST 2003