可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
So I'm building a web application, we are using JPA and Jersey to consume/produces JSON data.
I have a custom "EntityException" aswell as a custom "EntityExceptionMapper"
Here's the mapper:
@Provider
public class EntityExceptionMapper implements ExceptionMapper<EntityException> {
public EntityExceptionMapper() {
System.out.println("Mapper created");
}
@Override
public Response toResponse(EntityException e) {
System.out.println("This doesnt print!");
return Response.serverError().build();
}
}
My Exception:
public class EntityException extends Exception implements Serializable{
public EntityException(String message) {
super(message);
System.out.println("This prints...");
}
}
And I'm calling it from a REST call:
@POST
@Path("/test")
@Produces(MediaType.APPLICATION_JSON)
public String test() throws EntityException{
throw new EntityException("This needs to be send as response!!");
//return "test";
}
My problem is that, when the above exception is thrown, I get in the constructor (prints: "This prints...") Edit: I also get the: "Mapper created!"
But my response is empty, and I don't get to the sys out of my toResponse method. This is really similar to the example on the jersey website:
https://jersey.java.net/nonav/documentation/1.12/jax-rs.html#d4e435
What am I missing??
回答1:
I am using deployment agnostic application model so the following worked for me:
public class MyApplication extends Application {
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
s.add(HelloWorldResource.class);
/** you need to add ExceptionMapper class as well **/
s.add(EntityExceptionMapper.class)
return s;
}
}
回答2:
I had a similar problem where the ExceptionMapper
had the proper @Provider
annotation and the rest of the code was identical to Jersey's example but still wasn't registered properly.
Well it turns out I had to register manually my custom ExceptionMapper
within my HttpServlet
with the method addExceptionMapper
. Because it's now manually registered, the @Provider
annotation can be safely removed.
So with the following ExceptionMapper (I'm catching every RuntimeException
to rethrow them as 400)
public class MyCustomExceptionHandler implements ExceptionMapper<RuntimeException> {
@Override
public Response toResponse(RuntimeException exception) {
return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()).build();
}
}
I had to add the 2nd line in my init :
HttpServlet serviceServlet = jerseyServletFactory.create(someResource);
jerseyServletFactory.addExceptionMapper(new MyCustomExceptionHandler()); //<--
httpServer.register(serviceServlet, "/api");
httpServer.start();
回答3:
I had the same problem and was able to fix it by including the package of my ExceptionMapper in the jersey.config.server.provider.packages in my web.xml file. Below is a snippet from my web.xml.
<servlet>
<servlet-name>voteride-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.voteride.ws;com.voteride.errorHandling;org.codehaus.jackson.jaxrs
</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.scanning.recursive</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
回答4:
I have encountered the same issue while develop sample REST API. While creating REST API i have given base package name like org.manish.rest.message,
I supposed to create every other packages under the base package like this
- model -
org.manish.rest.message.model
- database -
org.manish.rest.message.database
- resource -
org.manish.rest.message.resource
in web.xml init param was given like this
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>org.manish.rest.message</param-value>
</init-param>
It means, i have registered my base package in web.xml, what ever package i will create under this; will be consider by JAX-RS based on my call and requirement. But when i created my exception package by mistake i put package name org.manish.rest.exception. Since this was not registered in web.xml so my complete exception class was not considered to handle exception by JAX-RS.
As a correction, i have just modified my exception package name from
org.manish.rest.exception
to org.manish.rest.message.exception
After that i executed once in post man and i got expected result.
Hope this can solve your query.
Thanks
Manish
回答5:
I used spring to wire up jersey app and used @Component with @Provider.
When I moved to jersey v > 2.5, it stopped working.
I resolved this very issue by putting @Singleton annotation instead of @Component alongside @Provider, like this:
@Provider
@Singleton
public class EntityExceptionMapper implements ExceptionMapper<EntityException> {...
回答6:
I'm using the Jersey JdkHttpServerFactory
, and I just had to add the ExceptionMapper
class as a resource, just like my other controller resources:
import com.sun.net.httpserver.HttpServer;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
import java.util.HashSet;
import java.util.Set;
import org.glassfish.jersey.jdkhttp.JdkHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
// ...
Set<Class> resources = new HashSet<>();
// Add whatever other resource classes you have...
//--->>> Add the exception mapper <<<---
resources.add(EntityExceptionMapper.class);
ResourceConfig resources = new ResourceConfig(resources);
URI uri = UriBuilder.fromUri("http://localhost/").build();
HttpServer server = JdkHttpServerFactory.createHttpServer(uri, resources);
回答7:
Try to register your exception mapper class in your X extends ResourceConfig file.
register(CustomExceptionMapper.class);
this line will help application to find your mapper class and return whatever you have written inside the toResponse method of mapper class
回答8:
I am still using jersey 1.17 , spring and jersy-spring
@Component annotation fixes this
回答9:
I also face the same issue.Just add the package name that have the ExceptionMappperHandler classes.
<web-app version="2.5" 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_2_5.xsd">
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>Service,Utilities.ExceptionMapper</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Here,service contain all service classes and Utilities.ExceptionMapper contains all exceptionMapper.
Hope its help
回答10:
I had the same problem. I just had to modify the web.xml.
Previously in my web.xml file param-value was com.two95.restful.resource
I just changed to root package com.two95.restful
. Then it started working like a charm with just the @Provider
annotation.
<servlet>
<servlet-name>Jersey Web Application</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.two95.restful</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>