I am running a Jersey 2.30.1 API and I want to upgrade the Swagger documentation to OpenAPI v3.
My new swagger dependencies in the pom.xml look like this:
<dependency>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
<version>3.17.0</version>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2-servlet-initializer</artifactId>
<version>2.0.2</version>
</dependency>
Previously (swagger 1.5 with swagger-ui 2.2.10-1), I had Swagger configured in my web.xml:
<servlet>
<servlet-name>Jersey2Config</servlet-name>
<servlet-class>io.swagger.jersey.config.JerseyJaxrsConfig</servlet-class>
<init-param>
<param-name>api.version</param-name>
<param-value>2.0</param-value>
</init-param>
<init-param>
<param-name>swagger.api.basepath</param-name>
<param-value>/api</param-value>
</init-param>
<load-on-startup>4</load-on-startup>
</servlet>
I would like to do the same now, but I can't find a documentation, if and how that would be possible.
How can I define the swagger base path and API version in my web.xml with OpenAPI v3?
After playing around with this, my solution is basically like so.
pom.xml:
<dependency>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
<version>3.52.1</version>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2</artifactId>
<version>2.1.10</version>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-jaxrs2-servlet-initializer</artifactId>
<version>2.1.10</version>
</dependency>
web.xml:
The Jersey2Config servlet is completely removed from web.xml.
The servlet configuration needs to be changed for the parameter io.swagger.v3.jaxrs2.integration.resources
<servlet>
<servlet-name>my servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>my.package.to.scan, io.swagger.v3.jaxrs2.integration.resources</param-value>
</init-param>
</servlet>
Additional to web.xml a new file openapi.yaml has to be created under src/main/webapp/WEB-INF. This is responsible for creating the openapi.yaml/ openapi.json file which will be consumed by the swagger ui.
openapi.yaml:
prettyPrint: true
cacheTTL: 0
readAllResources: false /** Only show methods in swagger-ui that are annotated */
openAPI:
info:
version: '1.0'
title: 'my application'
servers:
- url: '/my-application'
swagger ui:
...
window.onload = function() {
const window.ui = SwaggerUIBundle({
url: 'https://my-domain.com/my-application/openapi.json',
dom_id: '#swagger-ui-container',
docExpansion: 'none',
defaultModelsExpandDepth: -1,
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout",
apisSorter: "alpha",
tagsSorter: "alpha",
operationsSorter: "alpha",
validatorUrl: null
});
}
...
Related
I'm new to swagger and looking to get it set up on my latest REST API project but am failing miserably. Everything seems to be configured correctly but I am unable to navigate to swagger.json without getting a 404. I can't see what is missing or wrong
pom.xml
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey-jaxrs</artifactId>
<version>1.5.0</version>
<exclusions>
<exclusion>
<artifactId>jersey-server</artifactId>
<groupId>com.sun.jersey</groupId>
</exclusion>
<exclusion>
<artifactId>jersey-multipart</artifactId>
<groupId>com.sun.jersey.contribs</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-multipart</artifactId>
<version>1.11.1</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.11.1</version>
</dependency>
Exclusions as the project uses version 1.11.1 and causes conflicts if 1.13 is imported from swagger
web.xml
<servlet>
<servlet-name>Jersey REST Service</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>
io.swagger.jaxrs.json,
io.swagger.jaxrs.listing,
uk.package.test.myproject
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>Jersey2Config</servlet-name>
<servlet-class>io.swagger.jaxrs.config.DefaultJaxrsConfig</servlet-class>
<init-param>
<param-name>api.version</param-name>
<param-value>1.0.0</param-value>
</init-param>
<init-param>
<param-name>swagger.api.basepath</param-name>
<param-value>http://localhost:8082/myproject/api</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
Example annotations...
#ManagedBean
#Path("secure/cache")
#Restrict("ManageCache")
#Api(value = "secure/cache", description = "Rest api for do operations on admin", produces = MediaType.APPLICATION_JSON)
public class AdminApi {....
#GET
#Path("{name}")
#Produces(MediaType.APPLICATION_JSON)
#ApiOperation(value = "Get specific admin", httpMethod = "GET", notes = "Fetch the admin user details", response = Response.class)
#ApiResponses(value = { #ApiResponse(code = 200, message = "Given admin user found"),
#ApiResponse(code = 404, message = "Given admin user not found"),
#ApiResponse(code = 500, message = "Internal server error due to encoding the data"),
#ApiResponse(code = 400, message = "Bad request due to decoding the data"),
#ApiResponse(code = 412, message = "Pre condition failed due to required data not found") })
public List<String> getCacheKeys(.....
When the project is run the following is logged...
10:46:48,724 INFO [com.sun.jersey.api.core.PackagesResourceConfig] (MSC service thread 1-5) Scanning for root resource and provider classes in the packages:
io.swagger.jaxrs.json
io.swagger.jaxrs.listing
uk.package.test.myproject
10:46:48,771 INFO [com.sun.jersey.api.core.ScanningResourceConfig] (MSC service thread 1-5) Root resource classes found:
class uk.package.test.myproject.api.NotificationApi
class uk.package.test.myproject.api.UserApi
class uk.package.test.myproject.api.FlagsApi
class uk.package.test.myproject.api.UnitsByFunctionApi
class uk.package.test.myproject.api.CvDataApi
class uk.package.test.myproject.api.ImageApi
class uk.package.test.myproject.api.GazetteerApi
class uk.package.test.myproject.api.SearchApi
class uk.package.test.myproject.api.ViewApi
class uk.package.test.myproject.api.AdminApi
10:46:48,776 INFO [com.sun.jersey.api.core.ScanningResourceConfig] (MSC service thread 1-5) No provider classes found.
10:46:48,834 INFO [com.sun.jersey.server.impl.cdi.CDIComponentProviderFactoryInitializer] (MSC service thread 1-5) CDI support is enabled
10:46:48,842 INFO [com.sun.jersey.server.impl.application.WebApplicationImpl] (MSC service thread 1-5) Initiating Jersey application, version 'Jersey: 1.11.1 03/31/2012 06:49 PM'
Thank you in advance
Cheers
Martin
Just to let you know I have resolved this by using a custom Application rather than using package scanning :)
Thanks for your help
Martin
Your servlet mapping says that you should not be looking at the path you specified:
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
That typically means to look under the /api path. That means then, unless you're using a webapp called myproject, you should be looking under /api/swagger.json
I have found a few questions like this on SO already but none of them seemed to address my particular problem, and I have been unable to find a solution on my own.
Here is the error I'm getting:
Caused by: org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=multipart/form-data; boundary=----WebKitFormBoundaryHWk1XUaeu7pEiDth, type=class org.glassfish.jersey.media.multipart.FormDataMultiPart, genericType=class org.glassfish.jersey.media.multipart.FormDataMultiPart.
I am sending this through a jQuery AJAX request that looks like this:
$('#upload-image-form').on('submit', function(e) {
e.preventDefault();
var data = new FormData(this);
$.ajax({
url: url,
method: 'POST',
contentType: false,
processData: false,
data: data,
}).done(function(data) {
console.log(data);
}).fail(function(res, status) {
onError(res, status, 'Image upload failed');
});
});
And this is my Java endpoint:
#POST
#Path("/{userId}")
#Consumes("multipart/form-data")
public Response createGraphic(
#PathParam("userId") int userId,
FormDataMultiPart multiPartFormData) { ... }
I have seen a few people have luck with changing the parameter of the endpoint method to use #FormDataParam instead of FormDataMultiPart (as seen here), but I cannot edit the Java class, so I must use it how it is above.
My pom.xml has the following dependencies:
<dependency>
<groupId>org.jvnet</groupId>
<artifactId>mimepull</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.12</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>2.12</version>
</dependency>
web.xml
<servlet>
<servlet-name>Jersey</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>my.package</param-value>
</init-param>
<load-on-startup>5</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
The only other thing I was able to dig up was to register the MultiPartFeature using a ResourceConfig; however, the project I'm working with does not have any Application classes or any class that extends ResourceConfig (it's a WAR that's deployed to Tomcat, so no main class).
Is there any other configuration that needs to be done? I'm stumped as to why this is not working.
The MultiPartFeature has the required reader and writer. But you still need to register the feature. As you've mentioned, you will often see it's registration in an Application/ResourceConfig subclass. But in a web.xml, you can simply add it to the list of classes to add as provider. You can do that by adding an <init-param> to the servlet configuration, i.e.
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
org.glassfish.jersey.media.multipart.MultiPartFeature,
some.other.Provider
</param-value>
</init-param>
As you can see in the example, if you need to register any other providers/features, you comma-delimit the class names.
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
I am able to access REST services from the browser url: http://localhost:8080/assignment/services/services/test/test1
From My servlet, I use to call service method as shown below. Now I need to call through REST services but getting below error.
URL url = new URL("http://localhost:8080/assignment/services/services/"+userName+"/"+password);
System.out.println("URL-->"+url);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/xml");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while(bufferedReader.readLine() != null){
result = bufferedReader.readLine();
}
// result = userService.login(userName, password);
System.out.println(result);
here is the error:
INFO: Reloading Context with name [/assignment] is completed
URL-->http://localhost:8080/assignment/services/test/test1
Jul 30, 2013 12:52:02 PM org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor processRequest
WARNING: No root resource matching request path /assignment/services/test/test1 has been found, Relative Path: /test/test1. Please enable FINE/TRACE log level for more details.
Jul 30, 2013 12:52:02 PM org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper toResponse
WARNING: javax.ws.rs.NotFoundException
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:172)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:100)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:239)
at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:223)
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:203)
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:137)
at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:158)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java
...
Jul 30, 2013 12:52:02 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [LoginServlet] in context with path [/assignment] threw exception
java.io.FileNotFoundException: http://localhost:8080/assignment/services/services/test/test1
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1623)
at com.viasat.test.login.servlet.LoginServlet.process(LoginServlet.java:77)
at com.viasat.test.login.servlet.LoginServlet.doPost(LoginServlet.java:52)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
Service class:
#Service
#Path("/services/")
public class UserServiceImpl implements UserService {
#GET
#Path("{userName}/{password}")
#Produces(MediaType.TEXT_XML)
public String login(#PathParam("userName")String username, #PathParam("password")String password)
throws JAXBException, PropertyException, FileNotFoundException {
web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/beans.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<display-name>LoginServlet</display-name>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.abc.test.login.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/LoginServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
Update:
pom.xml:
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.12</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
Now Javax.ws.rs.NotFoundException gone, but, File not found exception still comes.
Solution-1
One of the solution is that version issue with CXF and Spring. I have made cxf version to 2.5.2 which avoids javax.ws.rs.NotFoundException.
Now I have updated to
<spring.version>3.2.2.RELEASE</spring.version>
<cxf.version>2.5.2</cxf.version>
I was using 2.7.5 cxf version.
Solution -2
In my service class I have made
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) instead of
#Produces(MediaType.TEXT_XML)
The URL you are using to fire the GET request has two services levels:
http://localhost:8080/assignment/services/services/"
but in your REST service class, there is only one 'services' level in Path. You may need to change the Path Param to like this:
#Service
#Path("/services/")
public class UserServiceImpl implements UserService {
#GET
#Path("services/{userName}/{password}")
#Produces(MediaType.TEXT_XML)
public String login(#PathParam("userName")String username, #PathParam("password")String password)
throws JAXBException, PropertyException, FileNotFoundException {
I think "services" is by default the path where CXF exposes the auto-generated WADLs and therefore cannot be used in a resource path.
Try either changing "services" to another word in your web.xml and Service class (#Path) or change the CXF servlet config like so (see the service-list-path param):
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<init-param>
<param-name>service-list-path</param-name>
<param-value>web-services</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Reference: http://cxf.apache.org/docs/jaxrs-services-description.html (section Service listings and WADL queries almost at the end).
Note that you can override the location at which listings are provided
(in case you would like '/services' be available to your resources)
using 'service-list-path' CXFServlet parameter
one common reason for this error is that cxf cannot find a restful implementation for the restful service to match the request to the resource method later. the spec is ambiguious in this area but your jaxrs annotations in the interface must match implementation in cxf.
--eliani
As described in CXF project throws java.lang.NoClassDefFoundError: javax/ws/rs/NotFoundException the
Error can be solved by adding
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0-m10</version>
</dependency>