I am currently using gwt-resty and jersey for the server side. The problem I have run into is how do I map an exception for the MethodCallback implementation. I have created an ExceptionMapper which converts the exception to json and returns it in json format but the onFailure method is giving me the generic error message for my exception, "Failed BAD Request"
The question is how do I convert the exception into something that gwt-resty can process the exception in order to get the message from the server side exception.
Here is my service implementation
service.getCurrentAddress("123456", new MethodCallback<Address>() {
#Override
public void onSuccess(Method method, Address response) {
Window.alert("Got your address" + response);
}
#Override
public void onFailure(Method method, Throwable e) {
GWT.log("failed", e);
GWT.log("Failed " + e.getMessage());
}
});
}
Here is my exception mapper.
#Provider
public class VendorExceptionMapper implements ExceptionMapper<Exception> {
#Override
public Response toResponse(Exception exception) {
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON).entity(exception).build();
}
}
I am not sure I understood your question but I think that you can parse Throwable e to get your exception in case of failure.
You can also intercept your exception by coding a restyGWT dispatcher and treat it before entering the onFailure().
Related
I am using ReplyingKafkaTemplate to establish a synchronous call between two microservices.
The receiver of the event is annotated with SendTo as below:
#KafkaListener(topics = "${kafka.topic.prefix}"
+ "${kafka.topic.name}", containerFactory = "customEventKafkaListenerFactory")
#SendTo
public CustomResponseEvent onMessage(
#Payload #Valid CustomRequestEvent event, #Header(KafkaHeaders.CORRELATION_ID) String correlationId,
#Header(KafkaHeaders.REPLY_TOPIC) String replyTopic) {
//Making some REST API calls to another external system here using RestTemplate
}
The REST API call can throw a 4xx or 5xx. There are multiple such calls, some to internal systems, and some to external systems. It may be a bad design, but let's not get into that.
I would like to have a global exception handler for the RestTemplate where I can catch all the exceptions, and then return a response to the original sender of the event.
I am using the same replyTopic and correlationId as received in the consumer to publish the event.
But still the receiver of the response throws No pending reply exception.
Whatever approach I have above, is it possible to achieve such a central error response event publisher?
Is there any other alternative that is best suited for this exception handling?
The #KafkaListener comes with the:
/**
* Set an {#link org.springframework.kafka.listener.KafkaListenerErrorHandler} bean
* name to invoke if the listener method throws an exception.
* #return the error handler.
* #since 1.3
*/
String errorHandler() default "";
That one is used to catch and process all the downstream exceptions and if it returns a result, it is sent back to the replyTopic:
public void onMessage(ConsumerRecord<K, V> record, Acknowledgment acknowledgment, Consumer<?, ?> consumer) {
Message<?> message = toMessagingMessage(record, acknowledgment, consumer);
logger.debug(() -> "Processing [" + message + "]");
try {
Object result = invokeHandler(record, acknowledgment, message, consumer);
if (result != null) {
handleResult(result, record, message);
}
}
catch (ListenerExecutionFailedException e) { // NOSONAR ex flow control
if (this.errorHandler != null) {
try {
Object result = this.errorHandler.handleError(message, e, consumer);
if (result != null) {
handleResult(result, record, message);
}
}
catch (Exception ex) {
throw new ListenerExecutionFailedException(createMessagingErrorMessage(// NOSONAR stack trace loss
"Listener error handler threw an exception for the incoming message",
message.getPayload()), ex);
}
}
else {
throw e;
}
}
See RecordMessagingMessageListenerAdapter source code for more info.
I have the following:
The "400 Bad request" is converted to a ResourceAccessException in Spring.
Is there any way to retrieve the payload here? I want to send the "errorMessage" further up the call chain.
Code-wise the following is used to do the request:
public <T> T post(String url, Object request, Class<T> className) {
try {
return logEnhancedRestTemplate.postForObject(url, request, className);
} catch(RestClientException ex) {
throw handleErrors(ex, url);
}
}
It is in the "handleErrors" method I want to use the "errorMessage" from the body.
If you want to retrieve the message of an exception use the method getMessage().
In your specific example maybe is better if you catch a generic exception, since I suppose that every type of Runtime exception should call your method handleErrors(ex, url).
If this is the case, I suggest you to modify your code with:
public <T> T post(String url, Object request, Class<T> className) {
try {
return logEnhancedRestTemplate.postForObject(url, request, className);
} catch(Exception ex) {
throw handleErrors(ex, url);
}
}
spring-data: how to intercept to return api/application specific error messages for 4xx, 5xx?
Spring-data-rest:
Without using a spring controller, I don't find a way to intercept the sql errors/exceptions and return more meaningful messages to the API callers.
You can use exception handlers, for example:
#ControllerAdvice
public class ExceptionsHandler {
#Order(Ordered.HIGHEST_PRECEDENCE)
#ExceptionHandler(DataIntegrityViolationException.class)
public ResponseEntity<?> conflict(DataIntegrityViolationException e) {
return new ResponseEntity<>(new errorMsg(e.getRootCause().getMessage()), CONFLICT);
}
...
#Order(Ordered.HIGHEST_PRECEDENCE + 4)
#ExceptionHandler(NotFoundException.class)
public ResponseEntity<?> handleNotFoundException(NotFoundException e) {
return new ResponseEntity<>(new errorMsg(e.getMessage()), NOT_FOUND);
}
...
#Order(Ordered.LOWEST_PRECEDENCE)
#ExceptionHandler(Exception.class)
public ResponseEntity<?> handleException(Exception e) {
return new ResponseEntity<>(new errorMsg(e.getMessage()), INTERNAL_SERVER_ERROR);
}
}
Useful resources:
Spring Boot - Error Handling
Exception Handling in Spring MVC
Error Handling for REST with Spring
I am new to Camel and am facing an issue with a route I need to setup. It will be great if someone can either guide me to the correct forum or better still rectify the issue I am facing.
Here is what I need to do - expose a restlet endpoint to accept data; use this data as input to an external SOAP web service and send back the response in JSON format back to the caller...
Here is what I have done...however, I am getting the following error while Camel tries to call the Web Service...can anyone guide me here? Thanks.
I am using camel 2.11.1 and cxf-codegen-plugin version 2.7.11
I am getting the following exception: org.restlet.data.Parameter cannot be cast to java.lang.String.
public class IntegrationTest extends CamelTestSupport {
String restletURL = <url>;
#org.junit.Test
public void integTest() throws Exception {
//trying to simulate the rest service call...
template.sendBodyAndHeader(restletURL, "Body does not matter here", "data", "{\"FromCurrency\":\"AUD\",\"ToCurrency\":\"USD\"}");
}
#Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
System.out.println("In Counfigure");
String cxfEndpoint = "cxf://http://www.webservicex.net/CurrencyConvertor.asmx?"
+ "wsdlURL=http://www.webservicex.net/CurrencyConvertor.asmx?wsdl&"
+ "serviceName={http://www.webserviceX.NET/}CurrencyConvertor&"
+ "portName={http://www.webserviceX.NET/}CurrencyConvertorSoap&"
+ "dataFormat=MESSAGE";
XmlJsonDataFormat xmlJsonFormat = new XmlJsonDataFormat();
SoapJaxbDataFormat soap = new SoapJaxbDataFormat("net.webservicex", new ServiceInterfaceStrategy(CurrencyConvertorSoap.class, true));
GsonDataFormat gson = new GsonDataFormat(ConversionRate.class);
gson.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE);
from(restletURL).routeId("Restlet")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
String data = (String) URLDecoder.decode((String) exchange.getIn().getHeader("data"), "UTF-8");
System.out.println(data);
// get the mail body as a String
exchange.getIn().setBody(data);
Response.getCurrent().setStatus(Status.SUCCESS_OK);
}
})
.unmarshal(gson)
.marshal(soap)
.log("${body}")
.to(cxfEndpoint)
.unmarshal(soap)
.marshal(xmlJsonFormat);
.log("${body}");
}
};
}
}
However, the sample works when I try out the individual pieces - restlet alone and CXF alone...
Thanks,
Ritwick.
Sure Willem, here is the entire configure implementation:
#Override
public void configure() throws Exception {
String restletURL = "restlet:http://localhost:8080/convert/{data}?restletMethods=get";
String cxfEndpoint = "cxf://http://www.webservicex.net/CurrencyConvertor.asmx?"
+ "portName={http://www.webserviceX.NET/}CurrencyConvertorSoap&"
+ "dataFormat=MESSAGE&loggingFeatureEnabled=true&defaultOperationName=ConversionRate&defaultOperationNamespace={http://www.webserviceX.NET/}&synchronous=true";
SoapJaxbDataFormat soap = new SoapJaxbDataFormat("net.webservicex", new ServiceInterfaceStrategy(CurrencyConvertorSoap.class, true));
soap.setVersion("1.2");
GsonDataFormat gson = new GsonDataFormat(ConversionRate.class);
gson.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE);
from(restletURL).routeId("Restlet")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
String data = (String) URLDecoder.decode((String) exchange.getIn().getHeader("data"), "UTF-8");
exchange.getIn().setHeader("org.restlet.http.headers", "");
exchange.getIn().setHeader("data", "");
exchange.getIn().setBody(data);
Response.getCurrent().setStatus(Status.SUCCESS_OK);
}
})
.unmarshal(gson)
.marshal(soap)
.to(cxfEndpoint)
.unmarshal(soap)
.marshal(gson)
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
String output = exchange.getIn().getBody(String.class);
exchange.getOut().setBody(output);
}
});
}
The issue I was facing has been resolved. In addition to "exchange.getIn().setBody(data);", I added the following line of code "exchange.getIn().setHeader("org.restlet.http.headers", "");" in order to get rid of the class cast exception I was getting. The restlet headers were causing this issue and once these headers were removed (I didn't need the headers in the first place), everything worked as expected.
Thanks,
Ritwick.
I'm using GWT and Resty for my web app.
I need to treat two exceptions as special cases and pass additional information to the client. These previously were handled by the Resty calls onFailure() method, as follows:
getClientFactory().getRequest().restyMethod(id,
new MethodRecipient<DataDTO>() {
#Override
public void onSuccess(Method method, DataDTO response) {
// do stuff
}
#Override
public void onFailure(Method method, Throwable ex) {
if (ex.getMessage().endsWith("exception message 1")) {
getClientFactory().getAppController().showRestFatalError("Message 1", "Title 1", errorMsg);
} else if (ex.getMessage().endsWith("exception message 2")) {
getClientFactory().getAppController().showRestFatalError("Message 2", "Title 2", errorMsg);
} else {
// else fall back to a friendly but vague "something else went wrong"
getClientFactory().getAppController().showRestFatalError("Unexpected error", "Unexpected Error", errorMsg);
}
}
});
To catch and log all exceptions before they get to the client, I've implemented a custom Spring MVC HandlerExceptionResolver as follows:
I have a custom HandlerExceptionResolver for logging controller errors as below:
#Component
public class LoggingHandlerExceptionResolver extends AbstractHandlerExceptionResolver {
private final Logger logger = LoggerFactory.getLogger(LoggingHandlerExceptionResolver.class);
#Override
public ModelAndView doResolveException(HttpServletRequest aReq, HttpServletResponse aRes, Object aHandler, Exception ex) {
logger.error("Server exception thrown", ex);
return null; // trigger other HandlerExceptionResolvers
}
}
When using the HandlerExceptionResolver, only status code 500 gets passed to the client. How do I get the two special cases to be recognized by the onFailure() method?