2010년 9월 17일 금요일

꽤 괜찮은 프로젝트 관리 툴! (Project Mgt tool ...

Project Mgt tool - qdPM & dotProject

Web based project mgt tool 중, 분명 공개소스가 있을 것이여~~~~~
...하고선 여기저기를 찾아 돌아다녔는데 처음에 발견한 것이 dotProject 이다...
신선한 느낌과 함께 "쓸만하다"란 생각을 가지게 만들어줬었다!
이후 관심을 가지고 좀 더 깊이 파고 들어가보니....
약간의 아쉬운 부분들이 발견 되었고 dotProject는 더 이상 update가 없는 개발멈춰버린 죽은project로 보인다.
완성도가 높고 보다 강력하기로는 pdPM이 좋은 것 같다.


찬찬히 들여다 보니 꽤나 유용한 개념을 담고 있었고
크게는 다음과 같은 Category를 가지고 있었다.

1. Projects Mgt 프로젝트 관리
2. Tasks Mgt
3. Tickets Mgt
4. Reprots Mgt
5. User Mgt

실제로 설치해서 돌려 보니 회사별 프로젝트 관리가 가능했고
MS Project와 같은 개념으로 worksheet를 생성할 수 있었다.
글구... My page가 나름 잘 구성되어 있어서
자신에게 할당된 job, event, wbs, worksheet, tickets만을 filtering해서 보여주는 것이 인상적이었다.
더불어 CSR(Customer Service Request), (Trouble Tickets, Change Request) 등을 관리할 수 있다는 점도 인상적이었고
그리고 각각에 대해서 Forum을 만들 수 있다는 것도 매우 매력적이었다.

다만 어떤 Service를 request할 때 참조파일을 첨부하거나 캡쳐와 함께 상황설명하기 마련인데
WebEditor가 좀 빈약했다. 단순히 textArea를 사용해서 그림을 넣어서 표현할 수가 없었고
파일첨부등은 별도의 Category에서 관리하기 때문에 일장일단이 있었다.

설치는 매우 쉬운편이고 자동화가 되어 있어서 별다른 조작 없이도
자신의 PC 설치해 볼 수가 있다.


이를 설치하기 위해서는 다음과 같은 준비물들이 필요하다....

1. APMSETUP7_2010010300.exe -> 편리하게 한 방에 아파치, PHP, MySQL5.1 을 설치해 준다...
2. 각각의 사이트에서 설명도 좀 읽고... demo도 보시고... 소스도 다운 받는다...
    1) dotProject - http://www.dotproject.net/
    2) qdPM -  http://qdpm.net/

3. 다음과 같이 받은 소스를 압축을 풀고 아래와 같이 위치시킨다.
  
이미지를 클릭하시면 원본크기로 보실수 있습니다.



4
각각 압축을 풀고 안에 있는 dotproject 폴더랑 qdpm만 copy해서
아파치의 context root디렉토리인 htdocs 디렉토리로 가져 갑니다.
이미지를 클릭하시면 원본크기로 보실수 있습니다.


아래 install.html 을 꼭~ 확인하세요!
설치 및 문제해결과 관련하여 잘 정리가 되어 있습니다.
이미지를 클릭하시면 원본크기로 보실수 있습니다.



5. 아파치 htdocs에 copy해서 위치시킨 모습....
이미지를 클릭하시면 원본크기로 보실수 있습니다.





왜 제가 한꺼번에 설명하고 있쪄? 이게 뭐하는 짓인겨???  ㅡ,.ㅡb....
자자... 지금부터 나누어서 다시 설명하겠습니다....
먼저 Dotproject 부터...


1. Dotproject  http://localhost/dotproject/install/
아래와 같은 그림이 나오면서 설치가 시작됩니다....
저의 경우는 이미 설치했기 땜시 start upgrade버튼이 보이는데
처음 설치하시는 분들은 start install이라는 버튼이 보이게 됩니다.
일단 이 버튼을 클릭하시면 이후 설치진행은 직관적이어서 쉽게 이해하고 설치하실 수 있습니다.
이미지를 클릭하시면 원본크기로 보실수 있습니다.



설치가 끝나고 http://localhost/dotproject 를 입력하시면 아래와 같이 로그인 화면이 나옵니다.
최초 ID/PWD는 admin/passwd 입니당~
이미지를 클릭하시면 원본크기로 보실수 있습니다.


로그인 완료!!! 캬~~~~~~~~~~~~~~~~~~~ ^^
이미지를 클릭하시면 원본크기로 보실수 있습니다.


2. qdPM
1) DB및 table생성 - 압축을 풀었던 곳의 install.sql을 사용.
이미지를 클릭하시면 원본크기로 보실수 있습니다.

phpMyAdmin으로 pdpm 이라는 이름으로 db를 생성하고 해당 db내에 다음과 같이 install.sql을 import하여 table을 생성한다.
이미지를 클릭하시면 원본크기로 보실수 있습니다.




2) D:\APM_Setup\htdocs\qdpm\core\config에 아래 선택된 두 개의 파일을 열어서 수정합니다.
이미지를 클릭하시면 원본크기로 보실수 있습니다.

3) 각각 다음과 같이 수정....
이미지를 클릭하시면 원본크기로 보실수 있습니다.


이미지를 클릭하시면 원본크기로 보실수 있습니다.



4) 로그인합니다...
http://localhost/qdpm
최초 ID/PWD는 admin@localhost.com/admin 입니다.
참고로 이 계정으로 로그인하면 설정화면이 나옵니다.
별도의 계정을 생성하시고 해당 계정으로 다시 로그인하셔야만
아래와 같이 프로젝트를 생성할 수 있는 화면이 나옵니다...
이미지를 클릭하시면 원본크기로 보실수 있습니다.



5) 이제부터 열심히 PROJECT, TASK 등을 만드시고 일 하시면 됩니닷! ㅡ,.ㅡB
이미지를 클릭하시면 원본크기로 보실수 있습니다.


http://www.dude.co.kr





P 이경철님의 파란블로그에서 발행된 글입니다.

2010년 8월 31일 화요일

JAVA(J2SE 1.4.1) 메모리 영역 구조

1. Sun Microsystyems의 자바 HotSpot VM은 힙을 세 개의 영역으로 나누고 있다.
 힙의 세 영역은 다음과 같다:
 1) Permanent space: JVM 클래스와 메소드 개체를 위해 쓰인다.
 2) Old object space: 만들어진지 좀 된 개체들을 위해 쓰인다.
 3) New(young) object space: 새로 생성된 개체들을 위해 쓰인다.
New object space는 세 부분으로 다시 나누어진. 모든 새로 생성된 개체들이 가는 Eden, 그리고 그 개체들이 나이들게(Old) 되기 전에 가는 Survivor space(From, To) 1과 2가 있다.


2. Garbage Collector
프로그램은 프로그램을 진행하면서 데이터들을 저장하는 것이 필요하다. 데이터들은 모두 메모리에 저장이 되는데, 저장할 데이터가 있으면 메모리의 일정 공간을 할당받아서 사용하게 된다. 프로그램 내에서 사용하게 되는 메모리를 'heap'이라고 한다. 더 이상 사용되지 않는 데이터에게 메모리를 계속 할당해 주는 것은 메모리를 낭비하는 것이므로, 그 데이터가 사용하던 메모리를 회수하는 것이 필요하다. 이러한 사용되지 않는 메모리에 대한 회수를 'Garbage Collection'이라고 한다. 자바에서는 프로그램이 사용하는 메모리를 JVM(Java Virtual Machine)이 모두 관리한다.


3. OutOfMemory Error 및 해결방법
자바는 객체, 변수등의 생성과 동시에 메모리(Heap)를 차지하게 되고, 문제는 이 객체와 변수를 너무 많이 발생시킴으로 해서 현재 할당된 메모리(Heap)를 초과하게 된다
그래서 더이상 할당받을 메모리(Heap)가 부족하게 되면 OutOfMemory Error 발생하게 된다.
OutOfMemory Error 해결방법으로는 jdk1.4에서 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC 옵션을 사용한  GC한 상태의 Heap메모리 정보출력 한다. GC정보를 통하여 New, Old, Perm 등의 영역중 실제 어느 부분이 부족하여 OutOfMemory가 발생하는지 찾은후 부족한 영역의 충분하 size를조절해 주는 방법으로 해결할 수 있다.


4. Heap layout 할당에 영향을 주는 스위치들

5. New Generation 메모리 할당 공식
   Eden = NewSize - ((NewSize/(SurvivorRatio + 2)) * 2)
   From space = (NewSize - Eden)/2
   To space = (NewSize - Eden)/2

6. Old Generation 메모리 할당 공식
   Old = Xmx - MaxNewSize

7.  JVM 스위치 설정 예제
 1) 현재 http://www.affis.net 서비스는 2200개의 Jsp파일을 가지고 있고 주로 정적이 페이지들이므로      Jsp 파일 로딩에 필요한 Perm size 위주로 메모리 튜닝을 하였다.
 2) 현재 http://club.affis.net 서비스는 어플리케이션 동적이페이지들로 작성되어 있고 어플리케이션        처리에 필요한  New size 위주로 메모리 튜닝을 하였다.

8. 맺음말
OutOfMemory 발생한다면 GC로그를 찍어본다. 로그를 분석해보면 New(eden, from, to), Old, Perm 등의 영역중에서 GC가 발생해도  메모리 영역이 계속 100%로 할당되는 영역이 보일것이다. 부족한 영역에 충분한 size 메모리를 할당해 주면 OutOfMemory 해결 된다.
그러나 부족한 영역에 계속해서 메모리 할당을 해주어도 사용률이 100%가 나온다면 프로그램 누수일수 있으니 프로그램을 점검해 봐야 할 것이다.

http://www.dude.co.kr
P 이경철님의 파란블로그에서 발행된 글입니다.

2010년 8월 4일 수요일

tomcat에 context 추가하기!!!

이젠 뭘 하나 하려면...  기억이 나질 않는다.... 된장.. ㅠ.ㅜ

$Tomcat\conf\Catalina\localhost 의 위치에 Default 로 설치된 admin.xml 파일을 복사하여
파일명을 원하는 컨텍스트명으로 변경한다.

 이미지를 클릭하시면 원본크기로 보실수 있습니다.




예제와 같이 http://localhost:8080/client/와 같은 컨텍스트명을 원하면 client.xml로 한다.


client.xml 파일의 내용은 다음과 같다.

----[ client.xml  ]----------------------------------
<Context
    docBase="E:\workspace\eclipse\tomcatClient"
    privileged="true"
    reloadable="true">
</Context>

reloadable = true 는 클래스 변경시 자동반영 옵션이다..
--------------------------------------------------

docBase 의 위치는 소스파일(물리적인 공간) 의 위치를 입력한다.

Context 추가 후 테스트를 위해 JSP 파일을 생성한다.
테스트를 위한 index.jsp 파일의 소스는 다음과 같다.


----[ index.jsp ]-----------------------------------

<%@ page contentType="text/html; charset=euc-kr" %>
<HTML>
<HEAD>
<TITLE> New Context Client </TITLE>
</HEAD>
<BODY>
Hello New Context ~~~  client  : 안녕
<%
 out.println("ContextPath : " + request.getContextPath());
%>
</BODY>
</HTML>

--------------------------------------------------

위의 내용을 실행한 결과는 다음과 같다.

이미지를 클릭하시면 원본크기로 보실수 있습니다.



Context 추가 완료~!!

http://www.dude.co.kr


P 이경철님의 파란블로그에서 발행된 글입니다.

Do you know tomcat monitoring tool is that Lam...

아~~따라~ 역쉬... 찾아 보면 다~~ 있어!!!!! 핫~ ㅋㅋ
일단 해당 사이트는 여기... http://www.lambdaprobe.org/d/installation.shtml


글구... 설정법... 적을려고 했는데...
이 것도 누군가가 잘~ 설명을 해두셨네...  캬~~~~~~~

------------------------------------------------------------------------------------

압축 푸신 후에 war파일을 webapps에 올려주시고
conf디렉토리 밑에 있는 tomcat-users.xml 수정해주세요.

 

<?xml version='1.0' encoding='utf-8'?>
    <tomcat-users>
          <role rolename="manager"/>
          <role rolename="admin"/>

          <role rolename="poweruser"/>
          <role rolename="probeuser"/>
          <role rolename="poweruserplus"/>
          <user username="admin" password="admin" roles="manager,admin,poweruser,poweruserplus,probeuser"/>

          <user username="tomcat" password="s3cret" roles="manager,admin"/>

    </tomcat-users>           

 
그리고
 내컴퓨터>속성>고급>환경변수>시스템 변수 에 다음을 추가해 줍니다.

    JAVA_OPTS
    -Dcom.sun.management.jmxremote



아마 Lambda Probe 사이트가 현재 안 열리고 있다.
그냥 이 파일 다운 로드 해서 사용하면 됩니다.^^

사용법은

probe.war를 $tomcat_home/webapps 에 올려놓고 tomcat을 시작하면 됩니다.
http://localhost:8080/probe/index.jsp


출처: http://www.voiceportal.co.kr/418

http://www.dude.co.kr




P 이경철님의 파란블로그에서 발행된 글입니다.

Junit 사용법

Junit Test case, suit 는 java application 을 위해 존재하는 것들이다.
Java application 이 아니고 web servlet 을 테스트 하고 싶을 때 Servlet Test Case 위자드를
사용하여 파일을 생성해서 테스트 해볼수 있다.이미지를 클릭하시면 원본크기로 보실수 있습니다.

보는 바와같이 상속받는 TestCase 클래스가 ServletTestCase 로 바뀌었다.
그리고 선택 옵션들이 많아졌다.
이미지를 클릭하시면 원본크기로 보실수 있습니다.

위자드로 자동 생성된 소스이다.

 public class JunitServletTest extends ServletTestCase {
       public JunitServletTest(String arg0) {
             super(arg0);
       }

       protected void setUp() throws Exception {
             super.setUp();
       }
       public void testMain(){
       }
       public void begin(WebRequest request) throws Exception {
       }
       public void end(WebRequest request) throws Exception {
       }
}
아래소스는 상속받은 ServletTestCase 클래스의 내용이다. Servlet 테스트를 하기위해 필요한
httpServletResponse 등과 같은 http관련 클래스 변수가 아래에 보일것이다.
public class ServletTestCase extends AbstractCactusTestCase
    implements CactusTestCase
{

    public ServletTestCase()
    {
    }

    public ServletTestCase(String theName)
    {
        super(theName);
    }

    public ServletTestCase(String theName, Test theTest)
    {
        super(theName, theTest);
    }

    protected ProtocolHandler createProtocolHandler()
    {
        return new HttpProtocolHandler(new DefaultServletConfiguration());
    }

    public HttpServletRequestWrapper request;
    public HttpServletResponse response;
    public HttpSession session;
    public ServletConfigWrapper config;
}
이와 관련된 로직을 이해하기 위해서는 Cactus 작동원리를 알아야한다.이미지를 클릭하시면 원본크기로 보실수 있습니다.

그림을 설명하자면 먼저 브라우저에서 URL 로 TestCase 를 호출하게 되면
Junit Test Runner 는 YYYTestCase 의 runTest() 메서드를 호출하게 된다.
그 메서드는 begin(), beginXXX() 차례로 수행하면서 beginXXX 에 전달된
WebRequest 매개변수를 이용해서 HTTP 관련변수를 셋팅한다.
다음은 Redirector Proxy 에 HTTP 연결을 확립하여 설정된 헤더 및 매개변수를 전달한다.

Redirector Proxy 는 이름 그대로 대리자 역할을 하는데 Client 에 생성했던것과 같은
Junit Test Runner 을 서버측에서 다시 한번 인스턴스를 생성한다. 서버측은 클라이언트와 달리
setUp, testXXX, tearDown 으로 실행된다.
testXXX 메서드는 Junit 의 assert API 를 사용하여 테스트를 수행하고 서버측  서블릿코드를
호출하게 된다. 그리고 서버객체에 대한 레퍼(Wrappers) 와 HTTP세션을 생성한다.

Exception 이 발생하게 되면 Redirector Proxy 에 의해 검출되며 클라이언트 측에 전달하여
Junit 에 의해 화면에 출력된다.

정상수행일 경우 YYYTestCase.runTest() 메소드는 endXXX, end 를 차례대로 호출한다.

서블릿 테스트 코드를 만들면 다음과 같이 간단하게 만들었다.
호출할 Servlet 서버소스 이다.
public class LoginServlet extends HttpServlet {
       public void doGet(HttpServletRequest req, HttpServletResponse res)
                   throws ServletException, IOException{
             PrintWriter out = res.getWriter();
             HttpSession session = req.getSession();
             String id = req.getParameter("id");
             String passwd = req.getParameter("passwd");
             if (checkLogin(id, passwd)){
                    session.setAttribute("id", id);
                    out.print(id+"Login Failed");
             }else{
                    out.print(id+"Login Success");
             }
       }
       private boolean checkLogin(String id, String passwd){
             return true;
       }
}

다음은 TestCase 클래스이다.
import javax.servlet.ServletException;
import org.apache.cactus.ServletTestCase;
import org.apache.cactus.WebRequest;

import com.meterware.httpunit.WebResponse;

public class JunitServletTest extends ServletTestCase {

       public JunitServletTest(String arg0) {
             super(arg0);
       }

       protected void setUp() throws Exception {
             super.setUp();
       }
       public void testMain(){
             LoginServlet servlet = new LoginServlet();
             try {
                    servlet.init(config);
                    servlet.doGet(request, response);
             } catch (ServletException e) {
                    e.printStackTrace();
             } catch (IOException e) {
                    e.printStackTrace();
             }
             assertEquals("bcho", session.getAttribute("id"));
       }
       public void begin(WebRequest request) throws Exception {
       }
       public void beginLogin(WebRequest request) throws Exception {
             request.addParameter("id", "bcho");
             request.addParameter("passwd", "passwd");
       }
       public void endLogin(WebResponse response) throws Exception {
             String responseTxt = response.getText();
             assertTrue(responseTxt.indexOf("success") > 0);
       }
       public void end(WebResponse response) throws Exception {
       }
}


http://www.dude.co.kr





P 이경철님의 파란블로그에서 발행된 글입니다.