eclipse-ee4j / jersey

Eclipse Jersey Project - Read our Wiki:
https://github.com/eclipse-ee4j/jersey/wiki
Other
692 stars 355 forks source link

java.lang.IllegalStateException: The resource configuration is not modifiable in this context. #4617

Open namedgraph opened 4 years ago

namedgraph commented 4 years ago

This is probably one of the most annoying issues I've encountered upgrading Jersey 1.x to 2.x:

java.lang.IllegalStateException: The resource configuration is not modifiable in this context.
    org.glassfish.jersey.server.ResourceConfig$ImmutableState.register(ResourceConfig.java:248)
    org.glassfish.jersey.server.ResourceConfig$ImmutableState.register(ResourceConfig.java:195)
    org.glassfish.jersey.server.ResourceConfig.register(ResourceConfig.java:428)
    org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:306)
    org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154)
    org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:347)
    javax.servlet.GenericServlet.init(GenericServlet.java:158)

In my case it comes from the factory register() related code:

        register(new AbstractBinder()
        {
            @Override
            protected void configure()
            {
                bindFactory(XsltExecutableFactory.class).to(XsltExecutable.class).
                proxy(true).proxyForSameScope(false).
                in(RequestScoped.class);
            }
        });

This causes the error with absolutely no explanation or seemingly even relation to the cause.

It's been plaguing users for years, and every report seems to have a different cause: https://stackoverflow.com/questions/20670310/why-would-java-lang-illegalstateexception-the-resource-configuration-is-not-mo

jansupol commented 4 years ago

Please provide a runnable reproducer

senivam commented 3 years ago

if you run this on Tomcat that might be caused by any previously missing dependency (activation, jaxb etc). You shall either bundle all required dependencies inside your WAR or put them into the lib folder of Tomcat's shared libraries.

namedgraph commented 3 years ago

@senivam in my case this has nothing to do with dependencies but with registering providers and some combinations of their proxies/scopes/injections. Very likely HK2 related.

senivam commented 3 years ago

@namedgraph actually it can be related to dependencies (I was just fixing that in Tomcat environment when I was writing my previous answer). When you deploy Jersey dependent app inside Tomcat and do not provide activation (and jaxb if needed) besides, it fails to load just with this very exception you are providing in the issue description.

But this was only presumption, in other cases the exception might be caused by other reasons.

So, if you believe this has nothing to to with dependencies, just provide a reproducer which we could run and check what really happens there.

And which AS do you use to deploy your app?

namedgraph commented 3 years ago

I'm not disputing that it can be related to dependencies :) Looking at SO, people seem to identify a variety of causes.

I will create a reproducer as soon as I can pin down the cause, which I haven't yet.

I am using Tomcat 9.x.

namedgraph commented 3 years ago

Here's the full error message:

Exception

javax.servlet.ServletException: Servlet.init() for servlet [com.atomgraph.linkeddatahub.Application] threw exception
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
    org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
    org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.base/java.lang.Thread.run(Thread.java:834)

Root Cause

java.lang.IllegalStateException: The resource configuration is not modifiable in this context.
    org.glassfish.jersey.server.ResourceConfig$ImmutableState.register(ResourceConfig.java:248)
    org.glassfish.jersey.server.ResourceConfig$ImmutableState.register(ResourceConfig.java:195)
    org.glassfish.jersey.server.ResourceConfig.register(ResourceConfig.java:428)
    org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:306)
    org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154)
    org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:347)
    javax.servlet.GenericServlet.init(GenericServlet.java:158)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
    org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
    org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.base/java.lang.Thread.run(Thread.java:834)
jansupol commented 3 years ago

Where do you call the register method?

namedgraph commented 3 years ago
public class Application extends ResourceConfig
{
    ...

    @PostConstruct
    public void init()
    {
        ...

        register(new AbstractBinder()
        {
            @Override
            protected void configure()
            {
                bindFactory(XsltExecutableSupplierFactory.class).to(XsltExecutableSupplier.class).
                proxy(true).proxyForSameScope(false).
                in(RequestScoped.class);
            }
        });

        ...
    }

    ...
}
dsvensson commented 2 years ago

I started getting this when upgrading from 2.34 to 2.35.

dsvensson commented 2 years ago

@namedgraph Did you find any workaround for this issue?

namedgraph commented 2 years ago

@dsvensson not really... This seems to happen when providers fail to register in the application. It went away for a while and now happening again after some non-Jersey dependency upgrade. And seems only to happen on GitHub's server and not my local WSL 2. Really weird.

I'll keep you posted.

obstreperous-oobleck commented 2 years ago

FWIW, I had this issue when I had both Jersey 2.33 and 2.34 components rattling around in the same Spring Boot application. (spring-boot-starter-jersey 2.5 was pulling in Jersey 2.33, but I had set our application's Jersey version to 2.34).

The result was that all our integration tests that made API calls to our Spring Boot application were failing. The first failed call had the following error message, which sure sounds like it's caused by an API difference between Jersey 2.33 and 2.34:

java.lang.NoSuchMethodError: 'void org.glassfish.jersey.server.ServerExecutorProvidersConfigurator.registerExecutors(org.glassfish.jersey.internal.inject.InjectionManager, org.glassfish.jersey.model.internal.ComponentBag, org.glassfish.jersey.spi.ExecutorServiceProvider, org.glassfish.jersey.spi.ScheduledExecutorServiceProvider)'
        at org.glassfish.jersey.server.ServerExecutorProvidersConfigurator.init(ServerExecutorProvidersConfigurator.java:62)
        at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:345)
        at org.glassfish.jersey.server.ApplicationHandler.lambda$initialize$1(ApplicationHandler.java:293)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
        at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:232)
        at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:292)
        at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:259)
        at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:311)
        at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154)
        at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:347)
        at javax.servlet.GenericServlet.init(GenericServlet.java:180)
        at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:117)
        at io.undertow.servlet.core.ManagedServlet$DefaultInstanceStrategy.start(ManagedServlet.java:309)
        at io.undertow.servlet.core.ManagedServlet.forceInit(ManagedServlet.java:212)
        at io.undertow.servlet.handlers.ServletChain.forceInit(ServletChain.java:130)
        at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:63)
        at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
        at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
        at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117)
        at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
        at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
        at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
        at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
        at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:280)
        at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:79)
        at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:134)
        at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:131)
        at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
        at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
        at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:260)
        at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:79)
        at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:100)
        at io.undertow.server.Connectors.executeRootHandler(Connectors.java:387)
        at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:852)
        at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1423)
        at org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1280)
        at java.base/java.lang.Thread.run(Thread.java:834)

And then, presumably because that first initialization failed, all subsequent API calls died with the "resource config not modifiable" message:

java.lang.IllegalStateException: The resource configuration is not modifiable in this context.
        at org.glassfish.jersey.server.ResourceConfig$ImmutableState.register(ResourceConfig.java:248)
        at org.glassfish.jersey.server.ResourceConfig$ImmutableState.register(ResourceConfig.java:195)
        at org.glassfish.jersey.server.ResourceConfig.register(ResourceConfig.java:428)
        at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:306)
        at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154)
        at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:347)
        at javax.servlet.GenericServlet.init(GenericServlet.java:180)
        at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:117)
        at io.undertow.servlet.core.ManagedServlet$DefaultInstanceStrategy.start(ManagedServlet.java:309)
        at io.undertow.servlet.core.ManagedServlet.forceInit(ManagedServlet.java:212)
        at io.undertow.servlet.handlers.ServletChain.forceInit(ServletChain.java:130)
        at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:63)
        at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
        at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
        at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117)
        at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
        at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
        at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
        at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
        at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52)
        at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
        at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:280)
        at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:79)
        at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:134)
        at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:131)
        at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
        at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
        at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:260)
        at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:79)
        at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:100)
        at io.undertow.server.Connectors.executeRootHandler(Connectors.java:387)
        at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:852)
        at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1449)
        at org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1280)
        at java.base/java.lang.Thread.run(Thread.java:834)
chylek-qr commented 2 months ago

This is happening randomly when stopping and then trying to re-start a Jetty server with JettyWebSocketContainerInitializer servlet. There is no Tomcat or other third-party library for managing the server.

IllegalStateException
The resource configuration is not modifiable in this context.

org.glassfish.jersey.server.ResourceConfig$ImmutableState in register at line 252
org.glassfish.jersey.server.ResourceConfig$ImmutableState in register at line 199
org.glassfish.jersey.server.ResourceConfig in register at line 432
org.glassfish.jersey.servlet.WebComponent in <init> at line 306
org.glassfish.jersey.servlet.ServletContainer in init at line 154
org.glassfish.jersey.servlet.ServletContainer in init at line 338
jakarta.servlet.GenericServlet in init at line 178
org.eclipse.jetty.servlet.ServletHolder in initServlet at line 633
org.eclipse.jetty.servlet.ServletHolder in initialize at line 415
org.eclipse.jetty.servlet.ServletHandler in lambda$initialize$2 at line 725
java.util.stream.SortedOps$SizedRefSortingSink in end at line 357
java.util.stream.AbstractPipeline in copyInto at line 510
java.util.stream.AbstractPipeline in wrapAndCopyInto at line 499
java.util.stream.StreamSpliterators$WrappingSpliterator in forEachRemaining at line 310
java.util.stream.Streams$ConcatSpliterator in forEachRemaining at line 735
java.util.stream.ReferencePipeline$Head in forEach at line 762
org.eclipse.jetty.servlet.ServletHandler in initialize at line 749
org.eclipse.jetty.servlet.ServletContextHandler in startContext at line 392
org.eclipse.jetty.server.handler.ContextHandler in doStart at line 902
org.eclipse.jetty.servlet.ServletContextHandler in doStart at line 306
org.eclipse.jetty.util.component.AbstractLifeCycle in start at line 93
org.eclipse.jetty.util.component.ContainerLifeCycle in start at line 171
org.eclipse.jetty.server.Server in start at line 470
org.eclipse.jetty.util.component.ContainerLifeCycle in doStart at line 114
org.eclipse.jetty.server.handler.AbstractHandler in doStart at line 89
org.eclipse.jetty.server.Server in doStart at line 415
org.eclipse.jetty.util.component.AbstractLifeCycle in start at line 93

Admittedly it's an older version (Jetty 11 and Jersey 3.1.3), but I saw something about dropping support for Jetty 11 in 3.1.4 so I don't know if it's safe to update.

niclash commented 2 months ago

I have no previous experience with Jersey, and got this issue "straight away" when trying to register factories. Running on Tomcat 10.1.25 inside IntelliJ IDEA. Also, I am extending ResourceConfig rather than Application as I need to provide custom resource instantiation.

I have committed a relatively small codebase https://github.com/niclash/qi4jwebdemo

DemoApplication (1) is the ResourceConfig and it instantiates a Qi4jApplication (2) which extends AbstractBinder and sets up the factories. That's all good, and the http request doesn't seem to touch any of my code.

I have also noticed that ResourceConfig.lock() is called and sets the State state to an immutable instance. This happens twice and before the AbstractBinder.configure() method is called (which intuitively feels wrong).

Update: Moving the factory registrations from configure() to the constructor does place the factory registrations ahead of the lock(), but the outcome is still the same.

(1) https://github.com/niclash/qi4jwebdemo/blob/master/app/src/main/java/org/hedhman/qi4jwebdemo/app/DemoApplication.java

(2) https://github.com/niclash/qi4jwebdemo/blob/master/webx/src/main/java/org/qi4j/library/webx/Qi4jApplication.java

chylek-qr commented 2 months ago

After further investigation, the exception started happening after adding

handler.addServlet(new ServletHolder(new ServletContainer(servlet))

where handler is a ServletContextHandler and servlet is a ResourceConfig. With this line, restarting the Jetty server causes "The resource configuration is not modifiable in this context." every time.

jansupol commented 2 months ago

Jetty 11 support has been in Jersey 3.0.x, and Jetty 12 support is in Jersey 3.1.x. That being said it does not mean Jersey 3.1 won't work in Jetty 11. It means that Jersey has an option to use Jetty as an HTTP Client and also embedded Jetty as a server where Jersey starts. This by no means prevents Jersey to be used in Jetty Servlet Container.

Now to demo. What is it supposed to be done to reproduce the issue with the demo @niclash ?

niclash commented 2 months ago

Now to demo. What is it supposed to be done to reproduce the issue with the demo @niclash ?

If you have IntelliJ IDEA, then you should now have "run configuration" for Tomcat. Either way, mount the war as '/demo' context and go to http://localhost:8080/demo/api and you get the exception in the web browser.