8

my Spring Boot + Jersey REST service doesn't work as expected.

EmailExistsException is thrown in UserController but I only receive error 500. All the time. And my exceptions aren't logged.

I suspect there is some configuration issue with exception handling but don't know where to set it up. Any suggestions?

@POST
@Path("register")
@Produces(MediaType.APPLICATION_JSON)
public Response register(NewUserPayload newUserPayload) throws EmailExistsException, MessagingException

EmailExistsExceptionMapper

@Provider
public class EmailExistsExceptionMapper extends AbstractExceptionMapper       implements
    ExceptionMapper<EmailExistsException>
{
@Override
public Response toResponse(EmailExistsException e)
{
    ResponseEntity re = new ResponseEntity(org.springframework.http.HttpStatus.BAD_REQUEST);

    return this.errorResponse(HttpStatus.BAD_REQUEST_400, re, e);
}
}

AbstractExceptionMapper

@Slf4j
public abstract class AbstractExceptionMapper
{
protected Response errorResponse(int status, ResponseEntity responseEntity, Throwable t)
{
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    t.printStackTrace(pw);
    log.error(sw.toString()); // logging stack trace.

    return customizeResponse(status, responseEntity);
}

private Response customizeResponse(int status, ResponseEntity responseEntity)
{
    return Response.status(status).entity(responseEntity).build();
}
}

build.gradle

compile("org.springframework.boot:spring-boot-starter-web") {
    exclude module: 'spring-boot-starter-tomcat'
}
compile "org.springframework.boot:spring-boot-starter-jetty"
compile "org.springframework.boot:spring-boot-starter-security"
compile "org.springframework.boot:spring-boot-starter-aop"
compile "org.springframework.boot:spring-boot-starter-data-jpa"
compile "org.springframework.boot:spring-boot-starter-thymeleaf"
compile "org.springframework.boot:spring-boot-starter-jersey"
compile 'org.springframework.boot:spring-boot-starter-mail'
Reeebuuk
  • 1,363
  • 2
  • 21
  • 42

4 Answers4

17

Answer that solved my problems:

I've put packages("package.name"); which is my root package name and exception mappers work like a charm.

@Component
@ApplicationPath("/api")
public class JerseyConfig extends ResourceConfig
{
public JerseyConfig()
{
    packages("package.name");
    register(UserController.class);
    register(TimezoneController.class);
}
}
Reeebuuk
  • 1,363
  • 2
  • 21
  • 42
  • no information about this configuration in the [jersey documentation](https://jersey.java.net/documentation/latest/representations.html#d0e6653). Does the `package` declaration will avoid you to declare controllers ? – herau Nov 10 '15 at 13:35
  • I've found it in some code snippet on the internet. I'm in Scala now so couldn't tell you more info about it. – Reeebuuk Nov 10 '15 at 13:38
  • 4
    Thanks! It turns out you have to either explicitly `register(YourExceptionMapper.class)` or place it in a scanned package via `packages("YourExceptionMapperPackage")`. I spent couple of hours trying to figure this out before I found your answer. – I-Lin Kuo Apr 08 '16 at 19:31
1

Have you configured custom ExceptionMapper as a jax-rs provider, and Are you sure that your exception is getting wrapped into EmailExistsException? You may have to look at this post.

JAX-RS using exception mappers

Community
  • 1
  • 1
Lovababu Padala
  • 2,415
  • 2
  • 20
  • 28
  • It has a @Provider annotation and yes, I'm sure that it gets wrapped and thrown. Another thing is that when I try to put breakpoint in EmailExistsExceptionMapper it is not alive in IDEA in debug mode. It seems that somehow it isn't used? Some config is missing maybe but where? – Reeebuuk Jan 16 '15 at 11:55
0

I had the same problem

I just mentioned the root package on the web.xml file in <param-value> tag of <init-param>

Then It started working like charm

<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>
Mr Lister
  • 45,515
  • 15
  • 108
  • 150
SM ANSARI
  • 335
  • 3
  • 13
0

If you using ExceptionMapper, you must register your exception mapper:

@Component
@Provider
public class ApiApplicationExceptionMapper implements ExceptionMapper<Exception> {

    @Override
    public Response toResponse(Exception exception) {
       ...
    }
}

In Jersey config class, scan Jersey Endpoint class with @Path annotation and custom Exception Mapper with @Provider annotation to register:

@Configuration
public class JerseyConfig extends ResourceConfig {

    @Autowired
    ApplicationContext applicationContext;

    @PostConstruct
    public void init() {
        this.registerEndpoints();
        this.registerExceptionMappers();
    }

    private void registerEndpoints() {
        Map<String, Object> beans = applicationContext.getBeansWithAnnotation(Path.class);
        for (Object apiClass : beans.values()) {
            logger.info("Jersey register: " + apiClass.getClass().getName());
            register(apiClass);
        }
    }

    private void registerExceptionMappers() {
        Map<String, Object> beans = applicationContext.getBeansWithAnnotation(Provider.class);
        for (Object exceptionMapper : beans.values()) {
            logger.info("Jersey exception mapper register: " + exceptionMapper.getClass().getName());
            register(exceptionMapper);
        }
    }
huytmb
  • 3,647
  • 3
  • 12
  • 18