MessageBodyWriter not found for media type=text/xml or type=text/plain when throwing an exception - json

I am getting an Exception
"MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=text/xml, type=class ..."
when an exception is thrown from within an application on Glassfish 4.1.
Before activation of Jackson instead of Moxy/Jaxb everything was fine.

Verify if your MessageBodyWriterAdater is producing the same media type as your services/methods.
They have to be consistent or you just have to write additional MessageBodyWriterAdapters for unsupported types.
e.g.
#Produces(MediaType.APPLICATION_JSON)
public abstract class JsonMessageBodyWriterAdapter<T> implements MessageBodyWriter<T> { ...
}
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path("xxx")
public class XxxBs {
#POST
public void create(#NotNull final XxxDO xxxDo) throws ResponseException {
// do something
}
}

Related

Jackson tries to cast Integer to String

I have a very basic Spring Boot app with .-data-jpa, .-data-rest and .-web dependencies.
In my model there is an entity Game that contains an Integer property homeGameSwitch.
When I get the resource with a REST call I get this exception:
.w.s.m.s.DefaultHandlerExceptionResolver : Failed to write HTTP
message:
org.springframework.http.converter.HttpMessageNotWritableException:
Could not write JSON: java.lang.Integer cannot be cast to
java.lang.String; nested exception is
com.fasterxml.jackson.databind.JsonMappingException: java.lang.Integer
cannot be cast to java.lang.String (through reference chain:
org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$PersistentEntityResourceSerializer$1["content"]->com.coli.stripebackend.model.Game["homeGameSwitch"])
I find it strange that Jackson can't handle an Integer.
Is there something I can do prevent this error?
The entity:
#Entity
public class Game {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private Integer homeGameSwitch;
public Integer getHomeGameSwitch() {
return homeGameSwitch;
}
The DAO:
#Repository("gameDao")
public interface GameDao extends JpaRepository<Game, Integer> {}
The service:
#Service("gameService")
public class GameServiceImpl implements GameService {
#Autowired
private GameDao gameDao;
#Override
public Game retrieveGameById(Integer id) throws Exception {
Optional<Game> optionalGame = gameDao.findById(id);
return optionalGame.get();
}
The error occurs when calling localhost:8080/game/7
The problem was related to the version of Spring Boot. I was using the version 2.0.0.M2 in which there seems to be a bug.
I don't have the problem when using the version 1.5.4.RELEASE.
This is a warning to future readers who come here: There are many ways to trigger this exception: Some similar ones are collected in Jackson serialization exception when trying to serialize LocalDateTime
It seems I just ran into another way of getting the exact same exception: Have a class like this:
class Foo extends HashMap<String, String> {
public long bar;
}
and try to serialize it.

Junit Mockito test case for ResponseEntity<?> in spring integration framework

I am trying to mock the external call.
ResponseEntity<?> httpResponse = requestGateway.pushNotification(xtifyRequest);
requestGateway is an interface.
public interface RequestGateway
{
ResponseEntity<?> pushNotification(XtifyRequest xtifyRequest);
}
Below is the test method i am trying to do.
#Test
public void test()
{
ResponseEntity<?> r=new ResponseEntity<>(HttpStatus.ACCEPTED);
when(requestGateway.pushNotification(any(XtifyRequest.class))).thenReturn(r);
}
A compilation error is there in the above when statement,saying it as an invalid type.even thougg r is of type ResponseEntity.
Can anyone please help me to solve this issue ?
You can instead use the type-unsafe method
doReturn(r).when(requestGateway.pushNotification(any(XtifyRequest.class)));
Or you can remove the type info while mocking
ResponseEntity r=new ResponseEntity(HttpStatus.ACCEPTED);
when(requestGateway.pushNotification(any(XtifyRequest.class))).thenReturn(r);

Jersey ParamConverter exceptions not handled by ExceptionMapper

Per title, exceptions thrown from a ParamConverter are NOT handled the way I expect.
With an ExceptionMapper:
#Provider
public class MyExceptionMapper implements ExceptionMapper<MyException> {
#Override
public Response toResponse(MyException exception) {
return Response.serverError().entity( "It triggered" ).build();
}
}
and ParamConverter:
#Provider
(boilerplate junk)
#Override
public DateTime fromString(String value) {
throw new MyException("convert");
}
It does NOT return the "It triggered" text in a 500 error, but rather a 404.
Anticipated question : Are both providers registered?
Yes - If I throw "MyException" from a resource (within 'regular' code) it works as expected. I can also convert see the stacktrace with the "convert" message.
Is there any way to make exceptions from ParamConverters be handled by the ExceptionMapper?
I am using jersey 2.3.1, along with spring-jersey, launched in a jetty container 9.1.0.RC0
Seem from reading this, the JAX-RS spec says the implementor should wrap unhandled exceptions in a NotFoundException (404) for #QueryParam and #PathParam, and from what I tested a 400, (I'm guessing BadRequestException) for #FormParam.
"if the field or property is annotated with #MatrixParam, #QueryParam or #PathParam then an implementation MUST generate an instance of
NotFoundException (404 status) that wraps the thrown exception and no entity"
A couple ways I can see handling the exception, is to
Just handle it in the ParamConverter, e.g.
return new ParamConverter<T>() {
#Override
public T fromString(String string) {
try {
return (T)new MyObject().setValue(string);
} catch (MyException ex) {
Response response = Response.serverError().entity("Boo").build()
throw new WebApplicationException(response);
}
}
#Override
public String toString(T t) {
return t.toString();
}
};
Or just have your exception extend WebApplicationException, and return the Response there. e.g.
public class MyException extends WebApplicationException {
public MyException(String message) {
super(Response.serverError().entity(message).build());
}
}
I experienced the same behavior in Jersey 2.26.
Any Exception that extends RuntimeException gets mapped to a ParamException, which is itself a sublcass of WebApplicationException.
Assuming your MyException extends RuntimeException, it's not getting caught because your ExceptionMapper only handles MyException.
Regarding the Jersey docs saying to throw a NotFoundException: I would argue a 404 does not apply when a queryParam can't be converted. A BadRequestException seems more appropriate. And also, I can't see anything unique in the Jersey frame work when a NotFoundException is thrown besides setting the response code
To get exceptions thrown from a ParamConverter end up in an ExceptionMapper, you'll have to have your ExceptionMapper catching a more global exception, like Throwable.
Another answer suggests returning a WebApplicationException. This should be a fine solution but will NOT work if the Response object has an entity. See here: https://github.com/jersey/jersey/issues/3716

Using ServiceStack unhandled exception behavior

I would like to get automatic exception serialization without manually adding ResponseStatus to the response DTO.
Based on this info on unhandled exception behavior I wrote the following code
public class ContactService : RestServiceBase<Contact>
{
public override object OnGet(Contact request)
{
return ContactApi.GetContactInfo(request);
}
//To trigger the serialization of the Exception to ResponseStatus
protected override object HandleException(Contact request, Exception ex)
{
throw ex;
}
<snip />
}
Do you see any issues with using the library in this manner?
Thanks in advance.
UPDATE: I would like to get the following response when there is an exception without having to add ResponseStatus property to my response DTO object.
I am able to achieve this with by overriding the HandleException method as shown above.
My question is:
Can overriding the default exception handling behavior in this manner cause any problems down the road?
{
"ResponseStatus":{
"ErrorCode":"ApplicationException",
"Message":"CRASH",
}
}

Camel Exception handling doesnt work if exception clause is defined in a separate class

I am trying to build a application with several camel routes which re use many common routes internally.
Hence, I am trying to segregate the routes in several different Route Builder classes and then connecting the routes where needed.
For eg, all routes pertaining to sending emails go into a EmailRouteBuilder class and all routes dealing with a particular JMS Queue go into MyQueueRouteBuilder class.
I suppose this should be alright since Camel doesnt not distinguish between classes and only looks for routes defininition.
In addition, I am also grouping several exception handling routes into a separate ExceptionHandlingRouteBuilder.
I am also connecting all the different classes together by defining the camel context in Spring like so -
<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="properties" location="classpath:${env}/autoimport.properties"/>
<!-- Common Routes -->
<routeBuilder ref="emailRouteBuilder" />
<routeBuilder ref="myQueueRouteBuilder" />
<routeBuilder ref="httpRouteBuilder" />
<routeBuilder ref="exceptionsRouteBuilder" />
<routeBuilder ref="customer1RouteBuilder" />
<routeBuilder ref="customer2RouteBuilder" />
</camelContext>
My exceptionsRouteBuilder contains many exception clauses like -
onException(ConnectException.class)
.routeId("connectExceptionEP")
.handled(true)
.log("Caught Exception: ")
.to("direct:gracefulExit");
..
..
..
However, it looks like there is a problem with the exceptions being defined in another class, or for that matter, defined separately out of the main route definition.
I verified this in the logs by looking for the routes being booted ( by routeId ) and also checking when an exception is thrown.
Additionally, to further confirm, I took the http Connect Exception handling route and put that directly in the httpRouteBuilder and lo..! , the exception handling now kicks in just fine for this exception..
Am I missing something here to get all exceptions to work while being nicely defined in its own class. ?
I am using Apache Camel 2.9.0 , but I verified the same behavior also in 2.8.3.
Thanks,
Anand
correct, the onException() clauses only apply to the current RouteBuilder's route definitions...
that said, you can reuse these definitions by having all your RouteBuilders extend the ExceptionRouteBuilder and call super.configure()...something like this
public class MyRouteBuilder extends ExceptionRouteBuilder {
#Override
public void configure() throws Exception {
super.configure();
from("direct:start").throwException(new Exception("error"));
}
}
...
public class ExceptionRouteBuilder implements RouteBuilder {
#Override
public void configure() throws Exception {
onException(Exception.class).handled(true).to("mock:error");
}
}
or even just have a static method in an ExceptionBuilder class to setup the clauses for a given RouteBuilder instance
public class MyRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
ExceptionBuilder.setup(this);
from("direct:start").throwException(new Exception("error"));
}
}
...
public class ExceptionBuilder {
public static void setup(RouteBuilder routeBuilder) {
routeBuilder.onException(Exception.class).handled(true).to("mock:error");
}
}
Based on the accepted answer, I found a cleaner way to implement exception handling, so you don't have to call super.configure() in every route. Just call a method that handles onException in the constructor of the base class.
//Base class that does exception handling
public abstracExceptionRouteBuildert class BaseAbstractRoute extends RouteBuilder {
protected BaseAbstractRoute() {
handleException();
}
private void handleException() {
onException(Exception.class).handled(true).to("mock:error");
}
}
//Extend the base class
public class MyRouteBuilder extends BaseAbstractRoute {
#Override
public void configure() throws Exception {
from("direct:start").throwException(new Exception("error"));
}
}