I have some webservices that are developed on axis 1.1, and I need to make a few changes. During this I am fixing up the exception handling code, but I don't know what kind of exception I should throw when there is an error.
I only need to send the message to the client, I don't need to worry about stack traces and custom information in the exceptions. I don't want to deal with extending soapfaults, or providing reasons for the failures, and all that jazz.
#WebMethod
public string[] myMethod() throws ..?.. {
throw new AxisFault(); // not recommended
throw new SOAPFaultException(); // seems overly general
throw new Exception(); // what we have now
}
Is there any right way to do this, or is throw new Exception the right way to go about it?
You may create a custom exception (say FooException) extending Exception annotated with JAX-WS #WebFault.
#WebFault(faultBean = "org.foo.bar.FooFault")
public class FooException extends Exception {
private FooFault fooFault;
public FooException() {
super();
}
public FooException(String message, FooFault fooFault, Throwable cause) {
super(message, cause);
this.fooFault = fooFault;
}
public FooException(String message, FooFault fooFault) {
super(message);
this.fooFault = fooFault;
}
public FooFault getFaultInfo() {
return fooFault;
}
}
// this is org.foo.bar.FooFault
public class FooFault {
// POJO
}
And then you declare that your web method throws that exception.
#WebMethod
public string[] myMethod() throws FooException {
// do some stuff
throw new FooException();
// or with a cause
try {
// something dangerous
} catch (Exception e) {
throw new FooException("Shit happens", new FooFault(), e);
}
// or like this
throw new FooException("Foo", new FooFault());
}
JAX-WS should do the rest.
Related
I am working on Spring Boot 2 to create a microservice. I have a requirement to create an After aspect to execute some piece of code.
#Aspect
#Component
public class FinallyAspect {
#Pointcut("#annotation(finallyEvent)")
public void runFinallyMethod(FinallyEvent finallyEvent) {}
#After("runFinallyMethod(FinallyEvent finallyEvent)")
public void finallyMethod(JoinPoint joinPoint, FinallyEvent finallyEvent) throws Throwable {
// ...
}
}
Is it possible to get inside finallyMethod whether an exception has occurred or the method returned successfully? I can do it with #AfterReturning and #AfterThrowing annotation, but if there is a way to check if the method has ended in error or success then I can check it in a single function.
It is not possible with After-advice to access whether the method returned successfully or with an exception. There are alternatives...
a) Around-advice (not recommended)
What you want can be manually implemented with a single method using the Around-advice, the most general kind of advice. It is recommended that you use the least powerful advice type that can implement the required behaviour (source). I do not recommend this approach as it can be error-prone in terms of exception handling if implemented the wrong way. For example, if you put your success-code in the try-block, exceptions thrown by this success-code are also caught by the same catch-block as is used for the failure-code. Also, you need to make sure to re-throw the exception and to return the return value of joinPoint.proceed().
This is how could do this properly if you wanted to:
#Around(value = "runFinallyMethod(finallyEvent)", argNames = "joinPoint,finallyEvent")
public Object finallyMethod(ProceedingJoinPoint joinPoint, FinallyEvent finallyEvent) throws Throwable {
final Object res;
try {
res = joinPoint.proceed();
} catch (Throwable e) {
// code in case of failure
throw e;
}
// code in case of success
return res;
}
b) Clean solution with private method
In this case, I suggest to use AfterReturning-advice and AfterThrowing-advice and then call a private method with a parameter indicating success/error. This is much more readable, does not have the drawbacks of the Around-advice but uses a bit more code.
A boolean (success) is needed
#AfterReturning(value = "runFinallyMethod(finallyEvent)", argNames = "joinPoint,finallyEvent")
public void finallyMethodReturning(JoinPoint joinPoint, FinallyEvent finallyEvent) throws Throwable {
finallyMethod(joinPoint, finallyEvent, true);
}
#AfterThrowing(value = "runFinallyMethod(finallyEvent)", argNames = "joinPoint,finallyEvent")
public void finallyMethodThrowing(JoinPoint joinPoint, FinallyEvent finallyEvent) throws Throwable {
finallyMethod(joinPoint, finallyEvent, false);
}
private void finallyMethod(JoinPoint joinPoint, FinallyEvent finallyEvent, boolean success) throws Throwable {
if (success) {
// code in case of success
} else {
// code in case of failure
}
}
The Throwable is needed
#AfterReturning(value = "runFinallyMethod(finallyEvent)", argNames = "joinPoint,finallyEvent")
public void finallyMethodReturning(JoinPoint joinPoint, FinallyEvent finallyEvent) throws Throwable {
finallyMethod(joinPoint, finallyEvent, null);
}
#AfterThrowing(value = "runFinallyMethod(finallyEvent)", throwing = "t", argNames = "joinPoint,finallyEvent,t")
public void finallyMethodThrowing(JoinPoint joinPoint, FinallyEvent finallyEvent, Throwable t) throws Throwable {
finallyMethod(joinPoint, finallyEvent, t);
}
private void finallyMethod(JoinPoint joinPoint, FinallyEvent finallyEvent, Throwable t) throws Throwable {
if (t == null) {
// code in case of success
} else {
// code in case of failure
}
}
I don't think you will be able to implement this using #After as this annotation can only give you the JoinPoint in context, which has no information about return values.
If you want to handle everything within the same method I think the only alternative is to implement this using #Around, where you can do something before and after a method execution. Your implementation could be:
#Around("runFinallyMethod(FinallyEvent finallyEvent)")
public Object finallyMethod(ProceedingJoinPoint jp, FinallyEvent finallyEvent) throws Throwable {
try {
Object result = jp.proceed();
// do nice stuff with result
return result;
} catch(Throwable throwable) {
// do nice stuff with the exception;
throw throwable;
}
}
I have a custom exception class as shown below;
public class DataSendingError extends Exception {
private static final long serialVersionUID = 1L;
public DataSendingError() {
super();
}
public DataSendingError(String errors) {
super(errors);
}
}
PFB the exception handler class:
#ExceptionHandler(DataSendingError.class)
public ResponseEntity<ErrorMessage> DataSendingErrorCase(DataSendingError ex) {
System.out.println("inside datasend");
ErrorMessage error = new ErrorMessage();
error.setErrorCode(HttpStatus.NOT_FOUND.value());
error.setMessage(ex.getMessage());
return new ResponseEntity<>(error,HttpStatus.NOT_FOUND);
}
#ExceptionHandler(Exception.class)
public ResponseEntity<ErrorMessage> exceptionHandler2(Exception ex) {
System.out.println("inside common");
ErrorMessage error = new ErrorMessage();
error.setErrorCode(HttpStatus.NOT_FOUND.value());
System.out.println("mesage"+ex.getMessage());
error.setMessage(ex.getMessage());
return new ResponseEntity<>(error,HttpStatus.NOT_FOUND);
}
But when I throw a datasending exception, the control is not going inside custom exception but it is going to Exception.class. and e.getmesaage is coming as null.I am throwing the message as shown below:
throw new DataSendingError("Error in processing the request either service is down or invalid input
Is I am doing anything wrong here. Please help me out on this.
Assuming all your exception handlers are in a separate class, is it annotated with #RestControllerAdvice?
I have a Spring Boot application that has the following approximate structure:
project
Api
ApiImpl
Application
Api is an interface that looks like this:
public interface Api {
public String methodOne(...) throws ExceptionOne, ExceptionTwo, ExceptionThree;
...
public int methodN(...) throws ExceptionOne, ExceptionThree, ExceptionFour;
}
ApiImpls is the request controller (in reality there is a second layer, but this should suffice for this example). There, I do something like the following right now:
#Controller
public class ApiImpl {
public String methodOne(...) {
try {
// do stuff that can yield an exception
}
catch(ExceptionOne e) {
// set proper response code and return values
}
catch(ExceptionTwo e) {
// set proper response code and return values
}
catch(ExceptionThree e) {
// set proper response code and return values
}
}
}
Basically, this behaviour yields a lot of repetition (might as well name my exceptions D, R, and Y...), but is otherwise very suited to handling the internal application logic.
My question is: How can I implement a custom Exception Dispatcher that would handle this in Java? Ideally, I would want something like this answer here, but unfortunately simply throwing the current exception like in that C++ code is not possible in Java, as far as I know. For brevity, what I would like to accomplish is something like the following:
#Controller
public class ApiImpl {
public String methodOne(...) {
try {
// do stuff that can yield an exception
}
catch(ExceptionOne e) {
handle()
}
}
private void handle() { // maybe Throwable or Exception subclass as parameter
// handle the correct exception type, set correct response code, etc.
}
}
Are there any good approaches to doing this so as to minimize code repetition?
Here is a preliminary attempt I tried to get this working:
public class Thrower {
public Thrower(int e) throws ExceptionOne, ExceptionTwo, ExceptionThree {
if(e == 0) {
throw new ExceptionOne();
}
if(e == 1) {
throw new ExceptionTwo();
}
if(e == 2) {
throw new ExceptionThree();
}
}
}
class ExceptionOne extends Exception {}
class ExceptionTwo extends Exception {}
class ExceptionThree extends Exception {}
public class ExceptionHandler {
private void handle(Exception ex) throws Exception {
try {
throw ex;
}
catch(ExceptionOne e) {
e.printStackTrace();
System.out.println("Exception one");
}
catch(ExceptionTwo e) {
e.printStackTrace();
System.out.println("Exception two");
}
catch(ExceptionThree e) {
e.printStackTrace();
System.out.println("Exception three");
}
}
public void causesException(int which) throws Throwable {
try {
Thrower t = new Thrower(which);
}
catch(Exception e) {
handle(e);
}
}
public static void main(String[] args) throws Throwable {
ExceptionHandler eh = new ExceptionHandler();
eh.causesException(0);
eh.causesException(1);
eh.causesException(2);
}
}
This works as expected, and I can handle the different exception types as needed (shown here using a constructor, but the principle would be the same). However, this feels extremely clunky.
If you are looking for globally handling all Controller Layer exceptions (in Spring MVC architecture), you can do that at one place for all controllers (option1 below) by using #ExceptionHandler methods which is a ControllerAdvice from Spring.
Option(1): Configure Exceptions in Separate Class
#ControllerAdvice
class MyProjectExceptionHandler {
#ExceptionHandler(value = ExceptionOne.class)
public R exceptionOne(ExceptionOne exe) {
//set proper response code and return values
}
#ExceptionHandler(value = ExceptionTwo.class)
public R exceptionTwo(ExceptionTwo exe) {
//set proper response code and return values
}
}
Option(2): Configure Exceptions in Controller Class itself
If you are looking for handling the exceptions within the Controller class itself, then you can do that as below:
#Controller
public class ApiImpl {
public String methodOne(...) {
}
#ExceptionHandler(ExceptionOne.class)
public R exceptionTwo(ExceptionOne exe) {
//set proper response code and return values
}
//other exceptions
}
You can look more on this at here
I found below code for exception handling which handles all execptions of thrown by application including runtimes.
public static void handleException(String strMethodName,
Exception ex) throws CustomException{
String strMessage = "";
try {
throw ex;
}
catch (NullPointerException npe){
logger.log(pr, strMethodName, npe.getMessage());
strMessage=ERR_02;
throw new CustomException(strMessage);
}
catch(IndexOutOfBoundsException iobe) {
logger.logMethodException(strMethodName,iobe.getMessage());
strMessage=ERR_03;
throw new CustomException(strMessage);
}
... So On
}
Below are some of the disadvantages that I think:
To idenitify root cause of the exception we will need to always check for the Message string.
No sepearation of type of exceptions
Advantage:
Less code. (Code can be minimized)
Can you please let me know whether I should go with such mechanism or not.
Not sure of the circumstances which you are using the code.
In your approach, you are not rethrowing the exception object which may be used for debugging
public static void handleException(String strMethodName,
Throwable th){
String strMessage = "";
try {
throw th;
}
catch (Throwable thr){
logger.log(pr, strMethodName, npe.getMessage());
//get the appropriate error code from a method
strMessage=getErrorCode();
throw new CustomException(strMessage, th);
//CustomException is of type RuntimeException
}
}
By catching and "THROWING" the Throwable object you are sure that even errors are handled properly. [It is important not to suppress the Throwable object]
I have made the WSDL from java code using the Xfire framework,
Here is my java code..
public class Test implements TestException {
public void testException(String check) {
List<String> list = new ArrayList<String>();
list.add("ABC");
list.add("XYZ");
list.add("PQR");
list.add("LMNOP");
list.add("EFGH");
list.add("Pqrst");
try
{
if(check(list,check))
System.out.println(check);
}
catch (MyException e)
{
e.printStackTrace();
}
}
public boolean check(List<String> list,String check) throws MyException {
if(list.contains(check))
return true;
else
throw new MyException();
}
}
The exception class is :
public class MyException extends Exception {
public MyException()
{
}
public String toString()
{
return "Exception by My Exception.....";
}
}
*The flex code : *
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" minWidth="955" minHeight="600">
<mx:WebService id="testService" wsdl="http://localhost:9090/ExceptionTest/xfire/Test?wsdl" showBusyCursor="true">
<mx:operation name="testException" result="testExceptionRH(event)" fault="testExceptionFH(event)"/>
</mx:WebService>
<mx:Script>
<![CDATA[
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
protected function click_clickHandler(event:MouseEvent):void
{
testService.testException(showText.text).send;
}
protected function testExceptionRH(event : ResultEvent) : void
{
messageLbl.text = "No Exception.....!!!!";
}
protected function testExceptionFH(event : FaultEvent) : void
{
trace(event.fault.faultDetail);
messageLbl.text = "Exception.....!!!!";
}
]]>
</mx:Script>
<mx:Button x="163" y="70" label="Click" id="click" click="click_clickHandler(event)"/>
<mx:TextInput x="114" y="27" id="showText"/>
<mx:Label id="messageLbl" fontWeight="bold" x="183" y="99"/>
Now the problem is whenever i am send the object other than object in list say "Amit" then it throw exception right, & so the fault message has to displayed but i am getting always the result handler message, I have check the logs of tomcat it shows exception (MyException) stack trace,
What wrong i am doing ..???
Please help, Thanks in Advance
you already caught the exception in your testException method so it was not propagated to your flex front end.
you should handle the exception (e.g. do your logging) in your catch block then throw it again.
try {
// do work...
} catch (Exception e) {
// handle exception
e.printStackTrace();
// include the root cause and propagate the exception to flex
// using RuntimeException as an example)
throw new RuntimeException("error msg here", e);
}