我在检索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)时,也会发生此问题。
如何解决此问题?
答案 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());
}
}