MySQL Column Alias문제 해결책

Problem explained

일반적으로  구버젼(5.0.x) MySQ JDBC에서 Column Name Alias를 사용할 경우 아래와 같이 오류가 발생한다.

SELECT DISTINCT c.name AS `Client Name`, ...

하지만, Alias를 사용하지 않으면 정상작동한다.

SELECT DISTINCT c.name, ...

The Solution

해결책은  JDBC URL을 수정하면 간단히 해결된다.

jdbc.url=jdbc:mysql://localhost:3306/miso?useOldAliasMetadataBehavior=true

JDBC Manual에 나와 있다.

역시 Manual을 잘 봐야 한다.
by 제이 | 2015/07/06 15:46 | JAVA, JSP 썅!! | 트랙백 | 덧글(1)
Arare 0.9 r36배포


Release Note

1. Tab기능 개선
    - 다중 Tab사용에 따른 다중결과 방식으로 개선
2. Tree기능 개선
    - Tree Icon기능 추가
3. Object Find기능 추가
    - . 입력 시 하위 Column선택메뉴 활성화
4. Table Information화면 추가
5. Exception dialog개선
6. DB2, MySQL서버 접속 및 사용기능 개선
7. MS-SQL JDBC 드라이버 교체
8. Look and Feel기능 안정화 및 불안정 Lib제거
9. Connection Test기능 추가 
10. 기타 안정화


by 제이 | 2013/12/04 15:09 | Arare | 트랙백(12173) | 덧글(0)
[자랑질]Arare 국제인증(?) 획득 !!!!!

Cross DBMS Query Executer인 Arare가 국제인증(?)을  획득하였습니다. ^^

오늘 Gmail을 통해 받은 메일 본문입니다.

Congratulations,

Arare SQL Executer, one of your products, has been added to Softpedia's
database of software programs for Mac OS. It is featured with a description
text, screenshots, download links and technical details on this page:
http://mac.softpedia.com/get/Developer-Tools/Arare-SQL-Executer.shtml

The description text was created by our editors, using sources such as text
from your product's homepage, information from its help system, the PAD
file (if available) and the editor's own opinions on the program itself.


"Arare SQL Executer" has been tested in the Softpedia labs using several
industry-leading security solutions and found to be completely clean of
adware/spyware components. We are impressed with the quality of your
product and encourage you to keep these high standards in the future.

To assure our visitors that Arare SQL Executer is clean, we have granted it
with the "100% FREE" Softpedia award. To let your users know about this
certification, you may display this award on your website, on software
boxes or inside your product.

More information about your product's certification and the award is
available on this page:
http://mac.softpedia.com/progClean/Arare-SQL-Executer-Clean-110839.html

Feel free to link to us using the URLs above. If you choose to link to the
clean award page for your product, you may use the award graphic or a text
link: "100% FREE award granted by Softpedia".


If you feel that having your product listed on Softpedia is not a benefit
for you or simply need something changed or updated, please contact us via
email at webmaster@softpedia.com and we will work with you to fix any
problem you may have found with the product's listing.

특별히 신청한 것도 없었는데 지들이 알아서 검토하고 평가해서 등록시켰더군요...ㅋㅋㅋ

다만, 아쉬운 것은 100% pure java로 만들어진 Application이라 Windows는 물론, Linux에서도 구동 가능한데 Mac용으로 소개해놓았더라구요....ㅡ.ㅡ

당근, 항의메일 보냈습니다.(근데 짧은 영어로 보낸거라 이해하려나 모르겠네요.....쩝)

Softpedia에 등록된 화면도 자랑질 하렵니다. ^^

http://mac.softpedia.com/get/Developer-Tools/Arare-SQL-Executer.shtml

by 제이 | 2012/01/06 15:04 | 트랙백 | 덧글(2)
Arare release (v0.9_r28)

꽤나 오랫동안 끄적거려오던 작업을 baseline을 그으려 한다.일단, 시작은 Oracle작업 시 사용하던 Golden의 기능을 Tibero나 MySql 등의 다양한 DB에서 사용하고자 만들게 되었다.

JDBC라는 뛰어난(?) 개념때문에 쉽게 접근가능하리라 생각했으나, 천성이 게을러서 빠른 진도를 못 나갔던 것이 사실이다.

프로젝트는 Google Code에서 진행하고 있었고,

당연히, Member는 혼자이다..ㅋㅋ

100% pure java이며, pure Swing이다.

Swing을 다루기 좋은 Netbeans로 작업하였다.

지금까지 작업한 기준으로 Binary와 Source를 Open하고자 한다.

물론, GNU 라이선스를 따름은 당연하다.

code사이트는 http://code.google.com/p/arare/ 이다. member로 참여코자 하시는 분 있으시면 신청해 주시길 바란다.
이글루스의 용량문제로 직접 첨부하지는 못하고 링크로 대신한다.
http://arare.googlecode.com/files/arare.zip

위의 download 링크에서 다운받으신 zip파일을 여시고 첨부된 bat파일을 실행하시면 된다.

많은 사용과 Feedback부탁드린다.

by 제이 | 2011/09/14 20:03 | Arare | 트랙백 | 덧글(0)
Arare
Arare
by 제이 | 2009/02/12 13:49 | Arare | 트랙백 | 덧글(0)
Radix Sort
public int[] doSort (int[] aArr) {
    int i, j, cipher, num, max; 
    int [][] bucket = new int [10][aArr.length];
    int [] count = new int [10];
        
    max = 0;
        
    for(i=0;i<aArr.length;i++){
        if(max<aArr[i])
        max = aArr[i];
    }
        
    cipher = 1;
        
    while(cipher<=max){
        for(i=0;i<=9;i++)
            count[i] = 0;
        for(i=0;i<aArr.length;i++){
            num = (aArr[i]/cipher)%10;
            bucket[num][count[num]++] = aArr[i];
        }
        num = 0;
        for(i=0;i<=9;i++){
            for(j=0;j<count[i];j++){
                aArr[num++] = bucket[i][j];
            }
        }
        cipher *= 10;
    }        
    return aArr;
}
by 제이 | 2007/09/06 09:37 | 기초다 기초...쩝 | 트랙백 | 덧글(0)
Quick Sort

public int[] doSort(int[] aList, int aLow, int aHigh){
    int lo = aLow;
    int hi = aHigh;
    if (lo >= hi){
        return aList;
    } else if (lo == hi - 1) {
        if(aList[lo] > aList[hi]){
            int T = aList[lo];
            aList[lo] = aList[hi];
            aList[hi] = T;
        }
        return aList;
    }

    int pivot = aList[(lo + hi) / 2];
    aList[(lo + hi) / 2] = aList[hi];
    aList[hi] = pivot;
     
    while (lo < hi){
        while (aList[lo] <= pivot && lo < hi){
            lo++;
        }
        while (pivot <= aList[hi] && lo < hi){
            hi--;
        }
        if (lo < hi){
            int T = aList[lo];
            aList[lo] = aList[hi];
            aList[hi] = T;
        }
    }
     
    aList[aHigh] = aList[hi];
    aList[hi] = pivot;

    doSort(aList, aLow, lo - 1);
    doSort(aList, hi + 1, aHigh);
    return aList;
}

by 제이 | 2007/09/06 09:36 | 기초다 기초...쩝 | 트랙백 | 덧글(0)
Shell Sort
public int[] doSort(int[] aList){
    int h,i,j,k,temp,n = 0;
    n = aList.length;
    for(h=n/2;h>0;h=h/2){
        for(i=0;i<h;i++){
            for(j=i+h;j<n;j=j+h){
                temp = aList[j];
                for(k=j;k>h-1&&aList[k-h]>temp;k-=h)
                    aList[k] = aList[k-h];
                aList[k] = temp;
            }
        }
    }
    return aList;
}
by 제이 | 2007/09/06 09:34 | 기초다 기초...쩝 | 트랙백 | 덧글(0)
Bubble Sort
public int[] doSort(int[] aList){
    int i, j, temp;
    for(i=0;i<aList.length-1;i++){
        for(j=1;j<aList.length-i;j++){
            if(aList[j-1] > aList[j]){
                temp = aList[j-1];
                aList[j-1] = aList[j];
                aList[j] = temp;
            }
        }
    }
    return aList;
}
by 제이 | 2007/09/06 09:32 | 기초다 기초...쩝 | 트랙백 | 덧글(0)
Selection Sort
public int[] doSort(int[] aList){
    int k,j,i,temp = 0;
    for(i=0;i<aList.length-1;i++){
        k = i;
        for(j=i+1;j<aList.length;j++){
            if(aList[k]>aList[j]){
                k=j;
            }
        }
        temp = aList[i];
        aList[i] = aList[k];
        aList[k] = temp;
    }
    return aList;
}
by 제이 | 2007/09/06 09:31 | 기초다 기초...쩝 | 트랙백 | 덧글(0)
Insertion Sort
public int[] doSort(int[] aList){
    int k,j = 0;
    for(int i=1;i<aList.length;i++){
    k = aList[i];
    for(j=i-1;j>=0 && k < aList[j];j--)
        aList[j+1] = aList[j];
        aList[j+1] = k;
    }
    return aList;
}
by 제이 | 2007/09/06 09:29 | 기초다 기초...쩝 | 트랙백 | 덧글(0)
J2EE 어플리케이션의 battleneck 발생과 대처방법
회사를 옮기고 맡은 업무가 TA&SA인데...그 중 특히나 J2EE appl에 대한 대처다....

이글 저글 읽다가...발견한 글인데 .... 최고의 글이다.......감동감동감동 !!!!!

여기 오는 독자들은 꼭 읽어보길...권한다...강추한다.

http://cafe.naver.com/ArticleRead.nhn?clubid=12263288&menuid=3&boardtype=&page=3&articleid=14
by 제이 | 2007/08/24 17:52 | JAVA, JSP 썅!! | 트랙백 | 덧글(2)
Ajax로 맹그는 Web Tail(2)

꽤나 오랫동안 연재를 하지 않았기에 혹시나 있지 모를 독자들에게 죄송하단 말을 하고 싶다.

하지만, 아마도 아무도 기다리지 않았으리란 생각이 앞서긴 한다...^^

일단, 지난 연재 때는 요구사항을 아주 가볍게 분석해 봤다.

물론, 이따위의 요구사항 분석법으로 프로젝트를 진행한건 절대 아님을 알려둔다...

다만, 이 글에서는 여러분이나 나나 편하게 이야기하는 형식을 따르고 있으므로 서로 쉽게 받아들이도록 했음을 이해하기 바란다.

각설하고,

분석결과에 따라 구현되는 시스템은 아래와 같다.

뭐 간단해 보인다...

맞다 간단하다...^^

이제 코드를 알아보자.

앞서 언급한 바와 같이 Server측과 Applet측은 이미 구현되어 있는 것을 그대로 사용하므로 여기서 새롭게 언급하진 않겠다.

그럼 Ajax관련 코드만 나열하면 아래와 같다.

1. LogTailServlet.java
2. LogViewer.html

아주 간단하다...^^

또한, 여기서는 기본적인 Web App는 구축되어 있다는 가정과 읽어와야 할 대상이 되는 Log파일이 존재한다는 가정하에 글을 진행하고 있으므로 해당 내용에 대해서 따로 언급하진 않겠다.

그럼 하나씩 알아보자.

먼저 LogTailServlet.java

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;


public class LogTailServlet extends HttpServlet {
    
    private static final long serialVersionUID = 1L;
 
    private static HashMap mStatusMap = new HashMap();
    private RandomAccessFile raFile = null;
    private long raPointer = 0L;
   
    public void init(ServletConfig config) {
        System.out.println("LogTailServlet: initializing...");
    }

   public  void doGet(HttpServletRequest request, HttpServletResponse  response)
        throws IOException, ServletException {
        doProcess(request, response);
    }

    public  void doPost(HttpServletRequest request, HttpServletResponse  response)
        throws IOException, ServletException {
        doProcess(request, response);        
    }
   
    private void doProcess(HttpServletRequest request, HttpServletResponse response)
                   throws IOException, ServletException {        
        try {
            String fileName = request.getParameter("fileName");
            String action = request.getParameter("action");
            String init = request.getParameter("init");
            if("Y".equals(init)) raPointer = 0L; 
            if ((action != null) && action.equals("checkLog")) {
                readFile(fileName, request, response);
            }
        } catch (Throwable e) {
            System.out.println("LogTailServlet exception :" + e.getMessage());
            e.printStackTrace();
        }
    }
   
    public void destroy(){
    }
   
    public void readFile(String aPath, HttpServletRequest request, HttpServletResponse response){
        try{
            String sLine = null;
            String sRet = "";
            raFile = new RandomAccessFile(aPath, "r");
            if(raPointer <= 0 && raFile.length() > 4096){
                raPointer = raFile.length()-4096;         
            }
            raFile.seek(raPointer);     
            Boolean bTempStatus = null;

            while((sLine = raFile.readLine()) != null) {
                sRet +=  sLine+"<br>"; 
            }
            printOutStatus(sRet,request, response);
            raPointer = raFile.getFilePointer(); 
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    private void printOutStatus(String sLine, HttpServletRequest request, HttpServletResponse response)  throws Exception {
        response.setContentType("text/xml");
        response.setHeader("Cache-Control", "no-cache");
        PrintWriter pw = response.getWriter();
        pw.write("<?xml version=\"1.0\" encoding=\"euc-kr\"?>");
        pw.write("<root>");
        pw.write("<message><![CDATA[" + sLine + "]]></message>");
        pw.write("</root>");
        pw.flush();
    } 
}

간단한 Servlet이다.

결국 readFile과 printOutStatus메소드가 주축이 됨을 알 수 있다.

원래 프로젝트 시 구현은 특정 문자열을 찾아서 해당 문자열에 포함된 부분에 대한 HashMap처리를 통해 Server의 Status를 확인하는 절차가 있었으나 여기서는 단순한 Tail부분만 언급하기로 한다.

readFile부분은 위의 소스를 보듯이 RandomAccessFile클래스를 사용하여 FilePointer를 얻어 멤버로 선언된 raPointer에 해당 파일을 읽은 위치까지 기록하고 다음 읽을땐 그 위치부터 읽는 방법을 사용하게 된다.

printOutStatus는 우리가 익히 알고 있는 Ajax Servlet의 기본적인 구현방법을 그대로 따르고 있다.

다만 파일의 로그를 읽는 것이기 때문에 "<" 나 ">"등의 태그가 사용되는 부분이 있을 수 있으므로 CDATA로 처리해 주었을 뿐이다.

물론, 4096으로 선언된 Buffer또한 서버의 성능에 따라 달라져야 함은 물론이다.

by 제이 | 2007/08/20 00:21 | 좋은데..Ajax ㅋㅋ | 트랙백 | 덧글(0)
Ajax로 맹그는 Web Tail(1)

정말 요즈음 들어 Ajax의 매력에 흠뻑 빠진 느낌이다.

물론, 그 극악의 코딩환경은 최악의 평가를 받아 마땅하지만, 적어도 Web Program의 한계를 뛰어넘었다고(사실 뛰어넘은 건 아니다. 다만 뛰어넘은듯 보일뿐...^^) 느끼게 해주는 결과물이야 말로 코딩을 하는 기쁨을 오랜만에 느끼게 해주곤 한다.

요새 들어 시간이 날 때 마다 Ajax로 뭘 할 수 있을까 하는 생각을 많이 하는데 그 생각의 결과와 완벽한 사용자(?)정신으로 무장한 고객님의 요구사항으로 인해 이 강좌의 주제가 탄생할 수 있었다.

먼저, 요구사항의 배경은 이렇다.

1. C/S환경의 Server와 Applet으로 통신을 하는 Web Client가 구축되어 있다.
    - 물론, 왜 그따위 구조냐고 반문하는 분들 많으리라 본다. 그 질문에 대한 답은 4년전에 구축된 프로젝트라는 변명으로 대신하고자 한다. 
    - 그동안 수정안하고 뭐했냐는 질문을 한번 더 하는 독자들이 있다면 그 답은 "니들은 에러없이 잘 구동되고 있는 수준낮은 구조의 은행권 기간계 관련 모듈을 최고의 심플하고 호환성 높은 구조로 바꾸겠다고 할때 니네들 영업이나 고객이 정말 고맙다고 꼭 해달라고 하던?" 이라는 질문으로 대체하고 싶다.

2. 문제는 Applet이 통신한 이후 서버의 로그를 볼 필요가 생기곤 한다.
    - 이 또한, 지금까지 4년동안 한번도 에러가 나거나 문제가 된적은 없었다. 하지만 고객들은 꼭 다시금 확인하고 싶어한다. 뭐 다른 은행권은 모르겠다만 적어도 내 고객은 그랬다.

3. 버뜨, 문제는 지금까지의 고객과 달리 새로이 업무를 맡으신 고객께서 서버로그를 읽으시기 싫고 뭔가 쌈빡한 화면으로 보시고 싶으시다는 데서 출발한다.

여기서 필자는 고민에 빠진다.

1. 로그를 보기 싫다면, 그럼 서버로부터 통신을 받아서 처리결과를 보여줘야 하나?
    - 아냐, 그러려면 서버도 바뀌어야 하고, Applet도 바뀌어야 하는데 넘 공사가 큰데.....ㅜ.ㅜ

2. 아니면, 서버에서 처리된 후 DB로 넣을까? 뭐 화면에서야 DB읽어서 보여주면 되지.
    - 아냐, 이또한 서버가 바뀌어야 하잖아. 게다가 화면을 주기적으로 갱신해줘야 하고.. 깜빡이는거 싫어한단 말야..고객님이..ㅜㅜ

3. 그럼 로그를 화면상에 보이도록 tail프로그램을 하나 사서 깔라고 해?
    - 아냐, 그러면 그 고객이 울 회사에서 날 내쫒을때까지 Complain할꺼야....ㅜ.ㅜ

에잇 그럼 어떻게 하면 되지?
결론적으로 필자가 생각한 방법은 아래와 같다.

1. 사용자의 Action을 받아서 Applet이 통신을 보내기 전, 서버단에서 Tailling하는 서블릿을 구동한다.

2. 해당 서블릿에서는 서버의 로그를 찾고자 하는 문자가 나올때까지 Tailling한다.

3. 이제 Applet에서 Server로 통신을 보낸다.

4. Server에서 처리된 결과를 Log로 쌓는다.

5. Tailling하고 있던 Servlet에서 해당 로그를 Catch한다.

6. Catch된 로그를 사용자 화면에 뿌린다.

좋아!! 바로 이거야 라고 생각하며 좋아했다.
하지만, 잠시 몇가지 문제가 봉착하게 됬다.
먼저, 앞의 시나리오상에서 3, 4번은 이미 구현되어 있는 기능이므로 문제가 되지 않는다.
또한, 1번의 Tailling이야 뭐 짜면된다...ㅋㅋㅋ
문제는 5, 6번이다. 이걸 우찌 해야 하지?

결론은 Ajax였다....^^

화면상에 사용자 모르게 변경사항을 반영할 수 있는 방법이니까 우리 까칠한 고객님은 별말씀 안하고 넘어갈 듯 했다.


---- 1강 End ---

꼬랑지 ~ 여기서 1강을 마친다....절단신공을 발휘함은 블로그의 독자들이 좀 더 쉽게 읽게하고픈 필자의 배려가 담겨있음을 기억해주길 바란다...^__^

by 제이 | 2007/04/17 18:58 | 좋은데..Ajax ㅋㅋ | 트랙백 | 덧글(0)
오랜만이다....슬픈거...
정말 오랜만에 블로그를 다시 시작했다..

아무도 모르는

이 블로그는 내가 누구인지 아무도 모르는 곳이다...

그래서 더 솔직해 질 수 있을지도 모르겠다...

오늘 정말 착한 사람을 다시 만났다

난 그 사람을 슬프게만 했는데....그 사람은 여전히 착했다...

그래서 슬픈걸까?

여전히 같은 모습의 그 사람때문일까?

갑자기 15년전의 내 모습이 떠오는건 왜인지...

마냥 슬퍼진다

그저 아둥바둥대며 살아온 시절은 아니었는지....뒤돌아보게 된다

역시 달라지는 건 없지만....그저 그대로이겠지만...
by 제이 | 2007/04/17 04:21 | Jay's Story | 트랙백 | 덧글(1)
Java Application Windows Service 등록법
일반적으로 Windows 에서의 Java Application은 Command Console을 사용하여 구동된다.
이 방식은 아래와 같은 단점을 가지고 있다.

1. 사용자 실수로 인해 Command Console에 Mouse Click이 발생하면 Application이 Hold됨.
2. 사용자가 Logout하면 해당 Application이 종료됨.
3. 특별히 제약이 없는 경우 터미널 서버나 원격 데스크탑 Application을 사용하여 같은 Application을 각 User별로 계속 구동할 수 있음.

이런 단점을 극복하기 위해 Unix에서는 Background Process로 구동시키면 되지만, Windows는 그 태생이 End User를 위한 DeskTop이기에 그 개념이 없다.

그와 유사한 개념이 Windows Service이다.

그러나 애석하게도 현재 JDK는 Windows Service를 사용하는 API를 제공하고 있지는 않다.

그로 인해 Apache나 InstallAnywhere등의 Application 벤더들은 그들만의 방법으로 Service등록을 가능하게 해서 사용하고 있는 실정이다.

지금 제시할 방법은 이러한 Java Application을 Windows Service로 등록하는 간단한 방법이다.

프로젝트에 적용중인 모듈에 적용하기 위해 여러자료를 찾다 발견한 매우 간단한 방법이다.

지금까지 제가 배포한 모듈의 경우 모두 이 방법을 사용해 서비스에 등록했다.

방법은 다음과 같다.

JavaService.exe 에 구동 Argument로 설정값을 넘겨주면 서비스 등록이 완료되게 된다.

실제 사용은 아래의 방법을 따른다.

1. JavaService.exe를 구한다.
2. 서비스 등록용 batch파일을 만든다. 아래는 필자가 사용하는 파일의 예이다.

C:JavaService -install MyApp %JAVA_HOME%jreinserverjvm.dll -Djava.class.path=.;C:MyAppclasses -start MyApp.StartApp -params INSTALL_DIR=C:MyAppr -out C:MyApplogsstdout.log -err C:MyApplogsstderr.log -auto

3. 서비스 해지용 batch파일을 만든다. 아래는 필자가 사용하는 파일의 예이다.

C:JavaService -uninstall MyApp

더 자새한 내용은 http://javaservice.objectweb.org/docs/description.html을 참고하기 바란다.
by 제이 | 2005/04/25 17:50 | JAVA, JSP 썅!! | 트랙백 | 덧글(4)
MS MOM 리눅스도 관리 - ZDNET 펀글
난 흔히 말하는 SMS 솔루션과 관계된 일을 하고 있다....

솔직히 우리 바닥에서 윈도우는 논외였다.

콘솔만 윈도우면 됬으니까...

크리티컬한 관리대상 장비는 거의 대부분 유닉스나 메인프레임이었기 때문이다

그런데...

아래의 기사는 슬슬 이 시장으로도 M$의 문어발이 접근하고 있다는 생각이 든다....

솔직히 어찌 될지도 궁금하고 겁나기도 하고 어케 대비해야 할지도 고민이다...

어쨋든..그리 멀지 않은 것만은 사실이다.

M$ !! 결국 오는건가?

===================================================================================
윈도우만 편애하던 MS의 CEO 스티브 발머가 마음을 바꾸고, MS가 앞으로 기업들이 보유한 다양한 시스템, 심지어 리눅스가 동작중인 시스템이라도 관리가 용이하도록 지원할 예정이라고 밝혔다.

발머는 지난 20일 그간 MS의 핵심 관리 제품인 오퍼레이션 매니저 소프트웨어에서 비(非) 윈도우 머신에 대한 지원을 강화해달라는 고객들의 요청에 귀를 기울여왔다고 밝혔다. 또한 MS는 올해 말 내놓을 버추얼 서버 제품의 서비스 팩 업데이트에서 리눅스 기반의 버추얼 머신 구동에 대한 지원을 강화할 계획이라고 말했다.

발머가 기조 연설을 하는 동안 레드햇 엔터프라이즈 리눅스가 동작중인 버추얼 서버가 시연됐는데, 연설 도중 발머는 "인정하고 싶지는 않지만 그것이 버추얼 서버 고객들에게 중요한 기능이라는 걸 안다"라고 말했다.

오직 고객을 위해?
현재 버전에서도 리눅스나 다른 운영체제를 구동할 수는 있지만, MS는 고객이 윈도우가 아닌 운영체제를 구동해 곤란을 겪을 때도 지원하겠다는 계획을 세운 것이다.

MS는 MS 오퍼레이션 매니저(MOM)로 솔라리스 서버를 제어하는 것을 시연하면서, MOM 콘솔 내에 팝업 형태로 알림 메시지가 나타나는 것을 보여주기 위해 솔라리스가 동작중인 시스템에서 냉각팬을 뽑아버리기도 했다.

발머는 "우리는 썬과 긴밀히 작업해왔다. 알고 있겠지만 전에는 썬과의 긴밀한 협력은 생각할 수도 없었다"라고 말하며, 1년 전 양사가 상호 긴장 완화를 한 이래 두 회사가 함께 작업한 그간의 성과를 기반으로 업데이트를 곧 내놓을 것이라고 덧붙였다.

WS-매니지먼트 웹 서비스 표준을 통해 솔라리스 서버 장비를 모니터링하는 데 MOM을 사용한다는 것은, MOM 관리 프로그램이 관리 대상이 윈도우 머신인지 알 필요가 없다는 의미다.

MS의 인프라스트럭처 서버 마케팅 부문을 총괄하고 있는 밥 켈리는 반대 상황도 함께 시연하면서 "보는 것처럼 솔라리스가 동일한 프로토콜을 이용해 윈도우 머신을 이렇게 쉽게 관리할 수 있다"라고 말했다.

MS의 상호운용성 부족하지 않다
켈리는 “MS의 목표는 윈도우가 수많은 윈도우와 비 윈도우 시스템들을 관리하는 데 가장 비용이 적게 드는 방법을 제공한다는 것을 확실히 보여주는 것”이라고 말했다. 그는 이 관리 소프트웨어가 새로 나온 것이지만 상호 운용성을 이미 제공하고 있다며, 이런 점은 MS가 그 동안 충분히 신뢰를 얻지 못했던 부분이라고 말했다.

켈리는 "우리 제품이 다른 회사 제품과 상호 운용이 되지 않는다는 것을 알고 있다는 것이 정말로 '부끄러운 일'"이라고 말했다.

발머는 20일 연설에서 차세대 데스크톱용 윈도우 제품인 '롱혼'에 대해서도 언급했다. 그는 롱혼이 내년 하반기에 나오면 관리 편의성이 나아지고 운영 비용이 좀더 저렴해질 것이라며, 윈도우 운영체제 최고 책임자인 짐 알친이 지난 주에 언급한 내용을 여러 번 되풀이하며 강조했다.

또한 발머는 롱혼 데스크톱 버전이 출시된 후 약 6개월 뒤에 롱혼 서버가 나올 예정이라며 롱혼 서버 출시 시기에 대해 좀더 자세히 언급했다. 역사적으로 볼 때 서버를 출시하기 전 테스트 기간이 비교적 오래 걸리기 때문에 정확한 스케줄을 맞추는 것을 기대하기는 어려웠다.

켈리는 롱혼의 클라이언트 버전과 서버 버전의 개발 주기를 맞춰가고 있다고 말했다. 이는 서버 출시에 필요한 추가 테스트에 6개월이라는 시간이 필요하다는 것을 의미한다. 그는 "이를 지키기 위해 최선을 다하고 있다"라고 덧붙였다.

발머의 이야기는 MS가 단일화된 시스템 센터 제품을 내놓기로 한 계획을 파기하고, 대신 기존 MOM과 시스템 매니지먼트 서버(SMS) 제품에 대한 업데이트 계획을 세우며 향후 관리 소프트웨어를 어떻게 내놓을지 밝힌 지 하루 만에 나온 것이다.
by 제이 | 2005/04/25 13:54 | 이건 또 먼데? | 트랙백 | 덧글(0)
질렀다 알육이

이동건이 넘 부러웠었나 보다...ㅜ.ㅜ

질렀다...PDA폰

전에 쓰던 전화를 3년 6개월을 썼다....
바꿀때가 되었다고 생각하던 차에 지름신이 강림하셔서 그만.....ㅜ.ㅜ

잘써야지...한 3년 쓰면 되겠지..머..쩝
by 제이 | 2005/04/21 19:14 | 끄적끄적 | 트랙백 | 덧글(0)
SJSXP를 이용한 XML Programming(Java 4월 19일 Tech Tip 펀글)
SUN JAVA STREAMING XML PARSER 소개

현재 dom4j를 사용해서 프로젝트를 수행하고 있다.
성능도 괜찮고 API도 잘 되어 있어서 괜찮다고 생각하고 있었는데 메일로 날아온 SJSXP TechTip을 봤는데 JDBC API를 사용하는 듯한 쉬운 사용법이 일단 맘에 든다.
새로운 프로젝트에 적용해보아야 할듯.....

====================================================================================

XML을 사용하는 대부분의 Java 개발자는 SAX (Simple API for XML) 라이브러리와 DOM(Document Object Model) 라이브러리에 익숙할 것이다. SAX는 이벤트 기반의 API이며, 이는 일반적으로 프로그래머가 파서와 몇 개의 리스너를 등록하고, 특정 XML 문법 생성자(예를 들어 요소나 속성)가 도착되면 리스너 메소드가 호출된다는 의미이다. 그 반대로 DOM은 트리 기반의 아케텍처를 가지며, 전체 문서를 스캔하여 마주치는 각각의 문법 생성자의 오브젝트 트리를 구축한다. 프로그래머는 스캔이 완료된 후 오브젝트 트리에 접근하여 수정할 수 있다

이 두 방법 모두 각각의 결점을 가지고 있다: 리스너를 이용하는 이벤트 기반의 API는 일반적으로 다루기 힘들다. 리스너들이 파서에 의해 조종되기 때문이다. 트리 기반의 API는 스캔되는 문서의 양에 비해 과도한 양의 메모리를 소모할 수 있다. 이제 Java 개발자들이 XML 을 스캔하는데 이용할 수 있는 세 번째 API가 등장하였다. StAX (Streaming API for XML parse)가 그것이다.

SJSXP란?

SJSXP(Sun Java Streaming XML Parser)는 StAX를 빠른 속도로 구현한다. 썬마이크로시스템즈와 협력하고 있는 BEA Systems, XML-guru James Clark, Stefan Haustein, Aleksandr Slominski (XmlPull 개발자들), 그리고 JCP의 다른 멤버들은 JSR 173를 구현하는 것으로써 StAX를 개발하였다. StAX은 공유 인터페이스들에 기반하는, 파서(parser) 독립적인 Java API이다.

SJSXP는 Java Web Services Developer Pack v1.5에 포함되어있다. SJSXP에 대해 처음으로 알아차릴만한 것은 이것이 스트림 API에 기반한다는 것이다. 즉, 개발자가 어느 한 노드에 접근하기 위해 전체 문서를 읽을 필요가 없다. 또한, 파서를 시작하여 파서가 데이터를 이벤트 리스너 메소드에 "push"하도록 허용하는 법칙을 따르지 않는다. 대신에 SJSXP는 "pull" 메소드를 구현하며, 이 메소드는 정렬 포인터를 문서에서 현재 스캔되고 있는 지점에 유지한다. 이는 종종 커서(cursor)라고 불린다. 사용자는 단순히 커서가 현재 가리키고 있는 노드에 대한 파서를 요청하면 된다.

XML 문서 파싱에 SJSXP 이용하기

SJSXP를 이용하여 XML 문서를 읽는 것은 아주 쉽다. 대부분의 작업은 javax.xml.stream.XMLStreamReader 인터페이스를 구현하는 오브젝트를 통해 이뤄진다. 이 인터페이스는 XML 문서의 첫 부분에서 마지막까지 이동되는 커서를 나타낸다. 몇 가지 명심해야할 것이 있다. 커서는 항상 하나의 아이템(시작 태그 요소, 진행 명령, DTD 선언 등)만을 가리켜야 한다. 또한 커서는 항상 앞으로 움직여야 하며 (뒤로 움직일 수 없다), 다음에 무엇이 나타나는지 미리 보기를 실행할 수 없다. 다음의 코드 발췌에서 파일로부터 XML을 읽는 XMLStreamReader를 얻을 수 있다.

URL url = Class.forName("MyClassName").getResource(
"sample.xml");
InputStream in = url.openStream();
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader parser = factory.createXMLStreamReader(in);


그 후 다음 코드를 이용하여 XML 파일을 반복할 수 있다.

while(parser.hasNext()) {

eventType = parser.next();
switch (eventType) {

case START_ELEMENT:
// Do something
break;
case END_ELEMENT:
// Do something
break;
// And so on ...
}
}


XMLStreamReader의 hasNext() 메소드는 XML 파일에서 또다른 유효한 아이템이 있는지 확인한다. 만약 있다면, 커서가 다음 아이템으로 넘어가게하기 위해 next() 메소드를 사용할 수 있다. next() 메소드는 만나게되는 문법상 생성자(아이템)의 타입을 가리키는 인티거 코드를 리턴한다.

XMLInputStreamReader에는 몇 개의 get 메소드가 있어서 커서가 가리키는 XML 아이템의 내용을 얻는 데 사용할 수 있다. 첫번째 메소드는 getEventType()이다:

public int getEventType()

메소드는 커서가 있는 곳에서 파서가 찾은 아이템의 타입을 식별하는 integer 코드를 리턴한다. next() 메소드에 의해 리턴되는 것과 같은 코드이다. 아이템은 XMLInputStream 상수 중 하나에 의해 식별된다.

XMLStreamConstants.START_DOCUMENT
XMLStreamConstants.END_DOCUMENT
XMLStreamConstants.START_ELEMENT
XMLStreamConstants.END_ELEMENT
XMLStreamConstants.ATTRIBUTE
XMLStreamConstants.CHARACTERS
XMLStreamConstants.CDATA
XMLStreamConstants.SPACE
XMLStreamConstants.COMMENT
XMLStreamConstants.DTD
XMLStreamConstants.START_ENTITY
XMLStreamConstants.END_ENTITY
XMLStreamConstants.ENTITY_DECLARATION
XMLStreamConstants.ENTITY_REFERENCE
XMLStreamConstants.NAMESPACE
XMLStreamConstants.NOTATION_DECLARATION
XMLStreamConstants.PROCESSING_INSTRUCTION


만약 아이템에 이름이 있는 경우, getName()과 getLocalName() 메소드를 사용하여 이름을 얻을 수 있다. 후자는 어떤 다른 정보(예; 확인된 네임스페이스가 없는 요소의 이름) 없이 이름 자체를 산출한다.

public Qname getName()
public String getLocalName()


만약 당신이 현재 아이템의 네임스페이스를 식별하고 싶다면 getNamespaceURI() 메소드를 사용 할 수 있다.

public String getNamespaceURI()

만약 DTD 선언 내의 텍스트나 요소 안의 텍스트 등과 같은 동반되는 텍스트가 있을 때에는 다음 메소드들을 사용하여 얻을 수 있다.(후자는 요소를 위해 단독으로 사용 될 수 있다)

public String getText()
public String getElementText()


만약 요소가 그것과 관계 되는 속성을 가진다면 getAttributeCount() 메소드를 사용하여 현재 요소가 가진 속성들의 갯수를 얻을 수 있다. 그 후 getAttributeName() 와 getAttributeValue() 메소드를 사용하여 각각의 정보를 검색 할 수 있다.

public int getAttributeCount()
public Qname getAttributeName(int index)
public String getAttributeValue(int index)


만약 속성의 로컬 이름과 요소의 네임스페이스 URI를 안다면, 또한 다음의 메소드를 이용하여 속성값을 얻을 수 있다.

public String getAttributeValue(
String elementNamespaceURI, String localAttributeName)


추측했겠지만, 모든 접근자 메소드가 특정 상태에 적용가능한 것이 아니다. 예를 들어, 현재 DTD를 프로세싱 중이라면 getElementText()을 호출할 수 없다. 만약 이를 호출한다면, 파서가 충돌하는 이벤트 타입을 식별했다는 XMLStreamException을 얻게 되거나 메소드가 스스로 널(null) 값을 리턴하게 될 것이다.

XMLInputFactory 클래스의 setProperty() 메소드를 사용하여 몇 가지 파서 속성을 시작할 수 있다. 예를 들어, 다음은 파서와 마주치는 엔티티 레퍼런스는 교체될 것이라고 지정한다.

factory.setProperty(
XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES,
Boolean.TRUE);


파서가 외부 엔티티를 지원하는 것을 막기 위해 다음과 같이 설정한다.

factory.setProperty(
XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES,
Boolean.FALSE);


파서가 네임스페이스를 알아차리게하기 위해 다음과 같이 설정한다.

factory.setProperty(
XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.TRUE);


SJSXP의 현재 버전에서는 다음의 명령은 허용되지만 파서는 확인되지 않는다는 것을 유의하기 바란다.

factory.setProperty(XMLInputFactory.IS_VALIDATING,
Boolean.TRUE);


만약 이 XMLInputFactory 특성들 중 어느 하나라도 가능하게 된다면 setXMLReporter() 메소드를 사용하여 파서가 만나게되는 오류를 제어할 수 있다. 파서가 만나는 오류의 타입을 가장 빨리 정확하게 결정할 수 있는 방법은 setXMLReporter() 메소드와 상호 작용하는 익명의 이너 클래스를 사용하는 것이다. 이는 다음과 같다.

factory.setXMLReporter(new XMLReporter() {
public void report(String message, String errorType,
Object relatedInformation, Location location) {
System.err.println("Error in "
+ location.getLocationURI());
System.err.println("at line "
+ location.getLineNumber()
+ ", column " + location.getColumnNumber());
System.err.println(message);
}
});


XML 문서 작성에 SJSXP 사용하기

XML 결과를 작성하는 것은 SJSXP를 이용하면 쉽다. 이 경우, XMLStreamReader 인터페이스 대신에 XMLStreamWriter 인터페이스를 사용할 수 있다. XMLStreamWriter 인터페이스는 작성하는 요소, 속성, 코멘트, 텍스트를 비롯해 XML 문서의 모든 부분을 작성하기 위한 직접적인 메소드를 제공한다. 다음의 예제에서는 어떻게 이 인터페이스를 얻어서 XML 문서를 작성하는데 사용하는지 보여준다.

XMLOutputFactory xof = XMLOutputFactory.newInstance();
XMLStreamWriter xtw =
xof.createXMLStreamWriter(new FileWriter("myFile"));

xtw.writeComment(
"all elements here are in the HTML namespace");
xtw.writeStartDocument("utf-8","1.0");
xtw.setPrefix("html", "http://www.w3.org/TR/REC-html40");
xtw.writeStartElement(
"http://www.w3.org/TR/REC-html40","html");
xtw.writeNamespace(
"html", "http://www.w3.org/TR/REC-html40");
xtw.writeStartElement(
"http://www.w3.org/TR/REC-html40","head");
xtw.writeStartElement(
"http://www.w3.org/TR/REC-html40","title");
xtw.writeCharacters("Java Information");
xtw.writeEndElement();
xtw.writeEndElement();

xtw.writeStartElement(
"http://www.w3.org/TR/REC-html40","body");
xtw.writeStartElement("http://www.w3.org/TR/REC-html40","p");
xtw.writeCharacters("Java homepage is ");
xtw.writeStartElement("http://www.w3.org/TR/REC-html40","a");
xtw.writeAttribute("href","http://java.sun.com");
xtw.writeCharacters("here");
xtw.writeEndElement();
xtw.writeEndElement();
xtw.writeEndElement();
xtw.writeEndElement();
xtw.writeEndDocument();

xtw.flush();
xtw.close();


각 요소를 작성하는 것이 끝나면 사용자는 라이터(writer)를 날려보내고 닫아야한다.

이전의 코드는 다음의 XML로 결과가 나타난다.(여기서는 쉽게 읽을 수 있게 라인 별로 나타내었다.)

<!--all elements here are explicitly in the HTML namespace-->
<?xml version="1.0" encoding="utf-8"?>
<html:html xmlns:html="http://www.w3.org/TR/REC-html40">
<html:head>
<html:title>Java Information</html:title>
</html:head>
<html:body>
<html:p>
Java information is
<html:a href="http://frob.com">here</html:a>
</html:p>
</html:body>
</html:html>


XML 문서 필터링

만약 각각의 아이템 타입을 스캔하고 싶지 않다면 들어오는 XML 문서에 대한 필터를 생성할 수 있다. 이를 위해서는 javax.xml.stream.StreamFilter 인터페이스를 구현하는 클래스를 생성한다. 이 인터페이스는 단지 accept() 메소드만으로 구성된다. 이 메소드는 XMLStreamReader 오브젝트를 허용하고 원시 Boolean을 리턴한다. StreamFilter의 일반적인 구현은 다음과 같다.

public class MyStreamFilter implements StreamFilter {

public boolean accept(XMLStreamReader reader) {
if(!reader.isStartElement() && !reader.isEndElement())
return false;
else
return true;
}
}


그 다음으로 XMLInputFactory의 createFilteredReader() 메소드를 호출하여 필터링된 리더(reader)를 생성하고 이를 원래 XML 스트림 리더와 StreamFilter 구현에 모두 전달한다. 다음과 같다.

factory.createFilteredReader(
factory.createXMLStreamReader(in), new MyStreamFilter());


SJSXP의 더 자세한 정보는 Sun Java Streaming XML Parser release notes를 참고하기 바란다.

Sun Java Streaming XML Parser 예제 코드 구동하기

이번 테크팁에 대한 샘플 아카이브(ttfeb2005sjsxp.jar)를 다운로드한다.


Java Web Services Developer Pack Downloads page에서 Java WSDP 1.5를 다운로드, 설치한다.


예제 압축파일을 다운로드 받은 디렉토리를 변경하고, 다음과 같이 샘플 아카이브에 대한 JAR 파일의 압축을 푼다.

jar xvf ttfeb2005sjsxp.jar

사용자의 classpath가 ttfeb2005sjsxp.jar와 jsr173_api.jar를 포함하도록 설정한다. 이들은 Java WSDP 1.5 installation의 sjsxp/lib 디렉토리에 위치하고 있다.


SJSXPInput를 컴파일하고 구동한다.

다음의 각각의 XML 아이템과 유사한 엔트리가 나타날 것이다.
Event Type (Code=11): DTD
Without a Name
With Text: Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-
transitional.dtd">
-----------------------------


SJSXPOutput를 컴파일하고 구동한다. 결과는 XMLOutputFile라는 이름의 파일에 보내지며, 위의 결과 예제에 보여지는 요소들을 포함할 것이다.
by 제이 | 2005/04/19 13:41 | JAVA, JSP 썅!! | 트랙백 | 덧글(0)
resin install on UNIX

1.Resin Install Command Line Argument

2.resin.conf(1)

3.resin.conf(2)

4.Resin Install on UNIX

5.How to Start with Appache

6.How to Start with IIS

7.Resin3.0 변경사항

Resin 역시 Java Application 이기 때문에 “Write Once, Run Everywhere” 를 추구한다.

그러므로 Unix에서 구동하기 위해 특별히 make해야 한다거나 소스를 수정해야 하는 것은 필요치 않다. 즉, JDK만 설치되어 있다면 동일하다는 뜻이다.

아래 문서의 내용은 Linux와 Mac OS-X도 함께 포함된다.

다만, Daemon이기 때문에 기본적으로 Background로 구동되어야 하고 그 구동방법이 Windows의 그것과는 다르기에 필요한 몇 가지 설정이 있을 뿐이다.

Unix에 Install하기 위해 고려할 사항은 아래와 같다.

1. Resin 사용자 계정 생성

2. JDK1.4이상 설치여부

3. Perl 5.6 이상 설치 여부(for $RESIN_HOME/bin/httpd.sh)

4. rc.d 등록여부

이 이외에 resin.conf설정이나 web-app 의 deploy방법, command-line argument사용법 등은 windows의 그것과 동일하며 이미 앞선 글에서 설명되었으므로 생략하도록 하겠다.

1. Resin 사용자 계정 생성

A. Install Guide에 의하면 Resin을 구동하기 위한 특별한 계정은 따로 존재하지 않는다.(꼭, Root 이어야 할 필요는 없다. 오히려 보안정책상 일반 User를 추천한다.)

B. 필요하다면 JAVA_HOME 과 RESIN_HOME을 설정한다.(구성되어 있지 않다면 설정하는 것이 좋다.)

2. JDK1.4이상 설치여부

A. Caucho에서는 JDK1.4이상을 권고하고 있으며 version확인법은 아래와 같다.

# java –version

java version "1.4.2_06"

Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_06-b03)

Java HotSpot(TM) Server VM (build 1.4.2_06-b03, mixed mode)

B. 주의할 것은 JRE만 설치되어서는 안되고 JDK가 설치되어야 한다는 것이다. 위의 내용은 JRE만 Check 할 수 있을 뿐이다.

# javac

Usage: javac

where possible options include:

-g Generate all debugging info

-g:none Generate no debugging info

-g:{lines,vars,source} Generate only some debugging info

-nowarn Generate no warnings

-verbose Output messages about what the compiler is doing

-deprecation Output source locations where deprecated APIs are used

-classpath Specify where to find user class files

-sourcepath Specify where to find input source files

-bootclasspath Override location of bootstrap class files

-extdirs Override location of installed extensions

-d Specify where to place generated class files

-encoding Specify character encoding used by source files

-source Provide source compatibility with specified release

-target Generate class files for specific VM version

-help Print a synopsis of standard options

C. 위와 같이 JDK 설치도 확인되어야 한다.

D. 각 OS별로 JDK설치 방법은 다르므로 관련 OS의 Tech note를 참조하기 바라며 이 글에서는 언급하지 않겟다.

3. Perl 5.6이상 설치여부

A. Unix에서 resin을 구동하는 방법은 $RESIN_HOME/bin/httpd.sh를 사용하는 것이다.

B. Httpd.sh의 내용은 주석부분을 제거하면 아래와 같다.

#! /bin/sh

#

# Extra arguments to Java. If you're passing arguments to the JVM, you'll

# need to use -Jxxx. For example, args="-J-ms48m". You can modify

# the pid file with args="-pid server-a.pid"

#

args=

# class to start

class=com.caucho.server.http.HttpServer

# name of the server

name=httpd

# location of perl executable

perl=perl

# trace script and simlinks to find thw wrapper

script=`/bin/ls -l $0 | awk '{ print $NF; }'`

while test -h "$script"

do

script=`/bin/ls -l $script | awk '{ print $NF; }'`

done

bin=`dirname $script`

exec $perl $bin/wrapper.pl -chdir -name "$name" -class "$class" $args $*

결과적으로 보면 httpd.sh가 있는 디렉토리를 구해서 perl을 사용해서 wrapper.pl이라는 파일을 구동시키고 있음을 알 수 있다.

위의 파일에 포함된 실행옵션들은 글 말미에 별도 설명하고 여기선 생략한다.

자세히 해석하길 원한다면 Unix shell script에 관한 자세한 자료를 참조하길 바란다.

C. 위에서 언급한 wrapper.pl의 내용은 아래와 같다.

i. Wrapper.pl은 약 800여 line의 perl파일이다. 해당 파일의 내용을 하나씩 해석하는 것은 Perl script 사용법을 언급하며 설명하는 것이고 이 글의 범위를 벗어나게 되므로 지양한다.

ii. 다만, 관련 파일의 내용에 대해 나열하고 주의사항을 언급한다.

iii. Wrapper.pl의 내용은 아래와 같다.

1. Resin의 start, stop, restart

2. JAVA_HOME설정

3. RESIN_HOME설정

4. configuration file의 변경

5. CLASSPATH설정

6. native thread로 강제 구동

7. green thread로 강제 구동

8. jit 컴파일러 사용여부

9. stdout log file의 변경

10. stderr log file의 변경

11. pid file 설정

12. 자동 restart 여부

iv. Wrapper.pl관련 오류 및 조치사항

1. 먼저 wrapper.pl구동을 위한 Perl은 Version 5.6이상을 권고하고 있으며 확인방법은 아래와 같다.

# perl -v

This is perl, v5.6.1 built for sun4-solaris-64int

(with 48 registered patches, see perl -V for more detail)

Copyright 1987-2001, Larry Wall

2. 아래의 내용은 perl이 설치되어 있지 않거나 perl 버전이 낮은 경우 발생한다.

# ./httpd.sh start

usage: dirname [ path ]

Can't open perl script "/wrapper.pl": No such file or directory

3. 아래의 내용의 원인도 역시 perl이 설치되지 않았거나 version이 맞지 않아서 발생하며 참고로 위의 내용은 HP-UX11에서 발생한 내용이다.

# ./httpd.sh

syntax error in file ./wrapper.pl at line 9, next 2 tokens "use File"

syntax error in file ./wrapper.pl at line 72, next 2 tokens "my("

syntax error in file ./wrapper.pl at line 73, next 2 tokens "fileparse("

syntax error in file ./wrapper.pl at line 517, next 2 tokens "0 and"

syntax error in file ./wrapper.pl at line 527, next token "}"

syntax error in file ./wrapper.pl at line 634, next 2 tokens "setpgrp;"

syntax error in file ./wrapper.pl at line 706, next 2 tokens "my $file "

syntax error in file ./wrapper.pl at line 715, next 2 tokens "$dir or"

syntax error in file ./wrapper.pl at line 717, next 2 tokens "$pwd or"

syntax error in file ./wrapper.pl at line 724, next 2 tokens "$dir or"

./wrapper.pl has too many errors.

4. 아래의 내용은 resin이 사용하는 pid파일을 write하지 못할 때 발생하는 내용이다. 해결방법은 해당 디렉토리와 파일의 권한을 확인하고 재설정하도록 한다.

# ./httpd.sh start

Can't locate Socket.pm in @INC at /resin-2.1.4/bin/wrapper.pl line 10.

BEGIN failed--compilation aborted at /resin-2.1.4/bin/wrapper.pl line 10.

4. rc.d등록여부

A. rc.d관련 설정은 해당 시스템 관리자의 role이므로 기본적으로는 권한이 있는 관리자에게 설정해달라고 하는 것이 옳다.

B. Caucho의 권고사항은 아래와 같다.

httpd.sh를 resin/bin에 resin-a.sh로 이름을 바꾸고 권한을 할당하여 복사한다.

resin-a.sh에 JAVA_HOME, RESIN_HOME, PATH, "-pid" 를 설정한다.

"resin-a.sh start" 와 "resin-a.sh stop”을 root 계정으로 test한다.

아래와 같이 수행한다.

"ln -s /usr/local/resin/bin/resin-a.sh /etc/rc.d/rc3.d/S86resin-a"

"ln -s /usr/local/resin/bin/resin-a.sh /etc/rc.d/rc5.d/S86resin-a"

"ln -s /usr/local/resin/bin/resin-a.sh /etc/rc.d/rc2.d/K14resin-a"sr/local/resin/bin/resin-a.sh /etc/rc.d/rc3.d/S86resin-a"

"ln -s /usr/local/resin/bin/resin-a.sh /etc/rc.d/rc5.d/S86resin-a" "ln -s /usr/local/resin/bin/resin-a.sh /etc/rc.d/rc2.d/K14resin-a"

by 제이 | 2005/04/18 19:05 | JAVA, JSP 썅!! | 트랙백 | 덧글(1)
resin command line argument
이글루는 표가 지원안된다...
간신히 미리보기에서 제대로 보이게 만들었더만 정작 올리니까 깨진다.
결국 사내 intranet에 올린 걸 그림으로 떠서 붙이기로 했다...쩝
by 제이 | 2005/04/18 17:12 | JAVA, JSP 썅!! | 트랙백 | 덧글(0)
ITIL Foundation
ITSMF korea에서 하는 첫 포럼 기념의 행사였던 ITIL Foundation교육을 받았다.

2일간 교육과 마지막날 인증시험이 있었고 꽤나 힘들게 공부했다.

내용은 쉬웠지만 너무 짧은 기간이 문제였다.

떨어질까 겁났는데 합겼했다....^^

4일 과정이라면 무난할 듯 하다.

올해 목표가 PMP, CISSP, ITIL Foundation이었는데 일단 하나는 이룬셈이다.

이제 PMP를 향해 달려가야겠다....이건 좀 더 공부해야겠지?...^^
by 제이 | 2005/04/15 13:35 | 끄적끄적 | 트랙백 | 덧글(2)
resin.conf(2)
이번 내용은 지난주에 언급한 바와 같이 다중 서비스 구축 방법에 대해서 알아보겠다.

1. 다중서비스 구축방법

이 문제는 resin이 standalone으로 구동된다는 전제하에 해당되는 것이다. 만약 Apache나 IIS에 plugin으로 구동시키고 있다면 두 개의Instance를 띄운다는 것은 Apache와 IIS의 설정과 관련된 일이므로 이 문서의 범위 밖의 일이므로 언급하지 않겠다.

두 개 이상의 instance를 사용하는 방법
현재 resin은 기본적으로 단일 Java 프로세스로 구동되며 내부적으로 Client의 요청마다 Thread를 생성하여 구동하는 기본적인 WebServer구조를 유지하고 있다.

즉, 이 말은 두 개의 instance를 띄운다는 것은 (Oracle에서의 Instance개념과 달리) 두 개의 Java Process를 각각 구동시킨다는 의미가 된다.

그러므로 두 개의 프로세스를 구동시키기 위해서는 Unix나 Windows 모두 권한이 있는 계정으로 접속한 후 command를 통해 여러개의process를 띄우면 되겠으나 두가지 고려할 사항이 있다.

1. port 설정

만약, 같은 port로 두 개를 띄우고 각각 자동적으로 서비스 되길 바란다면 그것은 두 개의 서비스가 아니라 하나의 서비스에 load balancing을 위한 설정을 하겠다는 뜻이다.

그러므로 두 개의 instance를 띄운다는 것은 각각 port가 다르게 설정되어야 함을 의미한다. port가 다르다는 것은 두 개의 resin.conf 파일이 각각 다르다는 것을 의미한다.

즉, $RESIN_HOME/bin/httpd -install -conf $파일명을 사용하여 각각 다른 conf파일을 지정해야 할 것이다.

2. Windows Service명 중복

Unix의 경우 어차피 Daemon Process로 구동되도록 명령을 수행할때, 같은 process명이라도 pid가 다르므로 상관없이 둘 다 daemon 으로 구동되겠지만 Windows의 경우 Background process로 구동하기 위해 service로 구동할 때는 service명이 같으면 안된다는 문제가 있다.

이 문제는 서비스 명을 다르게 주어서 등록하는 방법을 사용해 해결하면 된다.

즉, $RESIN_HOME/bin/httpd -install-as $서비스명을 사용하여 구동하여 중복된 이름을 방지할 수 있다.

이상의 두가지 문제는 이미 올렸던 글 1.Resin Install Command Line Argument을 참조하면 알 수 있다.

다중 web-app 와 가상호스트
지난 글에도 언급했지만 resin.conf의 구조는 아래와 같다.

<caucho.com>
<http-server>
<host id='gryffindor.caucho.com' app-dir='gryffindor'>
<web-app id='/'>
<servlet-mapping .../>
...
</web-app>
<web-app id='/test' app-dir='/usr/local/test'>
...
</web-app>
</host>
<host id='slytherin.caucho.com' app-dir='slytherin'>
...
</host>
...
</http-server>
</caucho.com>


이 구조를 잘 살펴보면 하나의 http-server에 두개 이상의 host가 존재하며 하나의 host에 두개 이상의 web-app가 존재함을 알 수 있다.

즉, 아래의 그림으로 설명할 수 있다.



위의 그림을 보면 의문점이 생길 것이다.

맨 아래쪽의 접근 방식을 보면 하나의 web-app를 사용할 때도 위와 같이 디렉토리명을 사용해서 접근이 가능한데 무엇이 다른가 하는 것이다.

다른점은 다른 app로 작동하느냐 이다.

즉, 하나의 web-app를 사용할 때는 아무리 디렉토리별로 다르게 접근한다고 해도 모두 같은 session을 공유하고 같은 WEB-INF의 class를 사용하도록 되어 있다.

하지만, 위와 같은 경우는 각기 다른 session을 가지며, 또한 WEB-INF 역시 각기 달리 갖는다. 완전히 독립적인 app로 인식한다는 것이다.

게다가 web.xml을 사용할 경우도 역시 각기 다른 web.xml을 사용해야 함은 물론이다.

그렇다면 가상호스트는 무엇인가?

위의 그림에서 하나의 서버에 두 개의 host가 존재한다

각각은 고유의 도메인을 가지고 있지만 같은 host의 같은 ip를 사용한다.

즉, 글자 그대로 가상의 호스트처럼 동작한다는 의미이다.

일단 사용자의 hosts파일은 아래와 같다고 가정한다.

/etc/hosts

127.0.0.1 localhost

127.0.0.1 www.sms.co.kr

127.0.0.1 www.maxigent.co.kr


사용자는 www.maxigent.co.kr로 접속을 시도한다. 그러면 먼저 사용자의 hosts파일을 검색해서 해당 도메인에 대한 정보에 해당하는 ip로 접속을 시도한다.

만약 해당정보가 없다면 해당 user의 시스템에 설정된 DNS서버에 quering을 하게 될 것이다.

이 부분에 대한 자세한 정보를 원한다면 internetworking의 구조에 대해 참조하기 바란다.

resin은 해당 request가 들어오면 자신의 conf파일을 검색해서 host id와 mapping을 시도한다.

그 결과 해당하는 host id가 존재하면 그부분의 web-app를 반환하게 된다.

결론적으로 기본적인 virtual hosting을 위한 resin.conf는 아래와 같다

<http-server>
...
<host id='sms.sds.co.kr'>
<app-dir>/home/www/sms/docs</app-dir>
...
</host>
<host id='maxigent.sds.co.kr'>
<app-dir>/home/www/maxigent/docs</app-dir>
...
</host>


이 이외에 Virtual Host with Apache or IIS, JVM per Virtual Host, IP-Based Virtual Hosting등의 좀더 깊이있는 주제는 http://www.caucho.com/resin-2.1/ref/virtual-host.xtp 을 살펴보기 바란다.

각 방법별 적용
위에서 두 개 이상의 web-app를 구동하는 방법을 알아봤다.

대부분의 site에서는 위와 같은 방법을 사용하여 운영할 이유는 특별히 없을 것이다.

그러나, 개발중인 경우나 test나 BMT등의 daemo용으로 구축을 요할 때 위의 방법중 하나를 사용하는 것은 필요하다.

위의 방법중 첫 번째 resin을 두 개 이상 구동하는 것을 추천한다.

물리적인 장비의 성능 및 용량이 충분하다면 이 방법을 사용하여 운영중이거나 혹은 다른 개발중인 app에 영향없이 다른 app를 구동할 수 있기때문이다.

물론, virtual host나 web-app를 두 개 이상을 두는 것도 생각해 볼 수 있는 방법이긴 하나 일단 web-app를 두 방법 모두 해당 resin instance의 성능을 나눠 사용하는 것이므로 먼저 운영중인 app에 영향이 생기는 것은 부정할 수 없다.

또한, web-app를 나눠 사용하는 경우 doc-root가 같기 때문에 개발자의 실수로 인한 다른 app의 문제 발생 소지를 가지고 있다.

virtual host의 경우 일단 DNS를 설정해야 한다는 문제가 있고, 그렇지 않을 경우 ip-based로 설정해야 하는데 이것 또한 장비의 NIC가 두 개 이상이어야 한다는 제한이 생기게 된다.

즉, 두 개 이상의 서비스가 필요하다면 장비의 성능이 제공하는 범위에서 각기 다른 process로 구동하라는 것이 결론이다.

장비의 성능이 문제가 된다면 -Xms, -Xmx -Xss등의 메모리 관련 command line argument와 <thread-max>, <thread-keepalive>, <request-timeout>, <accept-buffer-size>, <thread-min> 등의 값을 조절하면 될 것이다.
by 제이 | 2005/04/15 13:31 | JAVA, JSP 썅!! | 트랙백(2) | 덧글(2)


<< 이전 페이지 다음 페이지 >>