I use Jackson to check and databind input JSON for a REST API, and I would like to log the error when the input doesn’t match a #Valid constraint.
However, the exceptions are throwned as a Response by the API but do not appear in Quarkus’ logs.
How do I log Jackson’s exceptions ?
One has to create a handler for the Jackson exceptions, e.g. using ExceptionMapper.
The following example catches all exceptions of type JsonProcessingException (finer tuning is obviously possible), logs them as SEVERE (using lombok’s #Log annotation) and returns a 400 Bad Request Response including the message. Note that the function has to be toResponse(Exception).
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.java.Log;
#Log
#Provider
public class MyJsonProcessingExceptionHandler implements ExceptionMapper<JsonProcessingException> {
#Override
public Response toResponse(JsonProcessingException exception) {
log.severe(exception.getMessage());
return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()).build();
}
}
Do not forget the #Provider annotation so that the Exception handler acts as a filter on the REST API.
In principle other files of the project (including the controller) do not need to be modified, only this class in its own file.
Related
i am try to realize Ajax Long Polling in my project
this structure of my project
str
in json file i have this code
{"user": "user","two": "two","three": "three"}
When i am try run my project, i get his in idea console:
WARN 8032 --- [nio-8080-exec-3].w.s.m.s.DefaultHandlerExceptionResolver:Failed to bind request element: org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; nested exception is java.lang.NumberFormatException: For input string: "status"
and this in chrome console:
log
I will be grateful for any help
Your javascript file doesn't include jQuery library.
you can include this before bootstrap library ( depend on jQuery ).
<script src="https://code.jquery.com/jquery-3.3.1.min.js" type="text/javascript"></script>
As per your error trace provided here, you're providing non numeric value to status field which is not transforming into Long. Due to this NumberFormatException raised. You can add #ExceptionHandler either in your controller or can define a global exception handler using #ControllerAdvice to handle the exception and send appropriate response message and status code.
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
#ControllerAdvice
public class ApiExceptionHandler {
#ExceptionHandler(Exception.class)
public ResponseEntity<Object> handlerGenericError(Exception ex){
ex.printStackTrace();
return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
#ExceptionHandler(MethodArgumentTypeMismatchException.class)
public ResponseEntity<Object>handlerBadRequest(MethodArgumentTypeMismatchExceptionex){
return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
}
I am running a server under WebSphere Application Server (17.0.0.1/wlp-1.0.16.cl170120170227-0220) and have added the changes recommended in this post (How to change Jackson version in JAX-RS app (WebSphere Liberty)) for upgrading the level of Jackson in WAS Liberty. I am using Postman to test my server. When I submit a GET request for an object, it completes successfully. (After adding this change, my server can return my objects in either XML or JSON.). However, I am now seeing these messages in the server console when my server builds the Response object.
[INFO ] FFDC1015I: An FFDC Incident has been created: "org.jboss.weld.exceptions.AmbiguousResolutionException: WELD-001318: Cannot resolve an ambiguous dependency between:
- Managed Bean [class com.ibm.zss.boundary.JaxbJsonProvider] with qualifiers [#Any #Default],
- Managed Bean [class com.ibm.zss.boundary.JsonProvider] with qualifiers [#Any #Default] com.ibm.ws.jaxrs20.cdi.component.JaxRsFactoryImplicitBeanCDICustomizer 425" at ffdc_17.06.13_15.59.57.0.log
com.ibm.zss.boundary.JaxbJsonProvider and com.ibm.zss.boundary.JsonProvider are the classes I added based on the instructions from the previous post.
I also updated my server.xml to include:
<feature>jsonp-1.0</feature>
<feature>jaxrs-2.0</feature>
I've been searching for solutions for handling a WELD ambiguousResolutionException, but most of them address issues with classes where the developer has control over what is being injected. So, I don't know if I have any control over the code that I need to change for this problem.
For completeness, here are the classes which I added to my application:
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;
import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
#Provider
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class JaxbJsonProvider extends JacksonJaxbJsonProvider {
}
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
#Provider
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class JsonProvider extends JacksonJsonProvider {
public JsonProvider() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(objectMapper.getVisibilityChecker().withFieldVisibility(JsonAutoDetect.Visibility.ANY));
setMapper(objectMapper);
}
}
Can you either mark it an #Specializes or an #Alternative with low #Priority, depending on whether you want it to be used for injection points?
My source code like below.
It has a error, "No exception of type DataAccessException can be thrown; an exception type must be a subclass of Throwable".
I can't understand why the error ocurrs.
let me know. thx.
package com.sds.afi.cosmos.cmm.db.impl;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import org.springframework.stereotype.Repository;
import com.sds.afi.cosmos.cmm.db.MainDao;
#Repository
//#SuppressWarnings("unchecked") // 부적절한 컴파일러의 경고를 제거
public class MainDaoImpl extends SqlMapClientDaoSupport implements MainDao {
#Autowired
private SqlMapClientTemplate sqlMapClientTemplate;
#SuppressWarnings("unchecked")
#Override
public List<HashMap> getUserInfo() throws DataAccessException {
List<HashMap> lists;
lists = sqlMapClientTemplate.queryForList("common.getList");
return lists;
}
}
This can happen if some class in the type-hierarchy of the exception is not on the class-path. In that case, its not possible to verify whether the exception really extends Throwable, whether it is a checked one or not, etc. Hence the errors. e.g superclass of Dataaccessexception : NestedRuntimeException may be missing from the class-path as it is in a differnt jar i.e. spring-core.
Your DataAccessException is not a subclass of Throwable class (extends Throwable). It should be, and without this inheritance, your code is not compilable with the current throws clause.
Here is an example: http://www.osix.net/modules/article/?id=754
I had this same issue when I upgraded to 5.X.X version. I have added Spring-core.jar file and it worked fine for me. Just adding this here because it may help some one. Spring txn jar , dao jar and spring core are must.
This means that in your getUserInfo() method there is no code that throws that exception. So just remove the throws clause from your method declaration.
I was facing same problem.
What I have done wrong was I have created Exception class(by mistake) of my own.
In other programs I was trying to extend Exception class(default) but complier(eclipse)was loading user defined Exception class giving me same error.
So please make sure you are not overriding any default class.
I'm developing an application with RESTEasy and JBOSS 5.1.
For specific situations, I have to return 404 error (not found).
In the sources, I'm using
import org.jboss.resteasy.spi.NotFoundException;
throw new NotFoundException(...);
The problem is that, in the header response, I have
Status Code: 500 internal server error
even if in the body the exception is:
org.jboss.resteasy.spi.UnhandledException: org.jboss.resteasy.spi.NotFoundException
This is a normal behavior? It's not possible to return Status Code: 404?
I encounter some problem. I found the root cause. The built-in exception handle is only occur in resteasy newest version build 2.3.1 GA. If you upgrade to this version.You can get the expected result.
It does seem a bit strange that RestEASY does not handle the NotFoundException out of the box. It should, according to the docs:
Resteasy has a set of built-in exceptions that are thrown by it when it encounters errors during dispatching or marshalling.
Anyways, you can work around it by adding an ExceptionMapper:
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.mock.MockDispatcherFactory;
import org.jboss.resteasy.mock.MockHttpRequest;
import org.jboss.resteasy.mock.MockHttpResponse;
import org.jboss.resteasy.spi.NotFoundException;
import org.junit.Assert;
import org.junit.Test;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
public class ExceptionTest {
#Path("/")
public static class Service {
#GET
public String notFound() throws NotFoundException {
throw new NotFoundException("");
}
}
public static class FailureExceptionMapper implements ExceptionMapper<NotFoundException> {
#Override
public Response toResponse(NotFoundException exception) {
return Response.status(exception.getErrorCode()).build();
}
}
#Test
public void test() throws Exception {
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
dispatcher.getProviderFactory().addExceptionMapper(new FailureExceptionMapper());
dispatcher.getRegistry().addSingletonResource(new Service());
MockHttpRequest request = MockHttpRequest.get("/");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
Assert.assertEquals(404, response.getStatus());
}
}
I believe that instead of throwing an exception you should use:
import javax.ws.rs.core.Response;
return Response.status(404).build();
in your rest method when you need to return a not found.
regards.
Maybe a custom javax.servlet.Filter can help.
I'm throwing an exception MyCustomException from my application. (EJB Layer)
I've an exception mapper in web service layer which looks like following -
package net.webservices;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import net.common.MyCustomException;
#Provider
public class EJBExceptionMapper implements
ExceptionMapper<net.common.MyCustomException> {
public Response toResponse(MyCustomException exception) {
return Response.status(Response.Status.BAD_REQUEST).build();
}
}
I've registered my mapper in web.xml of the web service layer as following -
<context-param>
<param-name>resteasy.providers</param-name>
<param-value>net.webservices.EJBExceptionMapper</param-value>
</context-param>
The EJBExceptionMapper is not catching the MyCustomException. But instead its being caught by the catch block of the web service implementation.
What could be the problem?
Note: I don't want to register my ExceptionMapper manually using getProviderFactory().addExceptionMapper()
I don't know why your solution doesn't work (but I've never used RESTeasy, only Jersey). In any case, it would probably be simpler to extend WebApplicationException. That way, you don't have to register a provider:
public class MyCustomException extends WebApplicationException {
public MyCustomException() {
super(Response.status(Response.Status.BAD_REQUEST).build());
}
}
You need to throw exception (of type MyCustomException ) in the catch block and add a "Throws MyCustomException" to the method signature