I followed a basic HelloWorld tutorial to get an example REST web service going under Tomcat using Jersey. Everything runs absolutely fine, and I get the output I expect.
However, my Tomcat host insists that we test our apps locally using the -security mode. When I do this, the app no longer works. I had to battle with a few permission related issues first, but they seem to be resolved now, and this is the final error. It takes me to an Error 500 page, and this is the top of the stacktrace:
22-Mar-2020 17:33:42.842 INFO [http-nio-8080-exec-1] com.sun.jersey.api.core.PackagesResourceConfig.init Scanning for root resource and provider classes in the packages:
rc.framedata
22-Mar-2020 17:33:42.845 INFO [http-nio-8080-exec-1] com.sun.jersey.api.core.ScanningResourceConfig.logClasses Root resource classes found:
class rc.framedata.HelloService
22-Mar-2020 17:33:42.845 INFO [http-nio-8080-exec-1] com.sun.jersey.api.core.ScanningResourceConfig.init No provider classes found.
22-Mar-2020 17:33:42.848 INFO [http-nio-8080-exec-1] com.sun.jersey.server.impl.application.WebApplicationImpl._initiate Initiating Jersey application, version 'Jersey: 1.19 02/11/2015 03:25 AM'
22-Mar-2020 17:33:43.094 SEVERE [http-nio-8080-exec-1] com.sun.jersey.spi.container.ContainerResponse.write A message body writer for Java class java.lang.String, and Java type class java.lang.String, and MIME media type application/json was not found.
The registered message body writers compatible with the MIME media type are:
*/* ->
com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider
com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter
com.sun.jersey.server.impl.template.ViewableMessageBodyWriter
22-Mar-2020 17:33:43.095 SEVERE [http-nio-8080-exec-1] com.sun.jersey.spi.container.ContainerResponse.logException Mapped exception to response: 500 (Internal Server Error)
javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: A message body writer for Java class java.lang.String, and Java type class java.lang.String, and MIME media type application/json was not found.
at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:284)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1510)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1419)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1409)
at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:409)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:558)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:733)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
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.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:282)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:279)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAsPrivileged(Subject.java:549)
at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:314) at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:170)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:225)
at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:47)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:149)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:145)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
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.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:282)
at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:279)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAsPrivileged(Subject.java:549)
at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:314) at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:253)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:191)
at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:47)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:149)
at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:145)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:543)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:688)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:609)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:818)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1623)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.sun.jersey.api.MessageException: A message body writer for Java class java.lang.String, and Java type class java.lang.String, and MIME media type application/json was not found.
... 58 more
It runs fine without -security so I'm fairly sure my pom.xml dependencies etc must be set up correctly, but they look like this:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>servlet-api</artifactId>
<version>6.0.53</version>
</dependency>
</dependencies>
My web.xml looks like this:
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>rc.framedata</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
And finally, my HelloService.java class looks like this:
package rc.framedata;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("/hello")
public class HelloService {
#GET
#Path("{clientName}")
#Produces(MediaType.TEXT_PLAIN)
public Response greetClient(#PathParam("clientName") String name){
String output = "Hi " + name;
return Response.status(200).entity(output).build();
}
}
I'm at a loss as to how to debug this or figure out what could be wrong. If I Google the error, I only find people who can't get their project working full-stop, but I can.... it just doesn't work with -security mode.
I'm a complete novice with Tomcat and Jersey so any help is greatly appreciated in advance.
(using Java 1.8.0_231 and Tomcat 8.5.51 on Windows 10)
Related
I have an Tomcat 9.0.20 server running on my computer with JDK 12 and Jersey 2 as REST API helper. This works fine.
But when I deploy the files to my Ubuntu server, which is running the same tomcat and Java Version, I get an error 500:
javax.servlet.ServletException: Servlet.init() for servlet [jersey-serlvet] threw exception
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1839)
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:835)
Root Cause
java.lang.NoSuchMethodError: javax.ws.rs.core.Application.getProperties()Ljava/util/Map;
org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:306)
org.glassfish.jersey.server.ApplicationHandler.lambda$initialize$1(ApplicationHandler.java:292)
org.glassfish.jersey.internal.Errors.process(Errors.java:292)
org.glassfish.jersey.internal.Errors.process(Errors.java:274)
org.glassfish.jersey.internal.Errors.processWithException(Errors.java:232)
org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:291)
org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:258)
org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:311)
org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154)
org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:346)
javax.servlet.GenericServlet.init(GenericServlet.java:158)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1839)
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$WrappingR
I used these libraries:
I used Jhades to detect overlapping libraries but this didn't help me.
>> jHades - scanning classpath for overlapping jars:
WARNING: this classloader is not supported: jdk.internal.loader.ClassLoaders$AppClassLoader
WARNING: this classloader is not supported: jdk.internal.loader.ClassLoaders$PlatformClassLoader
My web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>de.kai.iae</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
My Hello.Java:
package de.kai.iae;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/hello")
public class Hello {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String sayHello() {
return "Hello Jersey";
}
}
There are several issues:
You must not put application jars inside tomcat's ./lib folder. Instead you should add those jars as dependencies for each application inside <WAR>/WEB-INF/lib In that way your applications will be independent and will be able to use different versions of those libraries.
Make sure you do not package several versions of the same dependency, which will most probably cause various class-loading issues such as ClassNotFoundException, NoClasDefFoundError and NoSuchMethodError
For instance you have jakarta.ws.rs-api wich is Jax-Rs version 2, but you also have jsr311-api which is Jax-Rs version 1.
So in your case, some jersey code tries to call getProperties() which was introduced in JaxRs-2, but the JVM has loaded the Application class from jsr311-api which is JaxRs-1 where that method does not exist.So removing the jsr311-api jar should fix the problem.
I build a Java REST application that I want to deploy on a Jetty server.
I try to work with last versions of libraries (Java 8, Servlet 3.1, Jetty 9.4.7 and Resteasy 3.1.4).
I already make my server work with Jersey 2.26 but it has a limitation I hear that Resteasy does not have:
With Jersey I can't deploy if I define an interface with #Path annotation defined on the class because when I implement the interface the deployment failed due to a conflict about this non-unique resource. In other word to make it work I need to move the following commented annotation into the implementation :
//#Path("li")
public interface ILaptopInfo {
#Path("test/{test}")
#GET
public String test(#PathParam("test") String who);
}
I use Maven so I removed Jersey's dependencies and add Resteasy one's as documentation says:
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-servlet-initializer</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxb-provider</artifactId>
</dependency>
I does not change my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
metadata-complete="false"
version="3.1">
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
But when I start my server I got a resteasy WARN and then a No class in holder javax.ws.rs.core.Application stacktrace. It makes me think it does not scan properly my project to find my resource or Resteasy stack does not properly start the scanning. Do you have an idea about that I could miss?
Below the stacktrace I got:
2017-10-26 14:12:33.519:INFO:oejs.Server:main: jetty-9.4.7.v20170914
2017-10-26 14:12:34.416:INFO:oeja.AnnotationConfiguration:main: Scanning elapsed time=628ms
2017-10-26 14:12:34.432:WARN:oeja.WebServletAnnotation:main: org.jboss.resteasy.plugins.server.servlet.HttpServlet30Dispatcher defines neither #WebServlet.value nor #WebServlet.urlPatterns
2017-10-26 14:12:34.770:INFO:oejs.session:main: DefaultSessionIdManager workerName=node0
2017-10-26 14:12:34.770:INFO:oejs.session:main: No SessionScavenger set, using defaults
2017-10-26 14:12:34.770:INFO:oejs.session:main: Scavenging every 660000ms
2017-10-26 14:12:34.933:WARN:oejshC.ROOT:main: unavailable
javax.servlet.UnavailableException: No class in holder javax.ws.rs.core.Application#83f91b4==null,jsp=null,order=-1,inst=false
at org.eclipse.jetty.servlet.BaseHolder.doStart(BaseHolder.java:86)
at org.eclipse.jetty.servlet.ServletHolder.doStart(ServletHolder.java:362)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:759)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:348)
at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1514)
at org.eclipse.jetty.maven.plugin.JettyWebAppContext.startWebapp(JettyWebAppContext.java:359)
at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1476)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:785)
at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:261)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:545)
at org.eclipse.jetty.maven.plugin.JettyWebAppContext.doStart(JettyWebAppContext.java:434)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:113)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:167)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:113)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:131)
at org.eclipse.jetty.server.Server.start(Server.java:449)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:105)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:113)
at org.eclipse.jetty.server.Server.doStart(Server.java:416)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.maven.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:467)
at org.eclipse.jetty.maven.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:333)
at org.eclipse.jetty.maven.plugin.JettyRunMojo.execute(JettyRunMojo.java:180)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
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:497)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
2017-10-26 14:12:34.971:WARN:oejshC.ROOT:main: unavailable
I had your same issue. Try this:
<servlet>
<servlet-name>Application</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.example.Application</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
In new project I decided to use latest Jersey (2.16) with Tomcat 8, but integration scheme described in documentation causes Tomcat to throw NPE:
java.lang.NullPointerException
org.apache.catalina.loader.WebappClassLoader.binaryNameToPath(WebappClassLoader.java:2503)
org.apache.catalina.loader.WebappClassLoader.findLoadedClass0(WebappClassLoader.java:2708)
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1215)
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1173)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:534)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1081)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)
org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:277)
org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2381)
org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2370)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:744)
Here is my web.xml
<servlet>
<servlet-name>bla.bla.core.jersey.config.JerseyServerConfig</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>bla.bla.core.jersey.config.JerseyServerConfig</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Here is the listing of JerseyServerConfig:
package ru.huawei.rnd.bulksms.core.jersey.config;
import org.glassfish.jersey.server.ResourceConfig;
import ru.huawei.rnd.bulksms.core.jersey.constants.FILTERS_AND_INTERCEPTORS;
import ru.huawei.rnd.bulksms.core.jersey.constants.JERSEY_FEATURES;
public class JerseyServerConfig extends ResourceConfig {
public JerseyServerConfig() {
register(JERSEY_FEATURES.FORM_PROVIDER);
register(JERSEY_FEATURES.MULTIPART);
register(FILTERS_AND_INTERCEPTORS.USER_GZIP_FILTER);
register(FILTERS_AND_INTERCEPTORS.GZIP_ENCODER);
packages("bla.bla.rest");
}
}
So, it looks correct according to scheme described here in "4.7.2.2. Deployment using web.xml descriptor". But when I try to call any JAX-RS resource, bang, Tomcat throws NPE. And it seems it's because of missing servlet-class element in web.xml.
It appears you are using the jersey-container-servlet-core dependency. This will work in situations when we declare the servlet container. But when we want to take advantage of the features where Jersey is automatically loaded, we need the jersey-container-servlet
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
This artifact has the JerseyServletContainerInitializer, which implements SerlvetContainerInitializer (for Servlet 3.x deployments).
Tested and got same results as you when using the former artifact, and works fine using the latter.
I found this same question in here few times, but I couldn't find an answer to that.
When I run my application, Im getting the following error
javax.ws.rs.NotFoundException: Could not find resource for full path: http://localhost:8080/RemoteQuartzScheduler/rest/TestClass/hello
at org.jboss.resteasy.core.registry.ClassNode.match(ClassNode.java:73)
at org.jboss.resteasy.core.registry.RootClassNode.match(RootClassNode.java:48)
at org.jboss.resteasy.core.ResourceMethodRegistry.getResourceInvoker(ResourceMethodRegistry.java:444)
at org.jboss.resteasy.core.SynchronousDispatcher.getInvoker(SynchronousDispatcher.java:234)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:171)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:220)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Here is the pom file of the project (I only added the main parts)
<repositories>
<repository>
<id>JBoss repository</id>
<url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.9.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-servlet-initializer</artifactId>
<version>3.0.9.Final</version>
</dependency>
</dependencies>
And here is my web.xml file
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name>RemoteQuartzScheduler</display-name>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<!-- this should be the same URL pattern as the servlet-mapping property -->
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/rest</param-value>
</context-param>
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
</servlet-class>
</servlet>
Here is my Test.java class
#Path("/TestClass")
public class Test implements Serializable{
private static final long serialVersionUID = -262701666015379272L;
#GET
#Path("/hello")
public Response heloMessage() {
String result = "Hello Word!!!!!!!!!";
return Response.status(200).entity(result).build();
}
}
Please tell me where did I do wrong?? Thanks in advance
I haven't gotten a chance to test your version (with the web.xml), and honestly I don't work much with xml when I do use Resteasy, so I won't go trying to explain what is wrong (if anything) with the web.xml.
But when working with an javax.xs.rs.core.Application subclass, we can define an #ApplicationPath("/path") annotation. This defines a servlet for our JAX-RS application, with the url mapping of /path/*. This is specified in the JAX-RS spec.
You can see more here about this deployment option, as well as others, in section 2.3.2 Configuration - Servlet. This is a 1.1 spec (you are using 2.0), but the deployment options are similar. I just couldn't find an html link to the 2.0. You can download the pdf though from here.
You can also read more about deployments with Resteasy here in the documentation.
But basically, what this deployment option does is scan for annotations of #Path, #Provider, etc for the application. The reason is that JAX-RS will first look for classes and object in overridden getClasses() and getSingletons(), respectively. If then return empty sets, this tell JAX-RS to do scanning (per the spec).
When I'm trying run REST service I get method not found service. I'm using Jersey 2.11 and Jboss 7.1. Jersey 1.8 works fine.
pom.xml
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-common</artifactId>
<version>2.11</version>
</dependency>
web.xml
<servlet>
<servlet-name>Jersey</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>app.rest.RefreshDatabaseService</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
RefreshDatabaseService.java
#Path("refresh")
public class RefreshDatabaseService extends ResourceConfig {
private static Logger logger = Logger.getLogger(RefreshDatabaseService.class);
public RefreshDatabaseService() {
packages("com.jtendo.notification.app.rest.RefreshDatabaseService");
}
#GET
#Path("all")
public String refreshAllTable() {
Log
12:55:29,502 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/NotificationGW-app]] (MSC service thread 1-3)() Servlet /NotificationGW-app threw load() exception: java.lang.NoSuchMethodError: javax.ws.rs.core.Application.getProperties()Ljava/util/Map;
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:304) [jersey-server-2.11.jar:]
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:285) [jersey-server-2.11.jar:]
at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:310) [jersey-container-servlet-core-2.11.jar:]
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:170) [jersey-container-servlet-core-2.11.jar:]
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:358) [jersey-container-servlet-core-2.11.jar:]
at javax.servlet.GenericServlet.init(GenericServlet.java:242) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1202) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1102) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3655) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardContext.start(StandardContext.java:3873) [jbossweb-7.0.13.Final.jar:]
at org.jboss.as.web.deployment.WebDeploymentService.start(WebDeploymentService.java:90) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_65]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_65]
at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_65]
I'm runing http://localhost:8080/app/rest/refresh/all.
In lib folder in my war file I don't see any duplicated jar file in different version. All jersey jars are in version 2.11.
You possibly have two jar files with javax.ws.rs.core.Application class, one of them (which unfortunately was found by java) has no getPropetries method.
Try using JHades to find overlapping jars and remove the wrong one.
From: http://java.dzone.com/articles/jar-hell-and-back