Category Archives: JAVA

[JOTM+Xapool] xapool 이용 시 Null Pointer Exception 문제 해결

사용자 삽입 이미지서로 다른 데이터 소스를 하나로 묶어 트랜젝션을 이용할 수 있게 해주는 멋진 라이브러리로 JOTM이라는 것이 있습니다.

보통은 JOTM + Xapool 조합으로 사용하게 됩니다. 하지만 사실 이 둘의 라이브러리는 시대에 많이 뒤떨어지는 것이 아닐까 하는 생각이 듭니다.

둘다 업데이트가 2년이 넘게 없어왔기 때문입니다. 이쯤 되면 이 오픈소스 프로젝트들은 사실상 더이상 이어지지 않는다고 봐도 되겠죠.

그 예로 Xapool의 마지막 stable 버젼인 1.5.0에는 치명적인 문제가 한가지 있습니다. 물론 1.6.0beta 버젼에서 해결은 되었긴 하지만 beta버젼보다는 안전한 stable버젼을 이용하고픈 마음이 들기 마련이죠.

[code]java.lang.NullPointerException


at org.enhydra.jdbc.pool.GenericPool.getFromPool(GenericPool.java:200)
at org.enhydra.jdbc.pool.GenericPool.checkOut(GenericPool.java:351)
at org.enhydra.jdbc.pool.StandardPoolDataSource.getConnection(StandardPoolDataSource.java:194)
at org.enhydra.jdbc.pool.StandardPoolDataSource.getConnection(StandardPoolDataSource.java:164)
at my.jotm.test.Client.getConnection(Client.java:63)


java.sql.SQLException: SQLException in StandardPoolDataSource:getConnection exception: java.sql.SQLException: SQLException in
StandardPoolDataSource:getConnection no connection available java.lang.NullPointerException


at org.enhydra.jdbc.pool.StandardPoolDataSource.getConnection(StandardPoolDataSource.java:213)


at org.enhydra.jdbc.pool.StandardPoolDataSource.getConnection(StandardPoolDataSource.java:164)[/code]
위의 에러 어떠십니까? 마음에 들어 보이십니까? 이와 같은 Null Pointer Exception 에러를 내뿜는 에러를 만날 수 있습니다.

위의 에러는 Xapool에서 내는 에러인데요. [이곳]에 관련 패치가 등록 되어있습니다.

1290343559.patch


이 패치의 내용은 다음과 같습니다. 커넥션을 얻어올때 특정한 상황에 따라 Null을 받아오게 되면 다음의 보관된 논리적인 커넥션을 얻어오도록 넘어가는 처리만 추가되었습니다.

[code]— xapool/org/enhydra/jdbc/pool/GenericPool.java-1.13 2005-06-14 21:57:10.756790600 -0500
+++ xapool/org/enhydra/jdbc/pool/GenericPool.java 2005-06-15 13:11:09.601072300 -0500
@@ -189,6 +189,12 @@
   
       o = (GenerationObject) e.nextElement();
       life = (Long) unlocked.get(o);
+      if (life == null) {
+   // Fix for #303462; note that this fixes the problem, but Enumeration’s on Hashtable’s
+   // are by definition somewhat unpredictable; a more robust fix may be in order
+   log.debug(“GenericPool:getFromPool fix for #303462 encountered”);
+   continue;
+      }
       unlocked.remove(o);
       // In any case the object will be removed.
       // Prevents others accessing the object while we are
[/code]
실제로 해당 패치를 적용한 후에는 관련 문제점이 발견되지 않았습니다. 혹시 귀찮으신 분들을 위해 패치된 버젼을 올려둡니다.
1000564104.jar

Apache MINA 2.0 에코서버 만들어 보기

사용자 삽입 이미지

제작년인가 JCO 컨퍼런스에서 이희승님의 발표 이후에 잊을 수 없던 프로젝트가 있었습니다.

바로 MINA(A Multi-purpose Infrastructure for Network Applications)인데요.

간단하게 말하면 자바의 네트워크 애플리케이션을 위한 프레임워크입니다.

필터를 사용한 뛰어난 확장성과 프로토콜 코덱과 비즈니스 로직을 분리하여 유지보수와 재사용성을 높인것이 특징입니다.

더군다나 커미터가 이희승님이라는 것이 중요한 점입니다. 한글로 질문해도 답변해 주시겠죠? -_-a

간단하게 예제 프로그램을 따라 만들어 보았습니다. [이곳]을 참고하였습니다.

현재 MINA2가 M3까지 나왔더군요. 예제를 위해서는 MINA코어뿐만 아니라 SLF4JLog4J가 필요합니다.

SLF4J의 경우에는 slf4j-api.jar파일과 slf4j-logj12.jar가 필요합니다. 13버젼용도 있지만 아직 알파버젼이니 12로 하기로 하였습니다.

그리고 log4j 1.2버젼의 jar로 세팅합니다.

MinaTimeServer
[code]import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
 
import org.apache.mina.core.service.IoAcceptor;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
 
public class MinaTimeServer
{
    private static final int PORT = 9123;
 
    public static void main(String[] args) throws IOException
    {
        IoAcceptor acceptor = new NioSocketAcceptor();

        acceptor.getFilterChain().addLast( “logger”, new LoggingFilter() );
        acceptor.getFilterChain().addLast(“codec”, new ProtocolCodecFilter(
                                            new TextLineCodecFactory(Charset.forName(“UTF-8”))));
 
        acceptor.setHandler(new TimeServerHandler());
 
        acceptor.getSessionConfig().setReadBufferSize(2048);
        acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
 
        acceptor.bind(new InetSocketAddress(PORT));
    }
}[/code]
Non-Blocking IO로 만듭니다. FilterChain이라는것에 필터를 추가합니다.

addLast라는 것을 보니 내가 원하는 순서대로 필터를 등록할 수 있는 모양입니다.

위와 같이 로깅을 하거나 인코딩 코덱을 만들어 사용할 수 있습니다.

핸들러를 추가하고 버퍼와 유휴시간을 정의한 후에 PORT를 설정하여 Bind합니다.

TimeServerHandler
[code]import java.util.Date;
 
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
 
public class TimeServerHandler extends IoHandlerAdapter
{

    @Override
    public void exceptionCaught(IoSession session, Throwable cause)
        throws Exception
    {
        cause.printStackTrace();
    }

    @Override
    public void messageReceived(IoSession session, Object message)
        throws Exception
    {
        String str = message.toString();
 
        if(str.trim().equalsIgnoreCase(“quit”))
        {
            session.close(true);
            return;
        }
 
        Date date = new Date();
        session.write(date.toString() + “\r\n”);
        System.out.println(“Message written…”);
    }

    @Override
    public void sessionIdle(IoSession session, IdleStatus status)
        throws Exception
    {
        System.out.println(“IDLE ” + session.getIdleCount(status));
    }
}[/code]
이녀석이 실제로 통신에 사용되는 핸들러입니다. 메시지를 받을때 마다 messageReceived이 호출됩니다.

쓰레드 방식의 모델이라 보기 힘든 구조네요, 콜백형식으로 작동하는 것을 알 수 있습니다.

다음에는 객체를 Serial로 주고 받을 수 있는지 해봐야겠습니다.

sessionIdle은 Main에서 정의한 유휴시간마다 호출되는 녀석입니다. 10초로 설정해 두었으니 10초동안 유휴상태로 있다면 그때마다 이 메서드가 호출됩니다.

getIdleCount를 이용해 카운트도 알 수 있군요. 서버를 완성했으니 실행해 볼까요.

사용자 삽입 이미지


quit를 입력하면 종료되고 그 이외의 문자를 입력하면 시간이 출력되는 것을 알 수 있습니다.