JAX-RS exception handling - rest

I'm relatively new to REST services in Java. I've created one and everything works fine except error handling. If I make a request with incorrectly formed JSON in it, Jackson JSON processor throws an exception which I unable to catch and I get error 500 in client. Exception follows:
javax.ws.rs.InternalServerErrorException: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.HashSet out of VALUE_STRING token
I have no idea how to handle exceptions raised outside my code.
Google suggests using Exception Mappers or Phase Inteceptors. Though I could miss something in search results.
What is the proper way to handle such situations?
Please, advise something. I'm stuck with this problem...

A JAX-RS ExceptionMapper should do the job. Just add a class like below to your code and if you have the exception type right, then you should get the hook to customize the handling.
#Provider
public class MyExceptionMapper implements ExceptionMapper<MyException> {
#Override
public Response toResponse(MyException ex) {
return Response.status(Response.Status.BAD_REQUEST).build();
}
}

Related

Spring Annotation: replacing #ControllerAdvice

I'm tasked with removing functionality given by #ControllerAdvice(basePackages = {"com.bla.controller"}) located in an old applications. This functionality became outdated, creating some unexpected error handling issues, after another "global" functionality utilizing #ControllerAdvice got installed by a separate team.
While this "global" functionality covers most needs, the old application still has a need for custom error handling, but without #ControllerAdvice.
My knowledge of Spring Annotations is very limited, and I'm hoping that someone may have a good idea what can be used instead so that the old application would have awareness where to send errors for error handling.
Here is an implementation sample from the file utilizing #ControllerAdvice(basePackages = {"com.bla.controller"}) notation showing both custom and basic usage in the old application:
#ResponseStatus(HttpStatus.NOT_FOUND)
#ExceptionHandler(ResourcePageException.class)
public String notFound(Model model, ResourcePageException exception) {
setAttributes(model);
populateModel(model, exception);
return Mapping.NO_RESULTS_VIEW;
}
#ResponseStatus(HttpStatus.NOT_FOUND)
#ExceptionHandler(NoCustomSearchResultsRestException.class)
public ResponseEntity<Object> locationLookupRestError(NoCustomSearchResultsRestException exception) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getModel());
}
So far I wasn't able to find a way to move all of the #ExceptionHandler methods into a single place without the use of #ControllerAdvice, but I did find this page summarizing Spring's error handling that I found useful in terms of understanding error handling by Spring: Using Spring Boot's ErrorController and Spring's ResponseEntityExceptionHandler correctly

How to know which RestController is throwing a global exception?

I have a Spring Boot application with multiple RestControllers, each of them connecting to different databases based on the services they are calling.
If any of them can't connect to the database for whatever reason, I'm throwing a message stating so like this:
#RestController
#RestControllerAdvice
public class GlobalExceptionHandler {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
// The Network Adapter could not establish the connection
#ExceptionHandler(value = SQLRecoverableException.class)
public ResponseEntity<String> handleBaseException(Exception e) {
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).body("Service Unavailable.");
}
}
Now, is it possible to identify which RestController triggered this exception?
I don't know how to connect a Global Exception to a Rest Controller when I'm using #RestControllerAdvice
Spring provide two level of Exception handling,
1. Controller level.
2. Global level.
Use controller level exception handling, If you need to add something based on controller basis.
Global level handling meant to be handle exception irrespective of knowing which controller exception belongs to.
Hope this answers your question. Better to go for controller level exception handing in your case.
Comment if you need more information.

How to check whether SOAP fault is being handled gracefully?

I'm using JUnit and Mockito in order to test whether my SOAP web service handles SOAP faults gracefully and doesn't throw any unwanted exceptions for example.
So up until now, as you can see from the code below, I'm only testing whether a SOAPFaultException is being thrown (of course it does, I threw it). I wonder how I could check though whether any other exception would be thrown when receiving the SOAP fault.
Also is there any way to mock a SOAP fault without throwing an exception (SOAPFaultException)?
public class SOAPFaultsTest {
private MyObj myObj = (MyObj) mock(IMockClass.class);
#Before
public void create() {
SOAPFault soapFault = null;
try {
soapFault = SOAPFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL).createFault();
soapFault.setFaultString("unable to create new native thread");
soapFault.setFaultCode(QName.valueOf("soap:Server"));
} catch (SOAPException e) {
e.printStackTrace();
}
// Define behaviour of myObj mock object
when(myObj.randomMethod(any(RandomClass.class))).thenThrow(new SOAPFaultException(soapFault));
}
// Here I'm testing whether invoking myObj's randomMethod with a RandomClass object as an argument throws a SOAPFaultException.
// It does because this is how I defined its behaviour.
// What I really want to test is whether receiving a SOAP fault at any time is going to cause any trouble.
#Test(expected=SOAPFaultException.class)
public void testSOAPException() throws SOAPFaultException {
RandomClass rc = new RandomClass();
myObj.randomMethod(rc);
}
}
I suggest you go with a full-stack mock (i.e. spawn an Endpoint on a local socket, point the client there). Then create a soap fault and let the mock throw an appropriate exception over the wire. If you're using CXF, I've created a simple JUnit Rule which does this, see the test method SoapServiceRuleTest.processSoapCallWithException().
As a general strategy, I suggest you make an abstract 'happy case' unit test which you then sabotage one call at a time by doing reset on the mock with each test method and adding thenThrow(..) correspondingly.

Best way to handle constraint violations when using EJB 3.0 and CMP

I have a web service (built using jaxb/jaxws) that invokes a stateless EJB to store some data in the database. The data is being stored as an entity bean. The entity bean has a unique constraint applied to it via the #Column(unique = true) annotation.
When the web service attempts to save data, the transaction fails, and rightfully so. The problem is that since I am using CMP, the transaction is not committed until after the call to the stateless EJB. The end result is that I am not able to trap the exception and it is getting funneled up to the WS stack and results in an ambiguous fault containing the string: Error committing transaction:;nested exception is: weblogic.transaction.internal.AppSetRollbackOnlyException.
Is there a way to catch the exception being thrown so I can provide more information to the caller? Thank you.
Version information:
Application Server: Oracle Weblogic 10.3
Persistence Provider: Hibernate 3.2.5.ga (JPA 1.0)
JDK/JRE: 1.6_0_05 (provided by Weblogic install)
Update:
I tried to implement an EJB 3 interceptor around the method invocation and this does not appear to work.
public class TestInterceptor {
#AroundInvoke
public Object logCall(InvocationContext context) throws Exception {
System.out.println("Invoking method: " + context.getMethod().getName());
try {
return context.proceed();
} catch (Throwable t) {
System.out.println("I caught an exception: " + t.getMessage());
throw new Exception(t);
}
}
The reason I think this doesn't work is because the processing chain is such that the actual persist happens outside of the method (of course).
You could try using Bean Validation. It's nicely connected with the JPA (invoked during pre-persist, pre-update and pre-remove phases and can be used in different layers of your application.
Unfortunately, as far as I know, if a validation constraint violation occurs, the transaction is marked for rollback... I don't know how you could cope with that but one (seems nasty and untested) way I could think of is to inject a ValidatorFactory and validate the object by yourself. Perhaps then you could catch the ValidationException.
EDIT: I'm not sure if the Bean Validation was available in Java EE 5.
EDIT 2: You can create an interceptor which will catch the exception thrown by the JPA (or more precisely by the database). As the interceptor is invoked as a part of the same transaction as the EJB method you might need to explicitly invoke EntityManager#flush(-) to synchronise changes with the database.

GWT RequestContext ENum in the request

If we use enum as one of the attribute in the Request invocation , it throws an UnsupportedOpeationException and does not even invoke the service method on the server.
#Service(value = DesignService.class, locator = DesignServiceLocator.class)
public interface DesignRequest extends RequestContext {
Request<List<DesignProxy>> findDesign(SortEnum sortorder);
}
when we invoke the designRequest.findDesign(sortorderEnum).fire() the UnsupportOperationException is thrown on the javascript console on chrome dev tools/Firebug console.
Looks like it is related to Issue 6504, which will throw an UnsupportedOperationException if it fails to find the type you are using - consider trying to change to class methods in your enum, or wait until 2.4 is released.
If you are not using anonymous enum instances, can you post more info about this error, such as where the exception is thrown from?