ExceptionMapper not called with jersey2 and jboss 7.11 - jboss

I have an exception mapper in my jaxrs project to catch all NotFoundException's and format the response. When running in Tomcat, the exception mapper is invoked when the exception is thrown. I have now had to move to JBoss, and all is working fine, except for the exception mapper is no longer called.
Web.xml
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Restful Web Application</display-name>
<servlet>
<servlet-name>RestConfigServer</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>com.xxx.rest.resources.RestConfigServerResourceImpl</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.xxx.rest.exceptions</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<listener>
<listener-class>com.xxx.ContextListener</listener-class>
</listener>
<servlet-mapping>
<servlet-name>RestConfigServer</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<!-- For JBoss as it ships with RESTEasy JAX-RS as a implicit dependency -->
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>resteasy.scan.providers</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>resteasy.scan.resources</param-name>
<param-value>false</param-value>
</context-param>
Exception Mapper
import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import com.openet.modules.config.server.rest.response.ErrorInfo;
import com.openet.modules.config.server.rest.response.ErrorResponse;
#Provider
public class NotFoundExceptionMapper implements ExceptionMapper<NotFoundException> {
public Response toResponse(NotFoundException ex) {
ex.printStackTrace();
return Response
.status(ex.getResponse().getStatus())
.entity(new ErrorResponse(new ErrorInfo(ex)))
.type(MediaType.APPLICATION_JSON)
.build();
}
}

Moved from version 2.7 to 2.24 of jersey and the exception mapper is now called.

Related

Jersey #Component / Configuration class

could someone help me to write correctly Jersey Configuration class? So I'm using xml file as guide line for my upload and download webapp. I don't know how to register download service.
<?xml version="1.0" encoding="UTF-8"?><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>Jersey-UP-DOWN-Image-File</display-name>
<!-- Jersey Servlet -->
<servlet>
<servlet-name>jersey-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Register resources and providers -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.jersey.series.upload.download.service</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<!-- welcome file -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
For now my config class looks like:
import Images_WebApp.Images_WebApp.Resource.ImageResource;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.stereotype.Component;
#Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(ImageResource.class);
register(MultiPartFeature.class);
}
}

Viewable route returns 404

When trying to access /Example/Site a 404 no found page will be shown, but the jsp is in webapp/WEB-INF/jsp/. Why is this not working?
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>jmattheis rest app</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>jersey-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>com.stackoverflow.jmattheis.rest</param-value>
</init-param>
<init-param>
<param-name>jersey.config.servlet.filter.forwardOn404</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.server.mvc.jsp.JspMvcFeature</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.mvc.templateBasePath.jsp</param-name>
<param-value>/WEB-INF/jsp</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.tracing</param-name>
<param-value>ALL</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Here the Resource:
#Component
#Path("Example")
public class Example {
#GET
#Path("/Site")
#Produces(MediaType.TEXT_HTML)
public Response getSite() {
return Response.ok(new Viewable("/test")).build();
}
}
Have a look at the Jersey2 MVC documentation
Jersey web applications that want to use JSP templating support should be registered as Servlet filters rather than Servlets in the application's web.xml. The web.xml-less deployment style introduced in Servlet 3.0 is not supported at the moment for web applications that require use of Jersey MVC templating support.
So you need to change your servlet to an filter to make it work.
It could be that this was not needed in the early versions of jersey 2, but I cannot find the older documentation for that so we'll never know.
Like this:
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>jmattheis rest app</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>jersey-filter</filter-name>
<filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.stackoverflow.jmattheis.rest</param-value>
</init-param>
<init-param>
<param-name>jersey.config.servlet.filter.forwardOn404</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.server.mvc.jsp.JspMvcFeature</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.mvc.templateBasePath.jsp</param-name>
<param-value>/WEB-INF/jsp</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.tracing</param-name>
<param-value>ALL</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>jersey-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

Issue setting up Swagger.io with JAX-RS project on JBoss / Wildfly 9

I implement a project that uses a quite simple JAX-RS backend for providing data to an AngularJS based UI. These are separated modules and deployed on a Wildfly 9. In order to have a nice documentation for the REST endpoints I came across swagger.io that seems a good fit. However, I have trouble setting up swagger following the documentation and examples since my project has a slightly different structure.
Current status
I can access http://localhost:8080/service/swagger.json that returns
{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": ""
},
"host": "localhost:8080",
"basePath": "/service",
"schemes": ["http"]
}
However the swagger-ui (swagger.json is correctly linked) does not show any of my REST endpoints.
I think the issue might be related to the basePath or the contextRoot that is set for the Wildfly but that's just a vague guess. Besides that I'm not even sure what swagger JAX-RS implementation to use. I thought since I use Wildfly (JBoss) it should be Resteasy but the swagger Jersey setup docs seem better fitting.
My REST endpoints look e.g. like that http://localhost:8080/service/users/register
Related resources
pom.xml
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-core</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jaxrs</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.4</version>
</dependency>
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"
version="3.1">
<display-name>service</display-name>
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
io.swagger.jaxrs.listing,
jfs.service.services
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<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:8080/service</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
</web-app>
jboss-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<context-root>/service/</context-root>
</jboss-web>
UserWebService as example
package jfs.service.services;
import com.google.gson.Gson;
import io.swagger.annotations.*;
import jfs.data.dataobjects.UserDO;
import jfs.data.dataobjects.enums.UserType;
import jfs.service.sessions.Session;
import jfs.transferdata.transferobjects.*;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import java.util.List;
#Path("/users")
#Api(tags = {"users"}, value = "/users", description = "Operations about user")
public class UserWebService {
#Inject
UserService service;
#POST
#ApiOperation(value = "Register company",
notes = "A user account for company will be created.",
position = 1)
#Path("/register")
#Consumes("application/json")
#Produces("application/json")
public Boolean registerCompany(RegisterDTO register){
Boolean result = false;
result = this.service.registerUser(register.email, register.password, UserType.COMPANY);
return result;
}
}
After some try & error I figured a way out to make it working. For the hooking up the swagger-core I switched from manual registration of the resource classes to the automatic scanning and registration. That required to change the configuration and initialization from the web.xml to the BeanConfig with e.g. a servlet.
I don't know about the (dis)advantages of the different approaches if there are any - maybe someone can share some insights.
Other than that, this is a working solution for me now:
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"
version="3.1">
<display-name>service</display-name>
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<servlet>
<servlet-name>SwaggerServlet</servlet-name>
<servlet-class>jfs.service.services.SwaggerServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
</web-app>
SwaggerServlet.java
package jfs.service.services;
import io.swagger.jaxrs.config.BeanConfig;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
public class SwaggerServlet extends HttpServlet {
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.0");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/service");
beanConfig.setResourcePackage("jfs.service.services");
beanConfig.setScan(true);
}
}

RESTEasy - Resource Class Register Failed when #Path is Marked in the Interface

I am using RESTEasy 2.0.1.GA on Jboss 4.3.0.GA.
The interface that my resource class implemented looks like this:
#Path("/")
public interface CwindRestfulService {
#GET
#Path("accounts/{email}")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Account getAccountInfo(#PathParam("email") String email) throws Exception;
}
When I set resteasy.scan=true in web.xml, it works fine. But it should be false with spring context. So now my web.xml is:
<web-app>
<display-name>Archetype RestEasy Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>resteasy.resources</param-name>
<param-value>com.cwind.rest.CwindRestfulServiceImpl</param-value>
</context-param>
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
And I got this error:
2014-02-20 18:10:23,303 ERROR [org.apache.catalina.core.ContainerBase] Exception sending context initialized event to listener instance of class org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
java.lang.RuntimeException: Class is not a root resource. It, or one of its interfaces must be annotated with #Path: com.cwind.rest.CwindRestfulServiceImpl implements: com.cwind.rest.CwindRestfulService
It suggested that I missed #Path while actually I didn't. But when I put the annotation to the resource class it does work. I googled and found a solution in http://pilhuhn.blogspot.com/2011/06/seemingly-common-resteasy-error-and.html. It needs to add a #ApplicationPath annotation. Now my interface is in a third party lib so I can't modify it. Does anybody have some suggestions? Thanks in advance.
It appears that you have not registered a Resteasy specific SpringContextLoaderListener. This is required for Spring to register scanned resource classes with Resteasy.
Below is an example web.xml configuration (this uses annotation configuration, but will also work with xml configuration):
<!-- Spring Configuration -->
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.myapp.SpringConfig</param-value>
</context-param>
<!-- RESTEasy Configuration -->
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/</param-value>
</context-param>
<!-- RESTEasy <-> Spring Connector (Needed so that RESTEasy has access to Spring managed beans!) -->
<listener>
<listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class>
</listener>
<!-- RESTEasy HTTP Request Processor Servlet -->
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Then you simply annotate your resource classes for Spring either with #Component or #Named as shown below:
#Named
#Path("/")
public class MyResource implements CwindRestfulService
{
//Stuff Goes Here...
}

Jersey integration with Spring MVC

I want to create a website that is able to work with rest with an android application.
For these rest-calls I want to make use of a seperate servlet
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"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>Stage XT-i</display-name>
<welcome-file-list>
<welcome-file>/WEB-INF/jsp/index.jsp</welcome-file>
</welcome-file-list>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-servlet.xml
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<!-- Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Jersey Web Application</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>be.kdg.teamf</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
As you can see al the jersey information is passed using the url: /rest/*
When I want to do a GET for a string using the url: localhost:9999/rest/user/sample it work perfectly.
However when I use #Autowired with jersey I get a nullpointer exception.
Java class:
#Path("/user")
public class UserRest {
#Autowired
private UserService userService;
#Context
UriInfo uriInfo;
// Another "injected" object. This allows us to use the information that's
// part of any incoming request.
// We could, for example, get header information, or the requestor's address.
#Context
Request request;
// Basic "is the service running" test
#GET
#Produces(MediaType.TEXT_PLAIN)
public String respondAsReady() {
return "Demo service is ready!";
}
#GET
#Path("sample")
#Produces(MediaType.APPLICATION_JSON)
public User getUserJson() {
User u = userService.listUsers().get(0);
System.out.println("Returning person");
return u;
}
}
Does anyone see the problem?
Thanks in advance.
Use Spring Jersey integration servlet
com.sun.jersey.spi.spring.container.servlet.SpringServlet