I am working on an application for which I required to build the response in case an invalid JSON payload is sent in the request.
Currently the exception message received at the server end is Unexpected character ('"' (code 34)): was expecting comma to separate OBJECT entries
at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream#310db662; line: 13, column: 7]
This is how I'm trying to achieve it ...
import java.util.ArrayList;
import java.util.List;
import javax.validation.ConstraintDeclarationException;
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 org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
#Provider
public class JsonParseExceptionMapper implements ExceptionMapper<JsonProcessingException> {
private static Logger logger = LogManager.getLogger(JsonParseExceptionMapper.class.getName());
#Override
public Response toResponse(final JsonProcessingException ex) {
System.out.println("inside json parse exception mappper");
logger.error(messages.toString());
return Response.status(Response.Status.BAD_REQUEST).entity(messages).type(MediaType.APPLICATION_JSON).build();
}
}
I also have a similar ExceptionMapper which catches the ConstraintViolationException which is working fine.
I also tried a few different exceptions as suggested over the internet, to name a few
JsonProcessingException
BadRequestException
JsonParseException
InvalidFormatException
ConstraintDeclarationException
But None of the above exceptions seem to work in this case. Does anyone have any idea as to which exception should be used in conjunction with the ExceptionMapper to catch such cases.
Also, I guess it is possible to have more than one ExceptionMapper implementations running parallel to each other. Please correct if I'm wrong.
Edit: This is what I mean by an invalid JSON Payload, look out for the missing comma before checksum
{
"payload": {
"name":"rachel",
"employeeid":"23443"
}
"checksum":""
}
Jersey v2.22.1
Spring v4.2.4-RELEASE
For some reason I'm not able to comment on any of the posts !!! Even the edit window has issues, I can't see any icon !!
I tried using RuntimeException, Exception and IOException as well but the ExceptionMapper didn't work for them too. I guess it takes a specific time of exception like the ConstraintViolationException which is in use with another ExceptionMapper and that one is working fine.
some part of web.xml
jersey.config.beanValidation.enableOutputValidationErrorEntity.server
true
jersey.config.server.disableMoxyJson
true
Initially I had registered JacksonFeature.class for Json Parsing which uses its own ExceptionMapper for JsonParseException.
I changed it to JacksonJaxbJsonProvider.class.
I'm now able to use my custom JsonParseExceptionMapper.
Had to change certain dependencies !!
Related
I have a simple micronaut app.
I have two separate endpoints where the method that executes will call an API using a client (I've tried both the http client from "java.net.http.HttpClient" and "io.micronaut.http.client.RxHttpClient" but the same issue happens).
When you hit any of the endpoints after starting the app, the function will execute as expected, where the client calls an external API and retrieves the response as a string. If you try to hit that same endpoint again, it will throw:
"javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure."
I don't think this is an issue on the API's server side for the following reasons:
This issue happens when I hit two separate endpoints with two separate external APIs
The request goes through the first time no problem
I can hit the same APIs in postman without error - it's just when I call them with the client that there is an issue.
My controller:
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.HttpResponse;
import javax.inject.Inject;
import java.io.IOException;
import static io.micronaut.http.HttpRequest.GET;
#Controller("/api")
public class DeckController {
#Inject
private DeckService deckService;
#Get(value = "/drawRx")
public HttpResponse<Card> drawCardRx(){
deckService.drawCardRx("ijhhxvxwn63g",1);
return HttpResponse.ok();
}
}
One of my services where the client calls the API:
public void drawCardRx(String deckId, int amount){
final String newDeckUrl = "/deck/"+deckId+"/draw/?count="+amount;
Disposable result = this.httpClient
.retrieve( GET(newDeckUrl))
.subscribe(data -> System.out.println(data));
return;
}
Like I said, the first time I hit the endpoint, the response is returned from the server without a problem.
I've tried the below articles and followed those steps, but no improvement.
https://www.baeldung.com/java-ssl-handshake-failures
How to solve javax.net.ssl.SSLHandshakeException Error?
Is there something I am missing?
I would like to ask about if there is a way to call a Filter (javax.servlet.Filter) inside an Apache Camel processor.
Scenario
Inside an Apache Camel Processor (org.apache.camel.Processor), I need to make use of some existing Filter class to perform some logics on the request.
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
public class TestProcessor implements Processor {
#Override
public void process(Exchange exchange) throws Exception {
RequestParameters parameters = exchange.getIn().getBody(RequestParameters.class);
...
......
// Can we call an existing Filter class here?
// e.g. addInfoFilter.doFilter(request, response, filterChain)
...
......
exchange.getIn().setBody(requestParams);
}
I'm not sure how this could be achieved. Please let me know if you have any insights, thanks.
It seems it is not possible to call a filter inside a Camel processor. Probably the best (or only way) is to intercept the request with the filter, using configuration in web.xml.
I'm learning REST web service. I need some clarification on handling custom exception in Jersey. By using WebApplicationException and ExceptionMapper you can throw custom Exception. My question is in which scenario we have go for WebApplicationException and ExceptionMapper. What are the differences between them?
I've gone through with some tutorial, I found that ExceptionMapper is like Generic.
#Provider
class MyWrapper implements ExceptionMapper<MyPojoClass>
{
}
One more difference is that,
Because of #Provider Jersey will catch this exception only by default, if any other exception occurs also.
Is there any other differences?
MyExceptionMapper.java
package com.katte.galaxe.exception;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
public class MyExceptionMapper implements ExceptionMapper<MyCustomException>
{
#Override
public Response toResponse(MyCustomException errMsg) {
ErrorMessage msg = new ErrorMessage(errMsg.getMessage(),1100);
return Response.status(Status.NOT_FOUND)
.type(MediaType.APPLICATION_XML)
.entity(msg)
.build();
}
}
MyWebApplicationException.java
package com.katte.galaxe.exception;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
public class MyWebApplicationException extends WebApplicationException{
private static final long serialVersionUID = -5788907118191114665L;
public MyWebApplicationException(ErrorMessage msg) {
super(Response.status(Status.NOT_FOUND)
.entity(msg)
.type(MediaType.APPLICATION_XML)
.build());
}
}
WebApplicationException and ExceptionMapper are not meant to be compared as they serve different purpose. Instead they are meant to be used together for a better response strategy.
Imagine a case wherein an exception is encountered while serving a request. Let's say you encountered a SQLException while accessing a database. In this case one can make use of ExceptionMapper to map SQLException with an appropriate 5xx response instead of propagating the original exception to the end user.
WebApplicationException
Runtime exception for applications.
This exception may be thrown by a resource method, provider or StreamingOutput implementation if a specific HTTP error response needs to be produced. Only effective if thrown prior to the response being committed.
ExceptionMapper
Contract for a provider that maps Java exceptions to Response.
As editing a question didn't seem to bump it up for more answers, I'll continue asking in a new thread.
The thing is that I'm trying to set up a very basic web-service with Spring, to which I should be able to send JSON through Java.
But I'm very new to Spring, and web-services in general, so I don't know where to troubleshoot.
Old question: Getting a RESTful webservice with Spring to understand a JSON-string
Right now I have this in my controller
#RequestMapping(value = "/toggleB")
public #ResponseBody String sendCommand(#RequestBody Ident ident) {
//body
}
The Ident-class just has a String as variable, called IP.
Sending this String
{"IP":"192.168.1.9"}
Gives the return code 400.
Thing is, I think there might be something wrong, or missing, in the build.gradle (or pom.xml).
How is a correct Gradle/Spring project supposed to be organized as?
My main method is runnable, and looks like this:
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;
#ComponentScan
#EnableAutoConfiguration
public class mainFile {
public static void main(String[] args) {
SpringApplication.run(mainFile.class, args);
}
}
I don't use any beans as configuration, might that be what fails my program?
Thanks again for replies!
I hope I'm not breaking the rules by continuing my question like this, but I didn't know how to bump the old one up.
Ah... The disadvantages of being completely new to a site, heh.
If you're sending JSON in the request body, make it a POST or a PUT request, also add headers to accept json. Fetch the Json as a string and then use a Json parser to parse it to a JsonNode or whatever you want. And at last return a ResponseEntity. Below is a sample code. Do ask specific questions in the comment for clarification if needed.
#RequestMapping(value = "/toggleB", method = RequestMethod.POST, headers = "Accept=application/json")
public ResponseEntity<java.lang.String> sendCommand(#RequestBody String ident) {
// Do your stuff
return new ResponseEntity<String>("Some response data/message",new HttpHeaders(), HttpStatus.OK);
}
I'm using Jersey to provide a java REST service to the outside world. I offer some functions that take JSON and I use the Jackson framework in combination with jersey to convert them into POJOs.
I have the problem that if wrong jackson format is sent to the server, the answer (content of the http response) is a jackson specific exception description. If I have a POJO with an attribute "surname" and send "sursname" in the json string to the server, I get:
Unrecognized field "sursname" (Class XY), not marked as ignorable at [Source: sun.net.httpserver.FixedLengthInputStream#903025; line: 1, column: 49] (through reference chain: XY["sursname"])
Thats quite ok, but I would like to have my own response content, for example my own error code. I already wrote a custom ExceptionMapper that should map all Throwables.
#Provider
public class WebserviceExceptionMapper implements ExceptionMapper<Throwable> {
#Override
public Response toResponse(Exception e) {
e.printStackTrace();
return Response.status(400).entity("{\"errorcode\":\"CRITICAL_ERROR\"}").type(MediaType.APPLICATION_JSON).build();
}
}
It seems that the jackson exception is thrown before my webservice method is called, so i have no chance to map it?
Does anyone have an idea? Big thanks und sorry for my english ;)
The reason that your custom ExceptionMapper doesn't catch the exceptions is because the Jackson library provides its own exception mappers, which catches the exception before it would be catched by your genereal exception mapper.
Some suggest that you should implement your own exception mappers for JsonParseExceptionMapper and JacksonMappingExceptionMapper, but that, however, will give inconsistent results. See this issue on their GitHub.
To solve this problem, you must make sure that none of the built-in exception mappers are registered. If you're using the jackson-jaxrs-providers library for JSON: jackson-jaxrs-json-provider, make sure that you are only registering either JacksonJaxbJsonProvider.class or JacksonJsonProvider.class in your Application class:
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(JacksonJaxbJsonProvider.class)
}
}
Be aware of the JacksonFeature.class, as it registers the built in ExceptionMappers. Also stay away from the jersey-media-json-jackson library, which automatically will add some built in exception mappers, without you having to do anything at all.
I ran into a similar issue a while back while using Jackson and Apache CXF. The exception mappers weren't called if the exception didn't happen in my JAX-RS method and instead happened in the JacksonJsonProvider. The solution in my case was to extend JacksonJsonProvider, catch the specific Jackson json exceptions, and rethrow them as WebApplicationException.
Here's my overriden readFrom method for my extended JacksonJsonProvider:
#Override
public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException {
try {
return super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream);
} catch (JsonParseException jpe) {
throw new WebApplicationException(jpe, Response.status(Status.BAD_REQUEST)
.entity(new ErrorEntity("Malformed json passed to server: \n" + jpe.getMessage())).build());
} catch (JsonMappingException jme) {
throw new WebApplicationException(jme, Response
.status(Status.BAD_REQUEST)
.entity(new ErrorEntity("Malformed json passed to server, incorrect data type used: \n"
+ jme.getMessage())).build());
}
}
Of course Jackson exception is thrown before: the Jackson provider is called in order to create an object you are expecting in your method. However, with ExceptionMapper you should be able to map not only your exceptions, but also the providers exception.
Are you sure your provider is registered? Does it being called if your throw exception from your method and not from provider?
If the answer to the previous question is "yes", try to implement ExceptionMapper for a concrete exception instead of Throwable.
I had the same problem and solve overriding the ExceptionMapper. Perfect! One extra thing that I needed to do and were not understanding 100% was how to override the JacksonProvider for my application (I don't know if it was related to Jersey's version that I was using - 2.19). Here's my web.xml part that overrides it:
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider
</param-value>
Thanks for your help, an ExceptionMapper for JsonParseException didn't help. I removed the jackson jar files from my projekt and included the jackson sources. Then I modified ord.codehaus.jackson.jaxrs.JsonParseExceptionMapper and JacksonMappingExceptionMapper to return my custom response content. I'm not happy with it, but it works now!
Thanks for your help!