기본적으로 배포 하는 방법에 대해서는 앞서 설명 하였다.


Tomcat War Deploy 하기 (http://blog.whitelife.co.kr/240)


이해가 안되는 경우 위 글을 참고하기 바란다.


항상 Java Web Application 을 Build 하여 전체 배포를 할 수는 없다. 고객의 추가 요구 사항에 따라 프로그램 소스는 얼마든지 수정 될 수 있다.


JSP 파일만 수정되면 Restart 가 생략이 가능 하지만, 그 이외의 파일이라면 반드시 수행해야 한다.


  • server.xml
<Host name="localhost"  appBase="/home/users/parkmc/webapps"
    unpackWARs="false" autoDeploy="true" deployOnStartup="false">

<!-- SingleSignOn valve, share authentication between web applications
     Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->

<!-- Access log processes all example.
     Documentation at: /docs/config/valve.html
     Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
       prefix="localhost_access_log." suffix=".txt"
       pattern="%h %l %u %t &quot;%r&quot; %s %b" />

</Host>


War 압축된 상태가 아닌, Context 경로에 직접 파일로 배포 하는 경우에는 unpackWARs="false" 로 설정 해야 한다. 기본적인 경로는 /ROOT 이다. 개별 적으로 추가가 필요하다면, Context 를 추가 한다.


/ROOT
    /META-INF
    /WEB-INF
        /classes
        web.xml


위의 폴더 구조에 따라 배포를 진행 한다. 파일 복사가 끝났다면, /bin/startup.sh 를 하여 서버를 시작 하자.


Java Web Application 개발은 대부분 Eclipse 를 사용 해서 개발 한다. 소스 파일 작성은 확실히 편리 하다. 하지만 Tomcat 을 사용 할때 문제점 이 있다.


1. Class 파일의 로딩 지연 현상

개발 진행 중에 Start, Stop, reStart 를 하루에도 몇십번? 씩은 하고 있다. 서버가 Start 될 때 이런 문구를 발견 하게 된다. ClassNotFoundException, NoClassDefFoundError 확인 하기 위해 파일을 찾아 본다. 실제로 Class 가 있고, Build 도 되어 있다. 결국 Clean Tomcat Work Directory 를 하고 난 후에야 해결이 된다.



2. Java Library 충돌

최근에 프로젝트를 진행 하면서 경험한 부분 이다. dom4j 라이브러리를 사용 하는대 2가지 버전이 Dependency 되어 있었다. Eclipse Tomcat 사용 할 때는 정상적으로 동작 한다. 하지만 Maven Build 하여 서버에 적용 하면 아니러니 하게도 ClassCastException 이 발생 한다. 흔히 Local 개발 환경에서는 정상 동작 하는대 실제 서비스를 적용 하는 환경에서 발생 하는 에러의 일부분은 이와 같은 사례 이다.


mvn dependency:tree


라이브러리를 사용할 때 의존성에 대한 검사를 하는 습관을 갖게 되면 라이브러리 간에 충돌은 줄일 수 있다.


위 두가지 사례를 들었다. Eclipse 에서도 배포가 가능 하겠지만, 개발 환경이 항상 Eclipse 를 사용 하고 있을 수는 없을 것이다. Maven 은 직접 소스를 build 해서 war 로 만들 수 있다. 개발자가 불편을 감안 하고 직접 Tomcat 에 deploy 하여 실제 서비스 환경과 비슷한 환경에서 테스트를 진행 할 수 있고, 좀 더 편리한 환경에서 테스트를 하고 싶다면, Tomcat Plugin 을 사용하면 된다.


<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>tomcat-maven-plugin</artifactId>
    <version>1.1</version>
    <configuration>
        <mode>war</mode>
        <port>8080</port>
        <path>/</path>
        <charset>UTF-8</charset>
        <uriEncoding>UTF-8</uriEncoding>
    </configuration>
</plugin>


pom.xml 에 추가 하자.


mvn clean tomcat:run


packing 이 war 로 선언 되어 있다면, war 로 Build 한 후 서버가 시작 될 것이다.


D:\Project\workspace\whitelife>mvn clean tomcat:run -Denv=local
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building whitelife web application
[INFO]    task-segment: [clean, tomcat:run]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean {execution: default-clean}]
[INFO] Deleting directory D:\Project\workspace\whitelife\target
[INFO] Preparing tomcat:run
[debug] execute contextualize
[INFO] [resources:resources {execution: default-resources}]
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 28 resources
[INFO] Copying 5 resources
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 80 source files to D:\Project\workspace\whitelife\target\classes
[INFO] [tomcat:run {execution: default-cli}]
[INFO] Running war on http://localhost:8080/
[INFO] Creating Tomcat server configuration at D:\Project\workspace\whitelife\target\tomcat
2014. 11. 7 오전 11:29:16 org.apache.catalina.startup.Embedded start
정보: Starting tomcat server
2014. 11. 7 오전 11:29:16 org.apache.catalina.core.StandardEngine start
정보: Starting Servlet Engine: Apache Tomcat/6.0.29
2014. 11. 7 오전 11:29:16 org.apache.catalina.core.ApplicationContext log
정보: Initializing Spring root WebApplicationContext
2014-11-07 11:29:16,934  INFO ContextLoader - Root WebApplicationContext: initialization started


http://localhost:8080/ 에 접속 하여 확인 해보자.


위 방법을 사용 하면서 Eclipse 는 본연의 모습을 찾아 가는 것 같고, Maven 은 Project 에 대한 매니저 역할을 하는 것 같아 보인다.


개발자 마다 개인의 스타일이 있고, 편한 방법이 있다. 정답은 없지만, 본인이 편리하게 사용할 수 있는 방법으로 개발 하면 될 것이다.


Tomcat 이 사용 하는 JRE 설정이 초기화 되어 있기 때문에 발생 한다. Window > Preferences 를 보자. 

Server > Runtime Environments 에 접근하여 JRE 설정을 하자.



정상적으로 동작 할 것이다.


'Tools' 카테고리의 다른 글

Bootstrap Editor 소개  (0) 2014.11.13
Eclipse FindBugs 사용 하기  (2) 2014.11.12
Markdown, Editor 소개  (3) 2014.09.17
간단하게 프로그래밍 할수 있는 Cloud9 활용하기  (0) 2014.09.03
Vim 사용 시 euc-kr, utf-8 로 변환 하기  (0) 2013.12.14

Eclipse 에서는 정상적으로 동작 하지만, CUI 환경에서 Maven clean tomcat:run 하는 경우 Parameter 값을 인식 하지 못하여 예외 상황이 발생 한다.


테스트 했던 프로젝트는 SpringFramework 3.2.11.RELEASE, Tomcat 7.0 으로 작성 하였다.


Cannot create inner bean 'net.sf.log4jdbc.tools.Log4JdbcCustomFormatter#746c2814' of type [net.sf.log4jdbc.tools.Log4JdbcCustomFormatter] while setting bean property 'logFormatter'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'net.sf.log4jdbc.tools.Log4JdbcCustomFormatter#746c2814' defined in file [D:\Project\workspace\sample\target\classes\spring\db\datasource-context.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'margin' threw exception; nested exception is java.util.FormatFlagsConversionMismatchException: Conversion = s, Flags = #


예외가 발생 했기 때문에, Bean 을 생성 하지 못했다. Log4JdbcCustomFormatter margin 값이 인식이 되지 않았기 때문이다.


<beans:bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource">
    <beans:constructor-arg ref="dataSourceSpied" />
    <beans:property name="logFormatter">
        <beans:bean class="net.sf.log4jdbc.tools.Log4JdbcCustomFormatter">
            <beans:property name="loggingType" value="MULTI_LINE" />
            <!-- <beans:property name="margin" value="19" /> -->
            <beans:property name="sqlPrefix" value="SQL&#58;&#58;&#58;" />
        </beans:bean>
    </beans:property>
</beans:bean>


margin 값을 제외하고 테스트 해보자. 정상 동작 할 것이다.


'Maven' 카테고리의 다른 글

Maven Tomcat Plugin 사용 하기  (0) 2014.11.07
Eclipse에 Maven 연동 후 경고 창이 뜰 경우.  (0) 2012.11.12
Eclipse에서 Maven Project 생성하기  (0) 2012.11.09
Eclipse와 Maven 연동하기  (0) 2012.11.08

Java Web Application 은 build 하면 war 파일로 압축 되어 생성 된다. manager 기능을 사용하면 web page 에서 upload 하여 편리하게 deploy 할 수 있다. 하지만 기능이 제한되는 단점이 있다.


manager 기능을 이용한 배포는 해당 링크를 참고 하자. (http://blog.whitelife.co.kr/73)


직접 deploy 하려면 server.xml 파일을 설정 해야 하고, $CATALINA_HOME 환경 변수 설정이 되어 있어야 한다. tomcat 의 start, stop, deploy, undeploy 를 $CATALINA_HOME/bin/catalina.sh 가 담당 하는대, $CATALINA_HOME 가 정의 되어 있지 않으면, 아무 동작도 할 수 없다.


windows 는 고급 시스템 설정에 환경 변수, linux 는 home directory 의 ~/.bashrc 파일에 추가 하자.


  • 환경 변수



  • ~/.bashrc

# User specific aliases and functions

export JAVA_HOME=/home/whitelife/java
export CATALINA_HOME=/home/whitelife/tomcat
export PATH=$PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin



server.xml 은 $CATALINA_HOME/conf 에 있는대, 이 정보를 기반으로 tomcat 은 동작 한다.


  • server.xml
<Host name="localhost"  appBase="webapps"
    unpackWARs="true" autoDeploy="true">

    <!-- SingleSignOn valve, share authentication between web applications
         Documentation at: /docs/config/valve.html -->
    <!--
    <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
    -->

    <!-- Access log processes all example.
         Documentation at: /docs/config/valve.html
         Note: The pattern used is equivalent to using pattern="common" -->
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
           prefix="localhost_access_log." suffix=".txt"
           pattern="%h %l %u %t &quot;%r&quot; %s %b" />

    <!--<Context docBase="static" path="/static" reloadable="true"/>-->
    <Context docBase="test" path="/" reloadable="true"/>

</Host>


appBase, docBase 에 대해 알아야 구체적인 설정을 할 수 있다. appBase 는 상대 경로로 적용 되어 있으면, $CATALINA_HOME/webapps 를 참조 한다. 설치 후 고양이 마크를 볼 수 있는 화면도 하위 폴더인 /ROOT 에 있다. 만약 다른 경로를 사용하고 싶다면, 절대 경로로 설정 한다. docBase 는 appBase 하위 폴더 설정 이라고 보면 되는대, 기본적으로 appBase 에 ROOT Web Application 이 deploy 된다. 추가 적으로 deploy 하는 경우에 사용한다고 보면 이해가 될 것이다. 그 때 사용하는 tag가 context 이다.


docBase: appBase 하위 경로
path: host 뒤에 정의 되는 prefix (ex: path=”/test”, http://localhost:8080/test)
reloadable: class 파일 수정 시 redeploy 여부


deploy 를 예로 들면, appBase 경로에 docBase 이름을 가진 test.war 파일을 복사 하고, $CATALINA_HOME/bin 에 있는 startup 을 실행 한다. windows 인 경우 확장자는 bat, linux 인 경우 sh 로 한다. 서버가 시작 되면, 압축이 풀리면서 deploy 가 진행 된다.


테스트 페이지에 접속 하면 deploy 여부를 확인 할 수 있을 것 이다.


지금부터는 경험담 이다. appBase 를 상대경로로 하고, docBase 에 원하는 Web Application 을 deploy 했다. 문제점이 생길떄도 있고, 아닌 경우도 있었다. ROOT Web Application 으로 인식 하고 최초에는 ROOT 로 deploy 하고, 그 후에 deploy 를 한다. 두번 deploy 되어 라이브러리 충돌 하는 경우가 생겼다. 최근에 참 두려운 Exception 으로 자리잡은 ClassCastException 이다. Class는 존재 하는대, 무엇으로 Cast 할지 판단을 하지 못하여 발생 하는 것 같다. 정말 충돌 나는 지 확인을 위해 두가지 테스트를 했다.


  1. war deploy
  2. war 압축을 풀고 수동 deploy

2번 방법으로 했을때에는 이미 압축이 풀려 있기 때문에, ROOT deploy 를 하지 않았다. 정상 동작 하였다.


해결을 위해서는 appBase 만 설정 하고, ROOT.war 로 파일 명을 지정하여 deploy 하거나, 압축을 풀고 직접 수동으로 deploy 하면 된다. 취향에 따라 방법을 선택 하자.


Maven 을 사용 하는 경우에는 pom.xml 파일에 finalName 을 추가하여 mvn package 하면 원하는 파일명으로 war 파일을 얻을 수 있다.


<build>
    <finalName>ROOT</finalName>
</build>


Tomcat의 Servlet 개발 시 HttpSession 클래스를 사용 한다. Session Timeout 설정을 위해서는, setMaxInactiveInterval(int interval) 함수를 사용해서 개별적으로 정해줄 수 있지만, 공통으로 사용할 수 있게 설정을 하는 편이 좋다. web.xml 에 아래 샘플을 추가 하자.


<session-config>
    <session-timeout>30</session-timeout>
</session-config>


session-timeout 은 분 단위로 설정 된다. 30 이라고 선언했다면 getSession() 할때 마다 Session 유효 시간은 30분 이다.

session 이 created, destoryed 되는 것을 확인 하고 싶을 때가 있을 것이다. HttpSessionListener 를 구현하면 확인이 가능하다.


  • HttpSessionCheckingListener.java
public class HttpSessionCheckingListener implements HttpSessionListener {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public void sessionCreated(HttpSessionEvent event) {
        if (logger.isDebugEnabled()) {
            logger.debug("Session ID".concat(event.getSession().getId()).concat(" created at ").concat(new Date().toString()));
        }
    }

    public void sessionDestroyed(HttpSessionEvent event) {
        if (logger.isDebugEnabled()) {
            logger.debug("Session ID".concat(event.getSession().getId()).concat(" destroyed at ").concat(new Date().toString()));
        }
    }
}


위 파일을 web.xml 에 등록 할 차례다.


<listener>
    <listener-class>kr.co.whitelife.web.mvc.listener.HttpSessionCheckingListener</listener-class>
</listener>


Tomcat Start 한 후 로그를 살펴 보자. 생성되는 부분, 소멸되는 부분 확인이 가능하다.


created
2014-10-07 14:06:05,957  DEBUG HttpSessionCheckListener - Session IDD31C36AE223F8C14BB1087F6BFCEBD35 created at Tue Oct 07 14:06:05 KST 2014
destroyed
2014-10-07 14:08:06,068  DEBUG HttpSessionCheckListener - Session IDD31C36AE223F8C14BB1087F6BFCEBD35 destroyed at Tue Oct 07 14:08:06 KST 2014

참고 사이트


Tomcat Work Directory 를 초기화 한다. Eclipsc 의 경우 Servers > 마우스 오른쪽 > Clean Tomcat Work Directory 클릭, 서버를 재 시작 하자.


Tomcat7은 설치 되어 있다고 가정 한다. War 파일도 준비해야 한다.


Step 1.  Admin 계정 만들기

D:\Develop\was\tomcat\apache-tomcat-7.0.35\conf\tomcat-users.xml 파일을 수정 하자.



<?xml version='1.0' encoding='utf-8'?>

<!--

  Licensed to the Apache Software Foundation (ASF) under one or more

  contributor license agreements.  See the NOTICE file distributed with

  this work for additional information regarding copyright ownership.

  The ASF licenses this file to You under the Apache License, Version 2.0

  (the "License"); you may not use this file except in compliance with

  the License.  You may obtain a copy of the License at


      http://www.apache.org/licenses/LICENSE-2.0


  Unless required by applicable law or agreed to in writing, software

  distributed under the License is distributed on an "AS IS" BASIS,

  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

  See the License for the specific language governing permissions and

  limitations under the License.

-->

<tomcat-users>

<!--

  NOTE:  By default, no user is included in the "manager-gui" role required

  to operate the "/manager/html" web application.  If you wish to use this app,

  you must define such a user - the username and password are arbitrary.

-->

<!--

  NOTE:  The sample user and role entries below are wrapped in a comment

  and thus are ignored when reading this file. Do not forget to remove

  <!.. ..> that surrounds them.

-->

<!--

  <role rolename="tomcat"/>

  <role rolename="role1"/>

  <user username="tomcat" password="tomcat" roles="tomcat"/>

  <user username="both" password="tomcat" roles="tomcat,role1"/>

  <user username="role1" password="tomcat" roles="role1"/>

-->

<role rolename="manager-gui" />

      <user username="min" password="min" roles="manager-gui" />


</tomcat-users>



관리자에 해당하는 권한을 주고 아이디를 생성 했다.


Step 2.  서버 시작 하기


  • Windows -> D:\Develop\was\tomcat\apache-tomcat-7.0.35\bin\startup.bat
  • Linux -> D:\Develop\was\tomcat\apache-tomcat-7.0.35\bin\startup.sh

OS에 맞는 파일을 실행 한다. 


2013. 2. 1 오후 3:04:24 org.apache.catalina.core.AprLifecycleListener init
정보: Loaded APR based Apache Tomcat Native library 1.1.24 using APR version 1.4.6.
2013. 2. 1 오후 3:04:24 org.apache.catalina.core.AprLifecycleListener init
정보: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true].
2013. 2. 1 오후 3:04:24 org.apache.catalina.core.AprLifecycleListener initializeSSL
정보: OpenSSL successfully initialized (OpenSSL 1.0.1c 10 May 2012)
2013. 2. 1 오후 3:04:25 org.apache.coyote.AbstractProtocol init
정보: Initializing ProtocolHandler ["http-apr-8080"]
2013. 2. 1 오후 3:04:25 org.apache.coyote.AbstractProtocol init
정보: Initializing ProtocolHandler ["ajp-apr-8009"]
2013. 2. 1 오후 3:04:25 org.apache.catalina.startup.Catalina load
정보: Initialization processed in 1208 ms
2013. 2. 1 오후 3:04:25 org.apache.catalina.core.StandardService startInternal
정보: Starting service Catalina
2013. 2. 1 오후 3:04:25 org.apache.catalina.core.StandardEngine startInternal
정보: Starting Servlet Engine: Apache Tomcat/7.0.35
2013. 2. 1 오후 3:04:25 org.apache.catalina.startup.HostConfig deployWAR
정보: Deploying web application archive D:\Develop\was\tomcat\apache-tomcat-7.0.35\webapps\ROOT.war
2013. 2. 1 오후 3:04:26 org.apache.catalina.startup.HostConfig deployDirectory
정보: Deploying web application directory D:\Develop\was\tomcat\apache-tomcat-7.0.35\webapps\docs
2013. 2. 1 오후 3:04:26 org.apache.catalina.startup.HostConfig deployDirectory
정보: Deploying web application directory D:\Develop\was\tomcat\apache-tomcat-7.0.35\webapps\examples
2013. 2. 1 오후 3:04:26 org.apache.catalina.startup.HostConfig deployDirectory
정보: Deploying web application directory D:\Develop\was\tomcat\apache-tomcat-7.0.35\webapps\host-manager
2013. 2. 1 오후 3:04:26 org.apache.catalina.startup.HostConfig deployDirectory
정보: Deploying web application directory D:\Develop\was\tomcat\apache-tomcat-7.0.35\webapps\manager
2013. 2. 1 오후 3:04:26 org.apache.coyote.AbstractProtocol start
정보: Starting ProtocolHandler ["http-apr-8080"]
2013. 2. 1 오후 3:04:26 org.apache.coyote.AbstractProtocol start
정보: Starting ProtocolHandler ["ajp-apr-8009"]
2013. 2. 1 오후 3:04:26 org.apache.catalina.startup.Catalina start
정보: Server startup in 1546 ms


Step 3.  관리자 페이지 접속 하기

따로 설정을 하지 않았다면 http://localhost:8080/manager 로 접속 한다.



방금 만들었던 Admin 계정을 입력 한다.



위와 같은 페이지가 뜨면 성공 이다. Applications 현황이나, Server Status를 볼 수 있다. 


Step 4.  War Deploy 하기

스크롤을 내리다 보면 아래와 같은 메뉴가 있다.



실행 절차


  1. 찾아보기 버튼을 클릭하여 War 파일을 추가 한다.
  2. Deploy 버튼을 클릭 한다.

참고) War 파일의 이름이 Context Path 가 된다. 아래 그림에 /whitelife 라고 추가 된 것을 볼 수 있다.



2013. 2. 1 오후 3:18:11 org.apache.catalina.startup.HostConfig deployWAR

정보: Deploying web application archive D:\Develop\was\tomcat\apache-tomcat-7.0.35\webapps\whitelife.war



정상적으로 Deploy가 된 경우, Applications 제일 밑에 추가 된 것을 볼 수 있다.

상황에 따라서 해당 Application을 Stop, Reload, Undeploy 할 수 있다.


Step 5.  Hello World !!! 확인하기


위 페이지가 떳다면 성공이다. 


+ Recent posts