org.glassfish.jersey.process.internal.RequestScoped有多个活动上下文

时间:2018-10-08 08:17:57

标签: java jax-rs jersey-2.0 hk2

我在检索RequestScoped内的ContainerRequestFilter对象时遇到困难,我试图通过向过滤器中插入Provider来实现这一点。我的应用程序配置如下:

class MyResourceConfig extends ResourceConfig
{
  public static class MyBinder extends AbstractBinder 
  {
    @Override
    protected void configure()
    {
      bindFactory(PolicyFactory.class)
        .to(Policy.class)
        .in(RequestScoped.class);
    }
  }

  public MyResourceConfig()
  {
    register(new MyBinder());
    register(MyDynamicFeature.class);
  }
}

@Provider
class MyDynamicFeature implements DynamicFeature
{
  @Override
  public void configure(ResourceInfo ri, FeatureContext ctx)
  {
    ctx.register(MyRequestFilter.class);
  }
}

@Priority(Priorities.AUTHENTICATION)
public class MyRequestFilter implements ContainerRequestFilter
{
  @Context
  private HttpServletRequest request;

  @Context
  private ResourceInfo resourceInfo;

  @Inject
  private javax.inject.Provider<Policy> policyProvider;

  @Override
  public void filter(ContainerRequestContext requestContext) throws IOException
  {
    policyProvider.get();
  }
}

MyRequestFilter中调用提供程序时,出现以下异常:

A MultiException has 2 exceptions.  They are:
1. java.lang.IllegalStateException: There is more than one active context for org.glassfish.jersey.process.internal.RequestScoped
2. java.lang.IllegalStateException: While attempting to create a service for SystemDescriptor(
  implementation=com.*.PolicyFactory
  contracts={com.*.Policy}
  scope=org.glassfish.jersey.process.internal.RequestScoped
  qualifiers={}
  descriptorType=PROVIDE_METHOD
  descriptorVisibility=NORMAL
  metadata=
  rank=0
  loader=org.glassfish.hk2.utilities.binding.AbstractBinder$2@16c49a23
  proxiable=null
  proxyForSameScope=null
  analysisName=null
  id=178
  locatorId=48
  identityHashCode=1250168232
  reified=true) in scope org.glassfish.jersey.process.internal.RequestScoped an error occured while locating the context

  at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2120)
  at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:777)
  at org.jvnet.hk2.internal.ServiceLocatorImpl.getUnqualifiedService(ServiceLocatorImpl.java:789)
  at org.jvnet.hk2.internal.IterableProviderImpl.get(IterableProviderImpl.java:111)
  at com.*.MyEndpointFilter.hasResourceAccess(MyEndpointFilter.java:127)
  at com.*.MyEndpointFilter.filter(MyEndpointFilter.java:52)
  at org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:132)
  at org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:68)
  at org.glassfish.jersey.process.internal.Stages.process(Stages.java:197)
  at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:269)
  at org.glassfish.jersey.internal.Errors$1.call(Errors.java:272)
  at org.glassfish.jersey.internal.Errors$1.call(Errors.java:268)
  at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
  at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
  at org.glassfish.jersey.internal.Errors.process(Errors.java:268)
  at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:289)
  at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:256)
  at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:703)
  at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:416)
  ... 12 more
Caused by: java.lang.IllegalStateException: There is more than one active context for org.glassfish.jersey.process.internal.RequestScoped
  at org.jvnet.hk2.internal.ServiceLocatorImpl._resolveContext(ServiceLocatorImpl.java:2216)
  at org.jvnet.hk2.internal.ServiceLocatorImpl.access$000(ServiceLocatorImpl.java:128)
  at org.jvnet.hk2.internal.ServiceLocatorImpl$3.compute(ServiceLocatorImpl.java:188)
  at org.jvnet.hk2.internal.ServiceLocatorImpl$3.compute(ServiceLocatorImpl.java:184)
  at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:97)
  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:154)
  at org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:199)
  at org.jvnet.hk2.internal.ServiceLocatorImpl.resolveContext(ServiceLocatorImpl.java:2230)
  at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2104)
  ... 30 more

在调试时,我观察到创建了Hk2RequestScope的2个实例,并具有以下堆栈跟踪:

Thread [main] (Suspended (breakpoint at line 61 in Hk2RequestScope))    
  Hk2RequestScope.createContext() line: 61  
  Hk2RequestScope(RequestScope).runInScope(Producer<T>) line: 411   
  JerseyInvocation.invoke() line: 752   
  JerseyInvocation$Builder.method(String, Entity<?>) line: 445  
  JerseyInvocation$Builder.post(Entity<?>) line: 351    
  LoginTest.testBadNewPassword() line: 181  
  NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]    
  NativeMethodAccessorImpl.invoke(Object, Object[]) line: 62    
  DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43    
  Method.invoke(Object, Object...) line: 498    
  ReflectionUtils.invokeMethod(Method, Object, Object...) line: 513 
  ExecutableInvoker.invoke(Method, Object, ExtensionContext, ExtensionRegistry) line: 115   
  TestMethodTestDescriptor.lambda$invokeTestMethod$6(ExtensionContext, JupiterEngineExecutionContext) line: 170 
  22179697.execute() line: not available    
  ThrowableCollector.execute(Executable) line: 40   
  TestMethodTestDescriptor.invokeTestMethod(JupiterEngineExecutionContext, Node$DynamicTestExecutor) line: 166  
  TestMethodTestDescriptor.execute(JupiterEngineExecutionContext, Node$DynamicTestExecutor) line: 113   
  TestMethodTestDescriptor.execute(EngineExecutionContext, Node$DynamicTestExecutor) line: 58   
  HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(ExecutionTracker) line: 113 
  1803669141.execute() line: not available  
  SingleTestExecutor.executeSafely(SingleTestExecutor$Executable) line: 66  
  HierarchicalTestExecutor$NodeExecutor.executeRecursively(ExecutionTracker) line: 108  
  HierarchicalTestExecutor$NodeExecutor.execute(C, ExecutionTracker) line: 79   
  HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(ExecutionTracker, TestDescriptor) line: 121 
  232307208.accept(Object) line: not available  
  ForEachOps$ForEachOp$OfRef<T>.accept(T) line: 184 
  ReferencePipeline$2$1.accept(P_OUT) line: 175 
  LinkedHashMap$LinkedKeyIterator(Iterator<E>).forEachRemaining(Consumer<? super E>) line: 116  
  Spliterators$IteratorSpliterator<T>.forEachRemaining(Consumer<? super T>) line: 1801  
  ReferencePipeline$2(AbstractPipeline<E_IN,E_OUT,S>).copyInto(Sink<P_IN>, Spliterator<P_IN>) line: 481 
  ReferencePipeline$2(AbstractPipeline<E_IN,E_OUT,S>).wrapAndCopyInto(S, Spliterator<P_IN>) line: 471   
  ForEachOps$ForEachOp$OfRef<T>(ForEachOps$ForEachOp<T>).evaluateSequential(PipelineHelper<T>, Spliterator<S>) line: 151    
  ForEachOps$ForEachOp$OfRef<T>.evaluateSequential(PipelineHelper, Spliterator) line: 174   
  ReferencePipeline$2(AbstractPipeline<E_IN,E_OUT,S>).evaluate(TerminalOp<E_OUT,R>) line: 234   
  ReferencePipeline$2(ReferencePipeline<P_IN,P_OUT>).forEach(Consumer<? super P_OUT>) line: 418 
  HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(ExecutionTracker) line: 121 
  1803669141.execute() line: not available  
  SingleTestExecutor.executeSafely(SingleTestExecutor$Executable) line: 66  
  HierarchicalTestExecutor$NodeExecutor.executeRecursively(ExecutionTracker) line: 108  
  HierarchicalTestExecutor$NodeExecutor.execute(C, ExecutionTracker) line: 79   
  HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(ExecutionTracker, TestDescriptor) line: 121 
  232307208.accept(Object) line: not available  
  ForEachOps$ForEachOp$OfRef<T>.accept(T) line: 184 
  ReferencePipeline$2$1.accept(P_OUT) line: 175 
  LinkedHashMap$LinkedKeyIterator(Iterator<E>).forEachRemaining(Consumer<? super E>) line: 116  
  Spliterators$IteratorSpliterator<T>.forEachRemaining(Consumer<? super T>) line: 1801  
  ReferencePipeline$2(AbstractPipeline<E_IN,E_OUT,S>).copyInto(Sink<P_IN>, Spliterator<P_IN>) line: 481 
  ReferencePipeline$2(AbstractPipeline<E_IN,E_OUT,S>).wrapAndCopyInto(S, Spliterator<P_IN>) line: 471   
  ForEachOps$ForEachOp$OfRef<T>(ForEachOps$ForEachOp<T>).evaluateSequential(PipelineHelper<T>, Spliterator<S>) line: 151    
  ForEachOps$ForEachOp$OfRef<T>.evaluateSequential(PipelineHelper, Spliterator) line: 174   
  ReferencePipeline$2(AbstractPipeline<E_IN,E_OUT,S>).evaluate(TerminalOp<E_OUT,R>) line: 234   
  ReferencePipeline$2(ReferencePipeline<P_IN,P_OUT>).forEach(Consumer<? super P_OUT>) line: 418 
  HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(ExecutionTracker) line: 121 
  1803669141.execute() line: not available  
  SingleTestExecutor.executeSafely(SingleTestExecutor$Executable) line: 66  
  HierarchicalTestExecutor$NodeExecutor.executeRecursively(ExecutionTracker) line: 108  
  HierarchicalTestExecutor$NodeExecutor.execute(C, ExecutionTracker) line: 79   
  HierarchicalTestExecutor<C>.execute() line: 55    
  JupiterTestEngine(HierarchicalTestEngine<C>).execute(ExecutionRequest) line: 43   
  DefaultLauncher.execute(TestEngine, ExecutionRequest) line: 170   
  DefaultLauncher.execute(Root, ConfigurationParameters, TestExecutionListener...) line: 154    
  DefaultLauncher.execute(LauncherDiscoveryRequest, TestExecutionListener...) line: 90  
  JUnit5TestReference.run(TestExecution) line: 86   
  TestExecution.run(ITestReference[]) line: 38  
  RemoteTestRunner.runTests(String[], String, TestExecution) line: 538  
  RemoteTestRunner.runTests(TestExecution) line: 760    
  RemoteTestRunner.run() line: 460  
  RemoteTestRunner.main(String[]) line: 206 

Thread [grizzly-http-server-1] (Suspended (breakpoint at line 61 in Hk2RequestScope))   
  Hk2RequestScope.createContext() line: 61  
  ServerRuntime.process(ContainerRequest) line: 249 
  ApplicationHandler.handle(ContainerRequest) line: 703 
  WebComponent.serviceImpl(URI, URI, HttpServletRequest, HttpServletResponse) line: 416 
  WebComponent.service(URI, URI, HttpServletRequest, HttpServletResponse) line: 370 
  ServletContainer.service(URI, URI, HttpServletRequest, HttpServletResponse) line: 389 
  ServletContainer.service(HttpServletRequest, HttpServletResponse) line: 342   
  ServletContainer.service(ServletRequest, ServletResponse) line: 229   
  FilterChainImpl.doFilter(ServletRequest, ServletResponse) line: 147   
  FilterChainImpl.invokeFilterChain(ServletRequest, ServletResponse) line: 106  
  ServletHandler.doServletService(Request, Response) line: 226  
  ServletHandler.service(Request, Response) line: 173   
  HttpHandler$1.run() line: 224 
  FixedThreadPool$BasicWorker(AbstractThreadPool$Worker).doWork() line: 593 
  FixedThreadPool$BasicWorker(AbstractThreadPool$Worker).run() line: 573    
  Thread.run() line: 748    

在这种特殊情况下,我是通过对Grizzly配置用于servlet部署的单元测试进行调用的。当不使用servlet部署时,以及实际运行应用程序(Tomcat)时,也会发生此问题。

如何解决此问题?

1 个答案:

答案 0 :(得分:1)

问题仅适用于较新版本的Jersey。以下MCVE不适用于Jersey 2.27或2.26,但在2.25上通过:

build.gradle

apply plugin: 'java'
apply plugin: 'eclipse-wtp'

repositories {
   mavenCentral()
}

sourceSets {
  src {
    java {
      srcDirs = ["src/main/java"];
    }
  }
  test {
    java {
      srcDirs = ["test/main/java"];
    }
  }
}

def jerseyVersion = '2.25'

dependencies {
  compile "org.glassfish.jersey.containers:jersey-container-servlet:${jerseyVersion}"
  compile "org.glassfish.jersey.inject:jersey-hk2:${jerseyVersion}"
  testCompile "org.junit.jupiter:junit-jupiter-api:5.2.0"
  testCompile "org.junit.jupiter:junit-jupiter-engine:5.2.0"
  testCompile "org.junit.platform:junit-platform-launcher:1.2.0"
  testCompile "org.glassfish.jersey.test-framework:jersey-test-framework-core:${jerseyVersion}"
  testCompile "org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-grizzly2:${jerseyVersion}"
}

version = '1.0'

jar {
    manifest.attributes provider: 'gradle'
}

Test.java

package test;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.IOException;

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class MyJerseyTest extends JerseyTest
{
  public static class Policy
  {
    public int getA()
    {
      return 1;
    }
  }

  static class PolicyFactory implements Factory<Policy>
  {
    @Override
    public Policy provide()
    {
      return new Policy();
    }

    @Override
    public void dispose(Policy instance)
    {
    }
  }

  public static class MyRequestFilter implements ContainerRequestFilter
  {
    @Inject
    private javax.inject.Provider<Policy> policyProvider;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException
    {
      Policy policy = policyProvider.get();

      if(policy.getA() != 1)
      {
        throw new WebApplicationException(Status.FORBIDDEN);
      }
    }
  }

  public static class MyDynamicFeature implements DynamicFeature
  {
    @Override
    public void configure(ResourceInfo ri, FeatureContext ctx)
    {
      ctx.register(MyRequestFilter.class);
    }
  }

  @Path("/test")
  public static class MyEndpoint
  {
    @Context
    Policy policy;

    public MyEndpoint()
    {
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response doTest()
    {
      return Response.ok().build();
    }
  }

  public static class MyResourceConfig extends ResourceConfig
  {
    public static class MyBinder extends AbstractBinder
    {
      @Override
      protected void configure()
      {
        bindFactory(PolicyFactory.class)
          .to(Policy.class)
          .in(RequestScoped.class);
      }
    }

    public MyResourceConfig()
    {
      register(new MyBinder());
      register(MyDynamicFeature.class);
      register(MyEndpoint.class);
    }
  }

  @BeforeEach
  public void beforeEach() throws Exception
  {
    // Workaround for JUnit 5
    setUp();
  }

  @AfterEach
  public void afterEach() throws Exception
  {
    // Workaround for JUnit 5
    tearDown();
  }

  @Override
  public ResourceConfig configure()
  {
    return new MyResourceConfig();
  }

  @Test
  public void testMyEndpoint()
  {
    Response response = target("test").request().get();
    assertEquals(Status.OK.getStatusCode(), response.getStatus());
  }
}