2017-05-16 3 views
3

Java EE 응용 프로그램에서 Java의 ServiceLoader을 사용하여 서비스를로드하려고합니다. 로드하려는 .jar 파일은 테스트 Java SE 응용 프로그램에서 작동하므로 올바른 것으로 가정합니다. 그러나, 아래의 코드는 itr.next에 실패Glassfish4 Java EE 응용 프로그램에서 ServiceLoader를 사용하는 경우 ClassNotFoundException

ServiceLoader<WorkflowStepSPI> loader = ServiceLoader.load(WorkflowStepSPI.class, Thread.currentThread().getContextClassLoader()); 
     loader.reload(); 
     List<String> names = new LinkedList<>(); 
     Iterator<WorkflowStepSPI> itr = loader.iterator(); 
     while (itr.hasNext()) { 
      WorkflowStepSPI wss = itr.next(); 
      logger.log(Level.INFO, "Found WorkflowStepProvider: {0}", wss.getClass().getCanonicalName()); 
      names.add(wss.toString()); 
     } 

의 ClassNotFoundException에 던져 예외를, (그렇지 않으면 코드가 컴파일되지 않을 것이다) 분명히 존재하는, WorkflowStepSPI을 찾을 수 없다는 불평. 다른 테스트에서는 Class.forName이이 클래스를 반환한다는 것을 확인했습니다.

내 자신의 URLClassLoader 인스턴스를 here으로 만들고 URL을 here으로 직접로드하려고 시도했지만 아무 소용이 없습니다.

아이디어가 있으십니까?

* 업데이트 * 요청으로

, 여기에 스택 트레이스의 : 정적으로 컴파일 된 클래스가 런타임에 사용할 수없는 경우 (A ClassNotFoundException 반대) A는 NoClassDefError가 발생 일반적으로

Warning: Class not found: edu/harvard/iq/dataverse/workflow/WorkflowStepSPI 
java.lang.NoClassDefFoundError: edu/harvard/iq/dataverse/workflow/WorkflowStepSPI 
at java.lang.ClassLoader.defineClass1(Native Method) 
at java.lang.ClassLoader.defineClass(ClassLoader.java:763) 
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) 
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) 
at java.net.URLClassLoader.access$100(URLClassLoader.java:73) 
at java.net.URLClassLoader$1.run(URLClassLoader.java:368) 
at java.net.URLClassLoader$1.run(URLClassLoader.java:362) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.net.URLClassLoader.findClass(URLClassLoader.java:361) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:411) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 
at org.glassfish.web.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1730) 
at org.glassfish.web.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1633) 
at java.lang.Class.forName0(Native Method) 
at java.lang.Class.forName(Class.java:348) 
at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:370) 
at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404) 
at java.util.ServiceLoader$1.next(ServiceLoader.java:480) 
at edu.harvard.iq.dataverse.api.WorkflowsAdmin.testSpi(WorkflowsAdmin.java:215) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:498) 
at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) 
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:151) 
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:171) 
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:152) 
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104) 
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:387) 
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:331) 
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:103) 
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:271) 
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) 
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) 
at org.glassfish.jersey.internal.Errors.process(Errors.java:315) 
at org.glassfish.jersey.internal.Errors.process(Errors.java:297) 
at org.glassfish.jersey.internal.Errors.process(Errors.java:267) 
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:297) 
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:254) 
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1028) 
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:372) 
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381) 
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344) 
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:221) 
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) 
at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:205) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) 
at edu.harvard.iq.dataverse.api.ApiBlockingFilter$3.doBlock(ApiBlockingFilter.java:65) 
at edu.harvard.iq.dataverse.api.ApiBlockingFilter.doFilter(ApiBlockingFilter.java:157) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) 
at edu.harvard.iq.dataverse.api.ApiRouter.doFilter(ApiRouter.java:30) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) 
at org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:873) 
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:739) 
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:575) 
at org.apache.catalina.core.ApplicationDispatcher.doDispatch(ApplicationDispatcher.java:546) 
at org.apache.catalina.core.ApplicationDispatcher.dispatch(ApplicationDispatcher.java:428) 
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:378) 
at edu.harvard.iq.dataverse.api.ApiRouter.doFilter(ApiRouter.java:34) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214) 
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316) 
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160) 
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734) 
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673) 
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99) 
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174) 
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:415) 
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:282) 
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459) 
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167) 
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201) 
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175) 
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235) 
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119) 
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284) 
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201) 
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133) 
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112) 
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77) 
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561) 
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112) 
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117) 
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56) 
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137) 
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565) 
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545) 
at java.lang.Thread.run(Thread.java:745) 
Caused by: java.lang.ClassNotFoundException: edu.harvard.iq.dataverse.workflow.WorkflowStepSPI 
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 
... 94 more 
+0

현재 얻고있는 스택 추적은 어디에 있습니까? 스택 트레이스에 따라 누락 된 클래스는 무엇입니까? 배포 구조는 어떻게 생겼습니까? jar 파일이있는 war 파일을 종속성으로 배포 하시겠습니까? 아니면 직접 jar 파일로 배포합니까? github에 간단한 버전의 앱을 게시 할 수 있습니까? ServiceLoader는 EE 컨테이너에서 제대로 작동하므로 배포에서보다 근본적인 문제가 원인이라고 가정합니다. – yntelectual

+0

프로젝트는 maven을 기반으로하는 표준 .war 파일입니다. 이것은 내 컴퓨터에서 로컬 Glassfish 4.1, Mac OS에서 발생합니다. SPI 구현의 .jar는 domain/lib 폴더에 있습니다. –

답변

0

, (ClassNotFoundException은 단순히 반사가없는 클래스를 얻으려고 할 때 발생합니다 (예 : Class.forName() 사용).

코드를 컴파일 할 때 클래스가 클래스 경로에 존재했습니다. 그러나 구성을 보지 않고는 결정할 수없는 여러 가지 이유로 클래스는 서버에서 사용할 수 없습니다. 가능한 원인은 다음과 같습니다.

  • 프로젝트를 (예 : .class 파일을 생성 한) 다른 프로젝트와 교차 편집 했으므로 다른 프로젝트가 WAR에 포함되지 않은 것입니다 (예 : 그 내용 WEB-INF/classes에 복사되지 않았습니다)
  • 가 어떤 이유로 WAR와 함께 제공되지 않은 라이브러리에 포함 된 다른 출력 디렉토리
  • 당신의 WAR은 잘못이고 (클래스 파일을 적절한 구조를 포함하지 않는해야 WEB-INF/classes에 들어가면 라이브러리는 WEB-INF/lib에 들어가야합니다.
  • 코드를 컴파일 한 Java 배포판과 다른 Java 배포판에서 서버를 실행하고 있습니다 (클래스 패키지로 인해 여기서는 분명히 해당하지 않지만 완전성을 위해 가리 키기 만 함).

일반적으로 , 서버와 함께 묶을 애플리케이션 별 WAR (일부 서버 특정 폴더)을 사용하는 것은 좋지 않은 습관이다. 또한 응용 프로그램 서버에서 일부 클래스 로더 분리 문제로 인해 미묘한 오류가 발생합니다. 대신 WAR에는 필요한 패키지가 들어 있습니다.

0

연습에 대한 piotr-wilkin의 탁월한 대답은 다음과 같습니다. 내가 가진 상태와 해결 방법은 다음과 같습니다.

시작 지점

시간을 절약하기 위해 (아이러니를!) 나는 SPI 구현 프로젝트에 대한 종속성으로 웹 애플리케이션의 .war 파일을 사용했다.이를 통해 SPI 구현시 기본 프로젝트의 클래스를 사용할 수있었습니다. 하지만 분명히 Glassfish의 클래스 로더를 혼란스럽게 만들었습니다 (Java SE의 클래스 로더는 이와 관련한 문제가있는 상태이기 때문에).

  1. 수정은 내가 SPI 구현해야하는 인터페이스와 새로운 .jar 파일을 만들었습니다. 이 jar 파일은 웹 응용 프로그램과 SPI 구현 프로젝트 모두에 대한 종속성으로 추가되었습니다.

  2. SPI의 .jar를 평소대로 포장했습니다 (META-INF/services/.....).
  3. SPI 구현의 .jar와 인터페이스의 .jar를 도메인의 lib 폴더에 추가했습니다.
  4. 재시작하는 글래스 피시

지금, 내가 대해 너무 행복하지 않다 인터페이스의 두 복사본을 가지고 있음을 깨닫는다. 그러나 그것은 단지 인터페이스이고 정적 필드에는 아무런 상태도 포함하지 않기 때문에 이것이 미학적 인 문제라고 생각합니다.

관련 문제