Windows XP 기준으로 Java SDK를 설정하는 방법을 알려드리겠습니다. 간혹 모르시는 분들이 계셔서 정리차원에서 올려드립니다.

우선 JavaSDK를 다운로드 받아 설치했다고 가정하겠습니다. 만약 아직 Java SDK가 없으신 분은 http://java.sun.com/javase/downloads/index.jsp 에 가셔서 적합한 Java SDK를 다운로드 받으시면 됩니다.

Windows XP에 시스템 등록 정보의 고급 탭에서 환경변수 버튼을 클릭합니다.



시스템 변수 부분에서 새로 만들기 버튼을 클릭합니다.
그리고 변수 이름을 JAVA_HOME 이라고 넣으시고 설치한 JavaSDK의 경로를 넣습니다. 저의 경우 C:\Program Files\Java\jdk1.6.0_14 입니다.


그 후 CLASSPATH를 설정합니다. 마찬가지로 변수 이름은 CLASSPATH 이며 .;%JAVA_HOME%\lib 를 넣으시면 됩니다.


그리고 PATH를 설정하면 됩니다. PATH를 설정하실 때에는 기존 PATH에 %JAVA_HOME%\bin 만 더 넣으시면 됩니다. 참고로 Windows에서 PATH를 설정하실때에는 구분자가 ; 입니다.


정리하면 다음과 같습니다.

JAVA_HOME
C:\Program Files\Java\jdk1.6.0_14

CLASSPATH
.;%JAVA_HOME%\lib

PATH
%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%JAVA_HOME%\bin


이렇게 설정을 완료한 후 실행에서 cmd를 입력하여 설정이 제대로 되어 있는지 확인합니다.



다음과 같이 javac -version을 입력하여 설치한 Java SDK의 버전을 확인해 봅니다. 그리고 java -version을 입력하여 JRE의 버전도 확인해볼 수 있습니다.

정리하면 다음과 같습니다.

javac -version

java -version

이렇게 설정하시면 편리하게 Java SDK 하에서 쉽게 개발을 하실 수 있습니다.

참고하세요 ;-)

저작자 표시 비영리
신고

WRITTEN BY
jangsunjin
전세계 사람들의 삶의 질을 높일 수 있는 소프트웨어를 만들어 함께 나누는 것이 꿈입니다. 이 세상 그 무엇보다 사람이 가장 소중합니다.

받은 트랙백이 없고 , 댓글이 없습니다.
secret
Maven을 사용하면서 가장 번거로운 일 중에 하나가 Sun에서 배포되는 라이브러리를 추가할 때입니다. 메이븐 중앙 저장소(Maven Central Respository)에는 분명히 검색인 되지만 아티팩트(jar)가 없어서, m2eclipse에서 Missing Artifact... 라는 에러가 나옵니다.

지금까지는 다른 분들이 올려놓은 레포지토리를 연결해서 사용하거나 일일이 여러분의 로컬 레포지토리에 인스톨하여야 해결되었지만.. Sun에서도 Maven 1과 Maven 2용 레포지토리를 운영하고 있으니 간단하게 레포지토리를 추가하여 해결할 수 있습니다.

여러분의 POM.xml에<repositories> 아래에 다음과 같은 저장소 정보를 입력하세요~
    <repository>
        <id>maven2-repository.dev.java.net</id>
        <name>Java.net Repository for Maven</name>
        <url>http://download.java.net/maven/2/</url>
        <layout>default</layout>
    </repository>


만약 이클립스에서 m2eclipse 플러그인을 사용하신다면 다음과 같이 추가할 수 있습니다.


이렇게 추가하시면 Sun 에서 배포하는 디펜던시들을 마음껏 편하게 이용하실 수 있습니다.

보너스로~ Jboss 레포지토리 정보도 알려드리겠습니다. 함께 추가하시면 거의 모든 디펜던시들을 잘 이용하실 수 있습니다. ;-)
    <repositories>
        <repository>
            <id>maven2-repository.dev.java.net</id>
            <name>Java.net Repository for Maven</name>
            <url>http://download.java.net/maven/2</url>
        </repository>
        <repository>
            <id>jboss-repository</id>
            <name>Jboss Repository for Maven 2</name>
            <url>http://repository.jboss.com/maven2/</url>
        </repository>
    </repositories>

더욱 상세한 정보는 https://maven2-repository.dev.java.net/ 에서 확인하세요~
저작자 표시 비영리
신고

WRITTEN BY
jangsunjin
전세계 사람들의 삶의 질을 높일 수 있는 소프트웨어를 만들어 함께 나누는 것이 꿈입니다. 이 세상 그 무엇보다 사람이 가장 소중합니다.

받은 트랙백이 없고 , 댓글  2개가 달렸습니다.
  1. Maven을 잘 사용하시는 것 같아서 질문좀 드리려구요~
    http://code.google.com/p/ebi-pride/ 여기의 데이터베이스를 설치하는 중에 프로젝트가 메이븐으로 되어있는데, 제가 메이븐을 사용해본적이 없어서..
    필요한 환경은 다 다운로드, 설치했습니다.

    Alternatively, if you host your own repository you can deploy the file there:
    mvn deploy:deploy-file -DgroupId=uk.ac.ebi.pride -DartifactId=pride-core -Dversion=2.5.7 -Dclassifier=javadoc -Dpackaging=javadoc -Dfile=/path/to/file -Durl=[url] -DrepositoryId=[id]

    위와같은 메세지에서 Dfile, Durl, DrepositoryId 에 각각 설정해줘야하는 값이 어떤것인지 좀 조언해주세요~
  2. 안녕하세요~

    Maven때문에 버벅거리고 있어서.. 조언을 구하고자 이렇게 글을 남깁니당..

    Maven설치하고 m2eclipse 플러그인을 설치하였는데... pom.xml의 Dependencies에서 라이브러리 검색이 되지 않고 있는데 무슨 현상 때문일까요?

    아무래도 저장소 때문인 것 같은데.. .m2 디렉토리 밑에 settings.xml파일까지 넣었습니당~ 근데도 검색이 안되요 흑...
    이럴 땐 어떻게 해야할까요? 예전에는 .m2디렉토리에 settings.xml파일을 넣었을 때 잘 되었던 기억이 있는데.. 저장소 url이 잘못된것인지 아님 설치를 잘 못 한건인지.. 궁금합니다아~~~ 조언해주심 정말 감사합니다 ^^
secret
Maven을 사용하여 메이븐 프로젝트를 구성하는 경우, 가장 귀찮은 것이 메이븐 중앙 레포지토리에 없는 디펜던시 아티팩트를 추가하는 일입니다.

특히 Oracle의 ojdbc14.jar 아티팩트의 경우 디펜던시로 추가하려고 m2eclipse에서 설정하면 잘 설정이 되지만, 실제 아티팩트인 ojdbc14.jar가 메이븐 중앙 레포지토리에 없어서 아티팩트가 없다는 에러가 발생합니다.

Oracle이 ojdbc14.jar를 메이븐 중앙 레포리토리를 통하여 배포하지 않는것은 여러가지 이유가 있을 수 있지만.. 메이븐 프로젝트를 구성하여 사용하는 경우에 일일이 아티팩트를 로컬 레포지토리에 인스톨하여 사용한다는것 자체가 귀찮고 개발자간 버전 불일치 문제가 있을 수 있습니다.

이때는 메이븐 중앙 레포지토리 외에 다른 레포지토리를 추가하여 간단하게 해결할 수 있습니다.

pom.xml에 다음과 같이 새로운 레포지토리를 하나 더 추가합니다.
<repository>
    <id>mesir-repo</id>
    <url>http://mesir.googlecode.com/svn/trunk/mavenrepo</url>
</repository>

그리고 다음과 같이 Oracle ojdbc14.jar 아티팩트를 위한 디펜던시를 설정합니다.
<dependency>
  <groupId>com.oracle</groupId>
  <artifactId>ojdbc14</artifactId>
  <version>10.2.0.4.0</version>
</dependency>

자 어떠세요~ 쉽게 ojdbc14.jar를 사용하실 수 있으시죠~ 언릉 Oracle이 메이븐 중앙 저장소에 ojdbc14.jar의 아티팩트를 올려주었으면 좋겠습니다. ;-)

참고로 이 자료는 http://www.jroller.com/mert/entry/oracle_s_ojdbc14_jar_mesir 를 참고하였습니다.
저작자 표시 비영리
신고

WRITTEN BY
jangsunjin
전세계 사람들의 삶의 질을 높일 수 있는 소프트웨어를 만들어 함께 나누는 것이 꿈입니다. 이 세상 그 무엇보다 사람이 가장 소중합니다.

받은 트랙백이 없고 , 댓글  3개가 달렸습니다.
  1. 감사합니다
    도움이 되었습니다 ^^
  2. 저작권법 위반.
  3. 추가했는데도 안되네요 ㅠㅠ
secret

JavaServer Faces에서는 입력되는 값들을 변환(Conversion)하고 검증(Validation)할 수 있는 표준적인 방안을 제공하고 있습니다.

이 방안을 통하여 여러분들은 언제나 쉽고 빠르게, 그리고 가장 중요한 점은 동일한 형태의 변환이나 검증을 할 경우 미리 만들어 놓은 검증기나 변환기를 재사용(Reuse)하여 원하는 어플리케이션을 보다 쉽고 빠르게 구축하실 수 있습니다.

이에따라 간략하게 JSF의 변환과 검증에 대하여 살펴보고자 합니다. 본 문서는 IBM developersWors의 JSF for nonbelievers: JSF conversion and validation라는 자료를 바탕으로 작성하였으며, Apress의 Pro JSF and AJAX란 책도 일부 참고하여 작성하였습니다.

 

여기서 중요한 점은 변환이란 무었이고 검증이란 무었인가?라는 것입니다.

변환이란 다음과 같은 것을 의미합니다.

  • String 값을 java.util.Date 객체로 변환하는 것입니다.
    즉 "20090107"이란 String 객체를 Date("20090107") 객체로 변환하는 것을 객체변환이라고 합니다.
  • String 값을 double으로 변환하는 경우도 있습니다.
    예를들어 "3.14159"란 String을 double pi = 3.14159로 사용하고 싶다면 타입변환을 하여야 합니다.

이러한 예를 통하여 변환이란 결국 객체를 다른 객체로 변환하거나, 객체를 다른 타입으로 변환하거나, 타입을 객체로 변환하는 것을 의미합니다.

 

그렇다면 검증이란 무었을 의미할까요? 예를 통하여 확인하여 보면 다음과 같습니다.

  • java.util.Date가 "yyyy-MM-dd HH24"와 같은 형식(format)인가? 를 확인하는 작업이 검증하는 작업입니다.
  • float의 값이 3.0에서 4.0 사이인지 확인하여 한다면 검증하여야 합니다.

이와 같이 검증은 무었인가의 값의 형식(format)이나 범위 등을 확인하는 작업입니다.

만약 검증하여야 할 대상의 형식이 복잡하다면 정규식(Regular Expression)을 이용하여 검증하실 수 있으며, 각 조건에 맞는 검증기 클래스(Validator Class)를 작성하실 수 있습니다.

 

변환(Conversion)과 검증(Validation)을 이해하였다면 JSF의 생명주기(Lifecyle)에 대하여 살펴볼 필요가 있습니다.

이 단계를 살펴보면 "Apply request values" 단계 후에 "Process Validations" 단계를 거치게 되어 있습니다. 이는 JSF를 바탕으로 구현된 어플리케이션의 경우 기본적으로 입력받은 값들을 검증하는 단계를 거치도록 되어 있다는 것입니다.

변환과 검증의 가장 중요한 목적은 모델을 업데이트하기 전에 값들이 정확한지 보장하기 위한 것입니다.

따라서 여러분들이 JSF를 사용하여 검증 및 변환을 한다면, JSF는 여러분들이 정의한 변환 규칙에 맞게 변환되는지 확인하고 변환할 것이며, 여러분들이 만든 검증 규칙에 맞는지 확인할 것입니다. 뭐 다른 Web 관련 UI Framework도 이런 규칙을 따르고 있잖아? 라고 말한다면 그 지적은 맞습니다. 하지만 JSF의 검증 및 변환에 관련된 라이프사이클을 조금 더 자세히 살펴본다면 약간 더 진보적이라는 것을 확인할 수 있습니다.

 

상기 그림에서도 나와 있듯이 JSF의 생명주기에서 "Apply Request Values" 단계에서 기본적인 변환이 일어납니다. 아울러 사용자가 정의한 변환도 이 때 일어납니다. 이는 다른 UI 관련 프레임웍과 차별화된 부분입니다.

JSF에서는 기본적으로 요청된 값들을 적용할때 값들을 객체로 변환하거나 지정된 타입으로 변환합니다. 거의 모든 다른 UI 프레임웍에서는 그냥 String 값인 상태로 전달되지만 JSF는 비즈니스 로직에 맞는 모델에 맞는 객체나 타입으로 변환시켜줌으로써 모델의 들어가는 값의 안전성과 신뢰성을 높입니다.

이는 중요한 사항입니다. 여러분은 아직도 HttpServletRequest 객체에서 request.getParameter("XXX");를 통해서 View에서 전달된 값을 일일이 받아서 사용하거나, Spring MVC를 사용한다면 조금 더 향상은 되었겠지만 거의 비슷한 방법으로 View에서 전달된 값을들 Business Logic이 담긴 Controller와 같은 클래스로 넘기고 있을 것입니다.

Spring Framework을 사용한다고 하여 값의 변환을 자동으로 시켜주지는 않습니다. 이것이 다른 UI 프레임웍과 JSF의 가장 근본적인 차이점중에 하나입니다.

아울러 JSF는 변환 단계 후 검증 단계를 실시합니다.

이 검증 역시 표준적인 검증과 사용자 정의 검증을 통하여 값들을 형식이나 범위등을 확인합니다. 검증할 범위가 특이하거나 일반적이지 않은 형식을 검증하여야 할 경우에는 사용자 정의 검증을 할 수 있습니다.

한가지 주의하여야 할 점은 javax.faces.component.UIInput을 상속받은 javax.faces.component.html.HtmlInputText나 javax.faces.component.UISelectOne 컴포넌트의 경우 immediate라는 속성을 true라고 지정하면 아래 그림과 같이 JSF의 생명주기가 바뀝니다.

immediate 속성의 기본값은 false인데, true로 설정하면 상기 그림과 같이 "Apply Request Values"에서 변환과 검증을 합니다.

immediate 속성에 대한 자세한 내용은 다음에 다루겠습니다. 당근 값을 즉시 전달하는데 사용하는 옵션입니다.

 

다음에는 JSF의 변환에 대하여 자세하게 알아보겠습니다. 먼저 확인하고 싶으신 분은 IBM developersWors의 JSF for nonbelievers: JSF conversion and validation라는 자료를 보시기 바랍니다. 설명이 참 잘되어 있습니다.

감사합니다. ;-)

신고

WRITTEN BY
jangsunjin
전세계 사람들의 삶의 질을 높일 수 있는 소프트웨어를 만들어 함께 나누는 것이 꿈입니다. 이 세상 그 무엇보다 사람이 가장 소중합니다.

받은 트랙백이 없고 , 댓글이 없습니다.
secret
JSF(JavaServer Faces)의 경우 Rederer 를 바꿀 수 있습니다. Rederer를 바꿀 수 있다는 의미는 하나의 컨텐츠를 다양한 형태로 바꿀 수 있다는 것을 의미합니다.
즉  하나의 HTML 문서를 MS Word로 바꾸거나 PDF로 바꿀 수 있다는 거죠.

최근 SVG에 대한 관심이 높아지면서 JSF + SVG에 대한 글이 있어서 공유차원에서 올립니다. 이미 Adobe Flex와 연동이 되고 있습니다. 나중에 한번 다루겠습니다.

개인적으로는 Flex나 SVG와 같은 벡터 그래픽을 Rich UI로 사용하는 것에 관심이 많습니다. 앞으로 점 더 연구해볼 가치가 있을 것 같습니다. :-)

출처: https://www.dimis.fim.uni-passau.de/~doeller/research_projects/sw_internship/Pfnuer/Praktikum.pdf


신고

WRITTEN BY
jangsunjin
전세계 사람들의 삶의 질을 높일 수 있는 소프트웨어를 만들어 함께 나누는 것이 꿈입니다. 이 세상 그 무엇보다 사람이 가장 소중합니다.

받은 트랙백이 없고 , 댓글이 없습니다.
secret
최근 Hibernate 3.x를 이용하여 개발을 하고 있습니다. 예전에 Hibernate 2.x를 사용하였을때과 가장 큰 차이점이 Hibernate Annotations(http://www.hibernate.org/hib_docs/annotations/reference/en/html_single/)이 도입되었다는 점입니다.

아~ 정말 편리해졌습니다. hbm.xml을 손수 고칠때와는 완전히 다르더군요 ;-)

Hibernate 3.x에서 Annotation이 대폭 강화되면서 이제 정말 Hibernate를 편리하게 사용해볼만 할것 같다는 생각이 듭니다. 사실 Hibernate를 많이 다루지 않았기 때문에 깊숙히 알고 있지는 않습니다. 이번 기회에 Hibernate를 깊이 익혀볼 생각입니다.

우선 Hibernate Annotation의 기능중에 1대1관계(One-to-One)를 설정하는 부분에 대하여 살펴보고자 합니다.
원문은 http://www.hibernate.org/hib_docs/annotations/reference/en/html_single/#entity-mapping-association 입니다.

 



2.2.5. 엔티티빈의 연관관계 및 관계 매핑(Mapping entity bean associations/relationships)

2.2.5.1 1대1(One-to-one) 관계

@OneToOne 어노테이션을 사용하여 1대1 관계를 엔티티 빈에 연관관계를 설정할 수 있다. 1대1 관계를 설정하는 경우에는 3가지이다.

  1. 연관된 엔티티 빈이 같은 PK(Primary Key) 값을 공유하고 있을 때거나
  2. 다른 엔티티 빈에 FK(Foreign Key)를 가지고 있는 경우나 (주의: 이 FK 컬럼은 데이터베이스 안에서 반드시 유일성 제약조건constrained unique으로 설정되어 1대1 다중 관계를 가지는 경우이다.)
  3. 또는 연관 테이블에서 3개의 엔티티 사이의 연결을 위하여 링크를 저장하여 사용할 경우이다. (유일성 제약조건은 각 FK가 1대1 다중 관계를 보장하기 위하여 정의된다.)

첫번째로, 공유된 PK를 사용하여 실제로 1대1 연관관계를 지정해보자.

@Entity
public class Body {
    @Id
    public Long getId() { return id; }

    @OneToOne(cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    public Heart getHeart() {
        return heart;
    }
    ...
}

@Entity
public class Heart {
    @Id
    public Long getId() { ...}
}
1대1일 관계는 실제로 @PrimaryKeyJoinColumn 어노테이션을 사용하여 표기된다.

다음 예제는 FK 컬럼을 통하여 연관된 엔티티들이 관계를 맺는 경우이다.

@Entity
public class Customer implements Serializable {
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="passport_fk")
    public Passport getPassport() {
        ...
    }

@Entity
public class Passport implements Serializable {
    @OneToOne(mappedBy = "passport")
    public Customer getOwner() {
    ...
}

Customer 엔티티 빈은 Passport 엔티티 빈에 연결되어 있으며, Customer 테이블안에 passport_fk 라는 컬럼이 FK로 설정되어 있다. 

연결되는 컬럼은 @JoinColumn 어노테이션으로 정의되는데, @Column 어노테이션과 유사하다. 

@JoinColumn 어노테이션은 referencedColumnName 이라는 하나 이상의 인자(Parameter)를 가진다.이 인자는 연결관계를 맺을때 목적이 되는 엔티티의 컬럼을 지정하는데 사용한다.

referencedColumnName 를 PK가 아닌 컬럼에 사용할때는 연관되는 클래스는 Serializable을 구현하여야 한다는 점에 주의하자.

또한 referencedColumnName을 PK가 아닌 컬럼에 사용할때는 하나의 컬럼을 프로퍼티에 지정할 수 있다는 점에 주의하자.(다른 경우에는 아마 동작하지 않을 것이다.)

연관관계는 양방향성을 가질 것이다. 양방향성 관계는 어느 한쪽에서(또는 다른 쪽에서) 연관관계에 대한 소유권을 가지는 것이다. 소유권을 가진 소유가자되면 연관관계가 있는 컬럼(join column)을 업데이트를 위한 책임을 가진다.

이러한 관계에서 한쪽의 책임을 회피시키려면 mappedBy 속성을 사용하면된다. mappedBy는 소유권을 가진 쪽에서 연관관계를 맺는 프로퍼티 명을 참조한다. 예제에서는 passport가 이런 경우이다.

여러분이 확인한바와같이 소유권을 가진 다른 한쪽에서 이미 정의하였다면 연관관계를 가지는 컬럼(join column)을 정의할 필요가 (반드시) 없다.

만약 @JoinColumn 을 사용하지 않고 소유권을 가진 다른 한쪽을 정의한다면, 기본값이 적용된다. join column은 소유자의 테이블에서 생성될 것이며, 이름은 소유자 측의 관계의 이름의 연속이 될 것이다.

즉 “_”를 사용하여 “관계명_관계명” 과 같은 컬럼명을 가지게 될 것이며, 소유자 측의 PK 컬럼의 이름이다.

이 예제의 경우 passport_id는 프로퍼티명이 passport이고 Passport 엔티티빈의 컬럼 ID가 id라는 것을 나타낸다.

세번째 가능한 경우는 연관 테이블(매핑 테이블)을 이용하는 매우 낮선 경우이다.

@Entity
public class Customer implements Serializable {
    @OneToOne(cascade = CascadeType.ALL)
    @JoinTable(name = "CustomerPassports",
        joinColumns = @JoinColumn(name="customer_fk"),
        inverseJoinColumns = @JoinColumn(name="passport_fk")
    )
    public Passport getPassport() {
        ...
    }

@Entity
public class Passport implements Serializable {
    @OneToOne(mappedBy = "passport")
    public Customer getOwner() {
    ...
}

CustomerPassportCustomerPassports라는 이름의 연관 테이블을 통하여 연결되어 있다. 이 연관테이블은 passport_fk라는 FK를 Passport테이블을 지정하기 위하여 가지고 있다. (inverseJoinColumn에 의하여 구체화되며, Customer 을 지정하기 위하여 customer_fk라는 이름의 FK를 joinColumns 속성에 의하여 구체화하였다.)

여러분은 반드시 이러한 매핑시  연관관계가 있는 테이블명과 컬럼(join column)을 명시적으로 정의하여야 한다.




다음에 계속 이어나가겠습니다.

한가지 궁금한게 아직 국내에서 Hibernate Annotation 문서를 번역한게 없나요? 아직 제가 못찾았는데... 번역된것이 있을듯도 한데.. 중요한 부분만 번역하려고 하는데.. 문서가 있다면 굳이 할 필요는 없을듯 합니다.

만약 Hibernate Annotation에 대한 국내문서를 알고 계신 분이 있으시다면 알려주시기 바랍니다.

감사합니다. :-)

신고

WRITTEN BY
jangsunjin
전세계 사람들의 삶의 질을 높일 수 있는 소프트웨어를 만들어 함께 나누는 것이 꿈입니다. 이 세상 그 무엇보다 사람이 가장 소중합니다.

받은 트랙백이 없고 , 댓글이 없습니다.
secret
Oracle의 기술백서중에서 "JavaServer Faces, Ajax, Flash: 차세대 사용자 인터페이스"라는 좋은 글이 있어서 공유차원에서 올립니다.

몇년전부터 JSF를 간혹 사용하여 오다가 최근 제가 맡은 프로젝트에서 본격적으로 활용하고 있습니다.

앞으로 JSF에 대한 좋은 글들을 올리겠습니다.

그럼 우선 Oracle의 문서부터 한번 살펴보시죠 :-)


신고

WRITTEN BY
jangsunjin
전세계 사람들의 삶의 질을 높일 수 있는 소프트웨어를 만들어 함께 나누는 것이 꿈입니다. 이 세상 그 무엇보다 사람이 가장 소중합니다.

받은 트랙백이 없고 , 댓글이 없습니다.
secret
JSF(JavaServer Faces)로 개발을 하다보면 JSP(JavaServer Pages)에서 가장 많이 사용하였던 request.getContextPath()를 EL(Expression Language)로 어떻게 표기해야 할지 막막할때가 있습니다.

특히 JSF의 경우 EL을 바탕으로  UI 관련 개발을 하기 때문에 EL에 익숙하지 않으신 분들의 경우 더더욱 그렇습니다.

가장 많이 사용되는 EL 중에 다음과 같은 표기식이 있습니다.

#{facesContext.externalContext.requestContextPath}

HttpServletRequest.getContextPath()와 같은 의미입니다.

이 외에도 facesContext의 externalContext에는 SessionMap이나 RequestMap과 같은 유용한 객체들이 많습니다. 한번씩 확인해보시기 바랍니다.

혹시 EL을 쓰시면서 궁금하신 부분들이 있으면 댓글달아주시면 최대한 알려드리겠습니다. ;-)
신고

WRITTEN BY
jangsunjin
전세계 사람들의 삶의 질을 높일 수 있는 소프트웨어를 만들어 함께 나누는 것이 꿈입니다. 이 세상 그 무엇보다 사람이 가장 소중합니다.

받은 트랙백이 없고 , 댓글이 없습니다.
secret

Java의 메소드 인라인(Method Inline)에 관한 좋은 글이 있어서 공유하고자 올립니다.
기회가 있을때 마다 Java의 이해라는 글을 올리고자 합니다.
이 글은 The Java HotSpot Performance Engine: Method Inlining Example 을 바탕으로 작성하였습니다.

 

Java에서는 성능 향상을 위하여 Java HotSpot Engine(VM)이 다음과 같은 경우 메소드 인라이닝(Method Inlining)을 합니다. 이를 통해서 메소드를 호출할때 실제 메소드를 호출하지 않고 바로 결과값을 돌려주어, JVM(Java Virtual Machine)의 성능을 향상시킵니다.

class A {
  final int foo() { return 3; }
}


A라는 클래스(Class)가 있고 다른 클래스에서 에서 foo()라는 메소드를 호출하면 당연히 3이라는 값이 리턴됩니다. 왜냐하면 이 클래스는 final이라는 키워드 때문에 변경할 수 없는 값을 리턴하기 때문입니다. 특히 final이라는 키워드를 사용하는 경우 int foo()를 오버라이드 할 수 없습니다.

이에따라 Java HotSpot VM은 final int foo() 메소드를 상수 3으로 교체하여 성능을 향상 시킵니다.

HopSpot이 이와 같이 메소드를 상수로 교체하는 것을 메소드 인라이닝(Method Inlining)이라고 부릅니다.
메소드 인라이닝은 다음과 같은 효과가 있습니다.

  1. 메소드 호출(Method call)을 하지 않습니다.
  2. 동적인 디스패치(Dynamic dispatch)를 하지 않습니다.
  3. 값에 대한 상수 연산(constant-fold; 상수처럼 인식되어 바로 연산할 수 있도록하기 때문에 상수연산으로 번역합니다.)이 가능합니다. 예를 들어 “a.foo()+2” 의 결과값은 “5” 인데, 런타임(Runtime)시 a.foo() 메소드를 실행하지 않고 바로 “3 + 2” 연산으로 처리됩니다.


예전에는 이러한 이유로 프로그래머들이 종종 final이라는 키워드를 사용하였습니다. final이라는 키워드를 사용하여 실행 속도를 높이거나 큰 메소드안에서 작은 메소드를 통합하기 위하여 인라인 기능을 사용하였습니다.

하지만 이런 테크닉을 사용하면 프로그래밍 언어에서 완벽한 모듈화(modularization)를 할 수 없었으며, 재사용성(reusability)이 감소하게 됩니다.


하지만 Java HotSpot VM은 final이란 키워드가 없이도 메소드 인라이닝 테크닉을 사용할 수 있습니다.

class B {
  int foo() { return 3; }
}

이제 final이라는 키워드가 없으니 당연히 오버라이드가 잘 될 것입니다. 하지만 아래의 클래스 C와 같이 B 클래스를 상속하여 int foo() 메소드를 오버라이딩하는 경우는 어떻게 될까요? C 클래스 외에 D 클래스도 B 클래스를 상속받아 int foo() 메소드를 오버라이딩하였다면 어떻게 될까요?

class C extends B {
  int foo() { return 6; }
}


사실 B.foo()라는 인라이닝 메소드를 부르는 어떤 코드만 있다면 큰 문제는 없습니다. 왜냐하면 B 클래스는 다른 어떤 클래스로부터 상속받지 않았으며, int foo() 메소드 역시 오버라이딩 되어있지 않기 때문입니다.

가장 궁금한 경우는 다음과 같을 때입니다.

B bc2 = (B) c;
int numByBC2 = bc2.foo();
System.out.println("bc2.foo() is " + numByBC2);

결과 값이 3일까요 6일까요? 객체지향개념에 맞도록 메소드 인라인이 이루어 졌다면 당연히 6입니다. 실제로 테스트해본 결과 java version 1.6.0_07에서 정상적으로 6이 리턴되었습니다.


하지만 본 문서의 예처럼 단순한 경우만 있는 것이 아닙니다. 메소드 내에서 다른 메소드를 호출하는 등의 영향으로 결과값이 틀려질 때도 있습니다.

기본적으로 Java HotSpot VM은 이러한 문제를 해결하기 위하여 인라인 메소드 선택의 문제가 발생할 만한 부분을 감지하여 코드에 기록(the code makes)하여 놓습니다. 기록시에는 메소드 인라인의 결과값에 대한 가정(assumptions)을 기록합니다.

그리고 각 클래스들이 로딩되어 실행될 때 이러한 가정이 맞는지 확인합니다. 만약 경합이 발생하거나 다른 이유로 컴파일시의 가정이 맞지 않는다면 해당 메소드 인라인의 가정은 무시됩니다. 이를 디옵티마이즈(Deoptimized)되었다고 합니다.


제가 이해를 돕고자 예제를 만들어 보았습니다. 메소드 인라인에 대한 이해와 함께 상속에 대한 이해도 높이실 수 있을 것 같습니다.

메소드 인라인에 대하여 궁금하신 분들은 제가 첨부한 Java 파일을 다운로드하셔서 간단하게 테스트해보시기 바랍니다.



참고로 결과값은 다음과 같습니다.

 

Created A object!
Called foo() method in A object!
a.foo() is 1
-----------------------
Created B object!
Called foo() method in B object!
b.foo() is 3
-----------------------
Created B object!
Created C object!
Called foo() method in C object!
c.foo() is 6
-----------------------
Created B object!
Created C object!
Called foo() method in C object!
bc.foo() is 6
-----------------------
Called foo() method in C object!
bc2.foo() is 6

 

감사합니다. ;-)

신고

WRITTEN BY
jangsunjin
전세계 사람들의 삶의 질을 높일 수 있는 소프트웨어를 만들어 함께 나누는 것이 꿈입니다. 이 세상 그 무엇보다 사람이 가장 소중합니다.

받은 트랙백이 없고 , 댓글  2개가 달렸습니다.
  1. 어라 왜 이글은 피드가 안오지 ㅎ
    아무래도 자바니깐 넌 이해못하니깐 안봐도 돼! 하면서 안오는 걸까요 :)

    뭐... 사실 잘 이해 못하겠어요!
    • 윈도우 라이브 라이터로 작성해서 그런것 같습니당~

      요넘에 정을 들이고 있는데~ 아직 완벽하게 사용을 못하고 있나보네요~

      대부분 관심이 많은 부분이 아니라서 이번에 정리차원에서 올렸는데~ 나중에 더 자세하게 정리해드릴께요~

      감사합니당 :)
secret