Post Jersey upgrade from 2.37 to 3.1.9 getting java.lang.NoSuchMethodException: Could not find a suitable constructor
Hi Team,
Mine is a Tomcat based application which is working fine with Tomcat 9.x, Servlet 4.x and Jersey 2.37
with below web.xml:
My AppServlet looks like below:
public class AppServlet extends ResourceConfig {
......
// Application startup
@Inject
public AppServlet(ServiceLocator serviceLocator) throws Exception {
logger.info("Application initialization started!!!");
.....
// Enable this to instantiate bound classes, with Immediate as the scope, during binding phase
// rather than when accessed for the first time
// ServiceLocator serviceLocator = ServiceLocatorUtilities.createAndPopulateServiceLocator();
ServiceLocatorUtilities.enableImmediateScope(serviceLocator);
register(new AbstractBinder() {
protected void configure() {
.......
bind(actorSystem).to(ActorSystem.class);
bind(I18NMessages.class).to(I18NMessages.class).in(Immediate.class);
bind(GraphDataManager.class).to(GraphDataManager.class).in(Immediate.class);
bind(CacheManager.class).to(CacheManager.class).in(Singleton.class);
.....
}
});
.....
}
@PreDestroy
private void shutdown() {
......
}
}
After I upgrade to Tomcat 10.1, Servlet 6.0.0 and Jersey to 3.1.9, I am getting below exception and application is not starting:
Java.lang.NoSuchMethodException: Could not find a suitable constructor......
at org.glassfish.jersey.inject.hk2.JerseyClassAnalyzer.getConstructor(JerseyClassAnalyzer.java:168)
at org.jvnet.hk2.internal.Utilities.getConstructor(Utilities.java:157)
at org.jvnet.hk2.internal.Utilities.justCreate(Utilities.java:1043)
at org.jvnet.hk2.internal.ServiceLocatorImpl.create(ServiceLocatorImpl.java:984)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:1088)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:1080)
at org.glassfish.jersey.inject.hk2.AbstractHk2InjectionManager.createAndInitialize(AbstractHk2InjectionManager.java:199)
at org.glassfish.jersey.inject.hk2.ImmediateHk2InjectionManager.createAndInitialize(ImmediateHk2InjectionManager.java:30)
at org.glassfish.jersey.server.ApplicationConfigurator.createApplication(ApplicationConfigurator.java:114)
at org.glassfish.jersey.server.ApplicationConfigurator.init(ApplicationConfigurator.java:72)
at org.glassfish.jersey.server.ApplicationHandler.lambda$initialize$0(ApplicationHandler.java:306)
at java.base/java.util.Arrays$ArrayList.forEach(Arrays.java:4204)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:306)
at org.glassfish.jersey.server.ApplicationHandler.
Due to this I am not able to upgrade to latest versions.
Appreciate any help on this.
Thanks Ashok.
Double-check the imports, for example, if you use jakarta.inject.Singleton.class vs javax.inject.Singleton.class. Otherwise, provide more info about the issue. The current report is not complete - no imports are visible, stack-trace is not complete. Dependencies are not included. It's not solvable in this state.
Thank you @senivam for the quick response, here are my imports
import java.sql.SQLException;
import jakarta.annotation.PreDestroy; import jakarta.ws.rs.ApplicationPath;
import javax.inject.Inject; import javax.inject.Singleton;
import org.glassfish.hk2.api.Immediate; import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.hk2.utilities.ServiceLocatorUtilities; import org.glassfish.jersey.internal.inject.AbstractBinder; import org.glassfish.jersey.media.multipart.MultiPartFeature; import org.glassfish.jersey.server.ResourceConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.jakarta.rs.json.JacksonJsonProvider; import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory;
import org.apache.pekko.actor.ActorSystem; import net.sf.ehcache.CacheManager;
public class AppServlet extends ResourceConfig {
private Config config;
private DBConnectionPoolManager dbConnectionPoolManager;
// Application startup
@Inject
public AppServlet(ServiceLocator serviceLocator) throws Exception {
logger.info("Application initialization started!!!");
.....
// Enable this to instantiate bound classes, with Immediate as the scope, during binding phase
// rather than when accessed for the first time
// ServiceLocator serviceLocator = ServiceLocatorUtilities.createAndPopulateServiceLocator(); ServiceLocatorUtilities.enableImmediateScope(serviceLocator);
register(new AbstractBinder() {
protected void configure() {
.......
bind(actorSystem).to(ActorSystem.class);
bind(I18NMessages.class).to(I18NMessages.class).in(Immediate.class);
bind(GraphDataManager.class).to(GraphDataManager.class).in(Immediate.class);
bind(CacheManager.class).to(CacheManager.class).in(Singleton.class);
.....
}
});
..... }
@PreDestroy private void shutdown() { ...... }
Here is the complete error stack:
SEVERE: Servlet.init() for servlet [.....] threw exception
MultiException stack 1 of 1
java.lang.NoSuchMethodException: Could not find a suitable constructor in ...... class.
at org.glassfish.jersey.inject.hk2.JerseyClassAnalyzer.getConstructor(JerseyClassAnalyzer.java:168)
at org.jvnet.hk2.internal.Utilities.getConstructor(Utilities.java:157)
at org.jvnet.hk2.internal.Utilities.justCreate(Utilities.java:1043)
at org.jvnet.hk2.internal.ServiceLocatorImpl.create(ServiceLocatorImpl.java:984)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:1088)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:1080)
at org.glassfish.jersey.inject.hk2.AbstractHk2InjectionManager.createAndInitialize(AbstractHk2InjectionManager.java:199)
at org.glassfish.jersey.inject.hk2.ImmediateHk2InjectionManager.createAndInitialize(ImmediateHk2InjectionManager.java:30)
at org.glassfish.jersey.server.ApplicationConfigurator.createApplication(ApplicationConfigurator.java:114)
at org.glassfish.jersey.server.ApplicationConfigurator.init(ApplicationConfigurator.java:72)
at org.glassfish.jersey.server.ApplicationHandler.lambda$initialize$0(ApplicationHandler.java:306)
at java.base/java.util.Arrays$ArrayList.forEach(Arrays.java:4204)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:306)
at org.glassfish.jersey.server.ApplicationHandler.
Apr 10, 2025 10:40:35 PM org.apache.catalina.core.StandardContext loadOnStartup
SEVERE: Servlet [....] in web application [/....] threw load() exception
java.lang.NoSuchMethodException: Could not find a suitable constructor in ..... class.
at org.glassfish.jersey.inject.hk2.JerseyClassAnalyzer.getConstructor(JerseyClassAnalyzer.java:168)
at org.jvnet.hk2.internal.Utilities.getConstructor(Utilities.java:157)
at org.jvnet.hk2.internal.Utilities.justCreate(Utilities.java:1043)
at org.jvnet.hk2.internal.ServiceLocatorImpl.create(ServiceLocatorImpl.java:984)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:1088)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:1080)
at org.glassfish.jersey.inject.hk2.AbstractHk2InjectionManager.createAndInitialize(AbstractHk2InjectionManager.java:199)
at org.glassfish.jersey.inject.hk2.ImmediateHk2InjectionManager.createAndInitialize(ImmediateHk2InjectionManager.java:30)
at org.glassfish.jersey.server.ApplicationConfigurator.createApplication(ApplicationConfigurator.java:114)
at org.glassfish.jersey.server.ApplicationConfigurator.init(ApplicationConfigurator.java:72)
at org.glassfish.jersey.server.ApplicationHandler.lambda$initialize$0(ApplicationHandler.java:306)
at java.base/java.util.Arrays$ArrayList.forEach(Arrays.java:4204)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:306)
at org.glassfish.jersey.server.ApplicationHandler.
Apr 10, 2025 10:40:35 PM org.apache.coyote.AbstractProtocol start INFO: Starting ProtocolHandler ["http-nio-8080"] Apr 10, 2025 10:40:35 PM org.apache.catalina.startup.Catalina start INFO: Server startup in [10869] milliseconds
Thanks for the additional information. Seen the imports:
import javax.inject.Inject;
import javax.inject.Singleton;
should be replaced to
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
and check if the related dependency for the Inject is migrated as well:
<-- This is new one for Jakarta 10 -->
<dependency>
<groupId>jakarta.inject</groupId>
<artifactId>jakarta.inject-api</artifactId>
<version>2.0.1</version>
</dependency>
Thank you @senivam , After making the above changes Application is started, but looks like initialization didn't happen properly, I am getting below exception when I am triggering any of my REST API.
An exception mapping did not successfully produce and processed a response. Logging the exception propagated to the default exception mapper. java.lang.NullPointerException: Cannot invoke "....getI18NMessage(java.util.Locale)" because "this.i18nMessages" is null at ........AuthInterceptor.filter(AuthInterceptor.java:60) at org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:108) at org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:44) at org.glassfish.jersey.process.internal.Stages.process(Stages.java:173) at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:266) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248) at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244) 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.process(Errors.java:244) at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:266) at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:253) at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:696) at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:397) at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:349) at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:358) at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:312) at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:670) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:397) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:905) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) at java.base/java.lang.Thread.run(Thread.java:840)
I am guessing the below classes are not initialized properly in the AppServlet
register(new AbstractBinder() { protected void configure() { ....... bind(actorSystem).to(ActorSystem.class); bind(I18NMessages.class).to(I18NMessages.class).in(Immediate.class); bind(GraphDataManager.class).to(GraphDataManager.class).in(Immediate.class); bind(CacheManager.class).to(CacheManager.class).in(Singleton.class); ..... } });
and I18NMessages class looks like below:
@Singleton public class I18NMessages {
@Inject private I18NMessages(Config config) { .... }
}
@senivam any help on the above?
Thanks Ashok.
you can try marking the class directy by annotation:
@Immediate
@jakarta.inject.Singleton
public class I18NMessages {
// class implementation
}
and then register it as a singleton within the binder:
bind(I18NMessages.class).to(I18NMessages.class).in(jakarta.inject.Singleton.class);
But, as I see, your code is quite complex, so consider focusing on the migration with help of the migration guide for the Jersey-related part.
in(Immediate.class) probably does nothing, as Immediate is no Scope recognised by Jersey.
@senivam I have javax.inject references in other places as well, after replacing them with jakarta.inject issue resolved.