Google App Engine 1.3.1 실행 시의 오류 - javax.xml.parsers.FactoryConfigurationError: Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found

이클립스에 구글 앱 엔진 플러그인을 설치한 후 어플리케이션을 하나 만들고, 결과를 확인하려고 '프로젝트명 우클릭 > Run As > Web Application'을 실행했다.

간단한 테스트 앱이라 잘 될거라 생각했는데, 왠걸 이클립스 콘솔에 오류 로그가 주르륵 출력된다.

2010. 2. 28 오후 3:10:52 com.google.apphosting.utils.jetty.JettyLogger warn

경고: failed com.google.apphosting.utils.jetty.DevAppEngineWebAppContext@ca0115{/,D:\dev\WORKSPACE_APPENGINE\JavaShop\war}

javax.xml.parsers.FactoryConfigurationError: Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found

    at javax.xml.parsers.SAXParserFactory.newInstance(SAXParserFactory.java:134)

    at org.mortbay.xml.XmlParser.setValidating(XmlParser.java:92)

    at org.mortbay.xml.XmlParser.<init>(XmlParser.java:84)

    at org.mortbay.jetty.webapp.TagLibConfiguration.configureWebApp(TagLibConfiguration.java:202)

    at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1215)

    at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:500)

    at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)

    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)

    at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117)

    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)

    at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117)

    at org.mortbay.jetty.Server.doStart(Server.java:217)

    at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)

    at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:188)

    at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:147)

    at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:219)

    at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:162)

    at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48)

    at com.google.appengine.tools.development.DevAppServerMain.<init>(DevAppServerMain.java:113)

    at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:89)


The server is running at http://localhost:8888/

어쨌든 서버는 시작됐다니까 주소줄에 'http://localhost:8888/'을 넣고 이동해 봤다. 역시 제대로 안뜬다.

구글링 해보니까 'war/WEB-INF/lib' 디렉토리에 xercesImpl.jar 파일을 넣으면 해결된단다. 구글 앱은 XML Parser 관련한 이런 저런 문제가 좀 있는 것 같다.

서버를 죽이려고 구글 앱을 위한 Server View가 있나 찾아 봤는데, 그런건 없다. 콘솔 우측의 Terminate 버튼을 눌러서 서버를 중지한 후 xercesImpl.jar를 복사해 넣어 주고 재시작.

잘 된다.

신고

Spring MVC의 CommonsMultipartResolver를 사용하여 업로드한 임시파일은 지워질까?

Spring MVC는 Commons FileUpload 패키지를 이용한 파일 업로드를 지원한다.


아무 생각 없이 사용하고 있다가 문득 FileUpload를 Spring 없이 사용할 때는 FileCleanerCleanup 리스너를 web.xml에 등록해서 temporary 파일을 자동으로 삭제하게 한다는게 기억났다.


아차! 지금이라도 등록해 줘야하는건가? 하는 생각에 확인차 서버의 temporary 경로를 살펴봤다.

그런데 이상하게도 파일 업로드 후에 남아 있었어야할 임시 파일이 하나도 없었다.


CommonsMultipartResolver가 뭔가 알아서 지우는건가 해서 뒤져봐도 관련 코드는 없었다.

이해가 안가서 좀 더 뒤지다가 결국 DispatcherServlet에서 삭제 코드를 찾았다. doDispatch 메서드의 finally 절에 cleanupMultipart 메서드를 호출하는 부분이 있었던 것이다.

public class DispatcherServlet extends FrameworkServlet {


    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

        ......

        try {

            ......

        finally {

            // Clean up any resources used by a multipart request.

            if (processedRequest != request) {

                cleanupMultipart(processedRequest);

            }


            // Reset thread-bound context.

            RequestContextHolder.setRequestAttributes(previousRequestAttributes, this.threadContextInheritable);

            LocaleContextHolder.setLocaleContext(previousLocaleContext, this.threadContextInheritable);


            // Clear request attributes.

            requestAttributes.requestCompleted();

            if (logger.isTraceEnabled()) {

                logger.trace("Cleared thread-bound request context: " + request);

            }

        }

    }


    /**

     * Clean up any resources used by the given multipart request (if any).

     * @param request current HTTP request

     * @see MultipartResolver#cleanupMultipart

     */

    protected void cleanupMultipart(HttpServletRequest request) {

        if (request instanceof MultipartHttpServletRequest) {

            this.multipartResolver.cleanupMultipart((MultipartHttpServletRequest) request);

        }

    }

    ......

}




신고

cygwin에서 classpath와 함께 java 콘솔 프로그램 실행하기

책(Groovy Recipes)을 보다가 간단한 groovy 프로그램을 groovyc로 컴파일한 후 실행하려고 했더니 잘 안된다.

$ java -classpath .:$GROOVY_HOME/embeddable/groovy-all-1.7.0.jar Greet

Exception in thread "main" java.lang.NoClassDefFoundError: Greet

Caused by: java.lang.ClassNotFoundException: Greet

        at java.net.URLClassLoader$1.run(URLClassLoader.java:200)

        at java.security.AccessController.doPrivileged(Native Method)

        at java.net.URLClassLoader.findClass(URLClassLoader.java:188)

        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)

        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)

        at java.lang.ClassLoader.loadClass(ClassLoader.java:251)

        at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)

보아하니 java 클래스로 컴파일된 groovy 파일을 실행하려면 필요한 groovy-all-1.7.0.jar 파일이 classpath로 안잡히는 거다.

cygwin에서 실행되는 java.exe는 윈도우용이라서 cygwin의 path 방식(유닉스 형식)을 이해할 수가 없다. 따라서 윈도우 방식의 path로 바꿔줘야한다.

$ java -classpath `cygpath -wp .:$GROOVY_HOME/embeddable/groovy-all-1.7.0.jar` Greet

Groovy Rocks!

신고

이클립스에서 log4j 설정과 함께 자바 어플리케이션 실행

Run Configutaions의 VM arguments에 다음과 같이 log4j.properties 혹은 log4j.xml 파일의 경로를 지정해 준다.

-Dlog4j.configuration=file:/C:/WORKSPACE_STS/SNOW/log4j.properties



신고

MySQL 5.0.45 원하는 위치에 수동 설치 및 윈도 서비스로 등록 하기

테스트 환경으로 사용할 일이 생겨서 MySQL을 집에 설치 했었습니다. 인스톨러 없이 D:\TOOLS 디렉토리에 UTF-8 환경으로 설치한 후 윈도 서비스로 등록까지 마쳤는데... 오늘 설치본을 그대로 복사해서 회사에서 사용하는 컴퓨터에 설치하려고 하니 어떻게 했는지 기억이 전혀 안나더군요. :-( 이러한 이유로 여기에 설치법을 남깁니다.


MySQL 설치

저는 MySQL AB다운로드 페이지에 있는 윈도 버전 중 수동설치 버전(Without installer 혹은 ZIP Archive라고 써 있는 놈)을 다운로드 받았습니다. MySQL Account 만들거냐고 물어보면 아래에 있는 "No Thanks..." 링크를 눌러서 등록 안하고 받으셔도 됩니다.


무설치 버전인 만큼 설치는 매우 간단합니다. 원하는 디렉토리에 압축을 풀어주기만 하면 되죠!
저는 D:\TOOLS\mysql-5.0.45-win32 디렉토리에 압축을 풀었습니다.

다른 작업 없이 명령 프롬프트를 하나 실행한 다음 D:\TOOLS\mysql-5.0.45-win32\bin 디렉토리로 이동한 후에 "mysqld --console" 명령만 실행하셔도 MySQL 서버를 바로 사용하실 수 있습니다.

D:\TOOLS\mysql-5.0.45-win32\bin>mysqld --console
080220 10:47:57  InnoDB: Started; log sequence number 0 19944194
080220 10:47:58 [Note] mysqld: ready for connections.
Version: '5.0.45-community-nt'  socket: ''  port: 3306  MySQL Community Edition (GPL)

위와 비슷한 메시지를 보여 주며 오류 없이 MySQL 서버가 시작된 후, 다음과 같이 "mysqlshow -u root" 명령을 실행하시면 Database 목록을 볼 수 있습니다.

D:\TOOLS\mysql-5.0.45-win32\bin>mysqlshow -u root
+--------------------+
|     Databases      |
+--------------------+
| information_schema |
| mysql              |
| test               |
+--------------------+


위의 과정만으로도 MySQL은 사용할 수 있는 상태가 되었습니다만, 좀 더 세밀한 설정을 하기 위해서는 옵션 파일을 만들어 줘야 합니다. 옵션 파일의 예제가 설치 디렉토리에 있기 때문에 약간의 수정을 해주면 바로 사용할 수 있습니다. 설치 디렉토리(D:\TOOLS\mysql-5.0.45-win32)를 보면 5개의 ini 확장자를 가진 파일이 있습니다. 용도에 따라 선택 하시면 됩니다. 저는 간단한 테스트가 목적이기 때문에 my-small.ini 파일을 선택했습니다.
MySQL은 "[설치 디렉토리]\my.ini" 파일 혹은, "C:\Windows\my.ini" 파일이나 "C:\my.cnf" 파일을 옵션 파일로 찾습니다. 저는 my-small.ini 파일의 복사본을 하나 만들어서 my.ini로 이름을 변경한 후, "C:\Windows" 디렉토리로 복사해서 옵션 파일 설정을 마쳤습니다.

MySQL은 Windows directory에서 my.ini 파일을 찾습니다. Windows directory 경로는 윈도 종류에 따라서 다르기 때문에 정확한 경로를 확인하려면, 명령 프롬프트에서 다음의 명령을 실행해 보시면 됩니다.

C:\> echo %WINDIR%


윈도 서비스로 등록하기

이 글에서 옵션파일을 만들어서 사용하는 목적은 윈도 서비스로 MySQL을 등록하기 위해서입니다. 이를 위한 최소한의 수정을 한 후 MySQL을 윈도 서비스로 등록해 보겠습니다.

윈도 서비스로 등록하기 위해서는 my.ini 파일에 설치 경로를 명시해야합니다.
위에서 만든 "C:\Windows\my.ini" 파일을 열어서 "[mysqld]" 섹션을 찾은 후 다음의 2줄을 넣어 줍니다(경로 구분자로 '\'가 아닌 '/'를 사용합니다. 주의하세요!).

basedir = D:/TOOLS/mysql-5.0.45-win32
datadir  = D:/TOOLS/mysql-5.0.45-win32/data


쉽게 짐작할 수 있겠지만, 위의 내용은 설치경로와 MySQL이 사용하는 데이터의 저장 경로입니다.
이제 my.ini 파일은 아래와 비슷한 내용으로 변경되었을겁니다.

# The MySQL server
[mysqld]
basedir = D:/TOOLS/mysql-5.0.45-win32
datadir  = D:/TOOLS/mysql-5.0.45-win32/data

port  = 3306
socket  = /tmp/mysql.sock
skip-locking
key_buffer = 16K
max_allowed_packet = 1M
table_cache = 4
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 64K


이제 윈도 서비스로 등록을 해보죠. MySQL이 실행 중이라면, 아래의 명령을 실행하여 MySQL을 죽입니다.
D:\TOOLS\mysql-5.0.45-win32\bin>mysqladmin -u root shutdown

MySQL이 완전히 종료된 것을 확인한 후, 아래의 명령으로 MySQL을 윈도 서비스로 등록할 수 있습니다.
D:\TOOLS\mysql-5.0.45-win32\bin>mysqld --install

만약 MySQL 서비스의 시작유형을 자동이 아닌 수동으로 하고 싶다면, 아래의 명령으로 등록합니다.
D:\TOOLS\mysql-5.0.45-win32\bin>mysqld --install-manual

설치된 MySQL 서비스를 삭제하고 싶으면, 아래의 명령으로 삭제할 수 있습니다.
D:\TOOLS\mysql-5.0.45-win32\bin>mysqld --remove

윈도 서비스 등록에 대한 더 많은 정보를 원하시면 이곳의 문서를 참고하세요~!
charset euckr
set character set euckr;
show variables like 'c%';


신고