상세 컨텐츠

본문 제목

java.lang.NoSuchMethodException

Oracle/Weblogic

by 야솔아빠 2011. 10. 20. 17:45

본문

반응형
weblogic + spring ejb를 이용하여 EJB를 사용하여 transaction을 관리하였습니다.

아래 그림처럼, transactin을 관리하는 Transaction domain 에서 Service1, Service2 domain에 존재하는 EJB 모듈을 호출하도록 하였습니다.




이렇게 서비스를 하는 도중에 아래와 같은 에러가 서버에서 났습니다.
에러는 자주 발생하는 것은 아니지만, 약 1~2주 시간이 경과를 하면 발생을 합니다. 불규칙적이며, 어떻게도 설명을 하지 못할 정도였습니다.

    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:95)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:226)
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:89)
    at org.apache.cxf.transport.servlet.ServletDestination.invoke(ServletDestination.java:99)
    at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:350)
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:145)
    at org.apache.cxf.transport.servlet.AbstractCXFServlet.invoke(AbstractCXFServlet.java:163)
    at org.apache.cxf.transport.servlet.AbstractCXFServlet.doPut(AbstractCXFServlet.java:157)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:730)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
    at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
    at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
    at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3498)
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
    at weblogic.security.service.SecurityManager.runAs(Unknown Source)
    at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2180)
    at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2086)
    at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1406)
    at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
Caused by: java.lang.NoSuchMethodException:
    at java.lang.Class.getMethod(Class.java:1605)
    at weblogic.ejb.container.internal.RemoteBusinessIntfProxy.getTargetMethod(RemoteBusinessIntfProxy.java:162)
    at weblogic.ejb.container.internal.RemoteBusinessIntfProxy.invoke(RemoteBusinessIntfProxy.java:53)

응급조치는 trsnaction domain의 was instance를 재기동하면 됩니다.

2년동안 이문제의 근본원인을 못찾고 재기동하는 방법으로 버텨왔는데, 다음과 같은 방법으로 해결을 했습니다.
java.lang.NoSuchMethodException 이 발생할 때는, 소스는 주석으로 처리된 소스입니다.
ejbRemoteBean 을 member 변수로 두어, null 이 아닐 경우는 재사용하도록 하였습니다.

        InitialContext context = null;
        try {
            if ( contentLifeCycleServiceBeanRemote == null ) {
                if ( log.isInfoEnabled() )
                    log.info("** lookup " + SERVICE1);
                context = getInitialContext(...);

                Object lookupObject = context.lookup(SERVICE1);
                ServiceBeanRemote beanRemote = (ServiceBeanRemote) PortableRemoteObject
                        .narrow(lookupObject, ServiceBeanRemote.class);
                contentLifeCycleServiceBeanRemote = beanRemote;

                if ( log.isInfoEnabled() )
                    log.info("** lookup success " + SERVICE1);
            }
           
        }
        catch ( NamingException e ) {

해결방법은 아래처럼 ejbRemoteBean을 재사용하지 않고 request 발생시마다, remoteBean을 lookup 하도록 하였습니다.
어찌보면 비효율적일 수 있으나, 이렇게 하여 문제가 해결되었습니다.
        InitialContext context = null;
        try {
            if ( log.isInfoEnabled() )
                log.info("** lookup " + SERVICE1);
            context = getInitialContext(...);

            Object lookupObject = context.lookup(SERVICE1);
            ServiceBeanRemote beanRemote = (ServiceBeanRemote) PortableRemoteObject
                    .narrow(lookupObject, ServiceBeanRemote.class);
            serviceBeanRemote = beanRemote;

            if ( log.isInfoEnabled() )
                log.info("lookup success " + SERVICE1);
            return serviceBeanRemote;
           
        }
        catch ( NamingException e ) {

추측되는 원인은, remoteBean을 재사용하면,
service1, service2 domain의 EJB module과 transaction domain에서 가지고 있는 remoteBean 모듈이 sync가 깨지는 것으로 보여집니다. 그 시점은 알 수 없었습니다.
그 시점을 밝혀보기 위해서 많은 테스트를 해봤습니다.
service1, service2 domain을 무작위로 중지시켜 보고, 신규 ejb module을 디플로이도 해보고 했습니다.

참고로 이 문제로 오라클엔지니어가 몇 번을 방문했었고, 상황재연이 쉽게 되지 않아 오라클측에서도 해결은 못했었습니다.
2년이 넘도록 문제가 해결이 안되었는데, 이런 방법으로 해결이 되었습니다.
반응형

관련글 더보기

댓글 영역