How to handle custom exceptions in Spring Aspect class? - java

I need to know how can i handle custom exceptions in my Aspect class, so that i can print log out of it?
Below is my Aspect class:
#Around("#annotation(com.aspect.LoggableService)")
public Object ServiceMetrices(ProceedingJoinPoint pjp) throws Throwable {
try {
pjp.proceed();
} catch(CustomException ex) {
// logging exception details here
LOGGER.info("Logs for API Metrices " + pjp.getSignature() + " {} " +
return pjp.proceed();
} catch (Exception ex) {
// Logging exception details
LOGGER.info("Logs for API Metrices " + pjp.getSignature() + " {} " +
return pjp.proceed();
}
I am calling this aspect annotation after the execution from my service class.
try {
//Code
}
catch(HttpClientErrorException x) {
throw new CustomException(x.getStatusCode(),"POST Request failed");
}
I want my exceptions to be handled by my CustomException block in my Aspect class instead of handling it in Exception class.

Related

How to handle Transaction timeout with #TransactionTimeout

I do have method:
#TransactionTimeout(value = 1, unit = TimeUnit.SECONDS)
#Asynchronous
public void asyncMethod() {
System.out.println("start running asyncMethod in thread " + Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("finished running asyncMethod in thread " + Thread.currentThread().getName());
}
As you can see I running this in Transaction and timeout is set to 1 second and inside I have 3 second sleep. So as a result of running this method I am gettin:
javax.transaction.RollbackException
But let say I would like to implement service which will print information that transaction timeout has occured to the user. How could I achieve that?
#Glains gave me some advice in comment to use Interceptor.
I have added something like that:
#Interceptor
public class LoggingTimeoutInterceptor {
#AroundInvoke
public Object log(InvocationContext ctx) throws Exception {
try {
System.out.println("Logger interceptor");
System.out.println("method " + ctx.getMethod().getName());
return ctx.proceed();
}catch (RollbackException e) {
System.out.println("Transaction RollbackException occured");
return null;
}
catch (Exception e) {
System.out.println("Exception occured");
return null;
}
}
}
This code is writing first two sysout correctly. But is not catching any exception and I dont know why. I was trying to change #AroundInvoke to #AroundTimeout but then it is not running at all.

How to customize the error message for NoSuchElementException in Optional class

I have a method that throws NotFoundException if my object id is null.
public void removeStatementBundleService(String bundleId) throws NotFoundException {
Optional<StatementBundle> bundleOpt = statementBundleRepository.findById(bundleId);
if(bundleOpt.isPresent()) {
StatementBundle bundle = bundleOpt.get();
if(bundle.getStatements() != null && !bundle.getStatements().isEmpty()) {
for(Statement statement: bundle.getStatements()) {
statementRepository.delete(statement);
}
}
if(bundle.getFileId() != null) {
try {
fileService.delete(bundle.getFileId());
} catch (IOException e) {
e.printStackTrace();
}
}
statementBundleRepository.delete(bundle);
} else {
throw new NotFoundException("Statement bundle with id: " + bundleId + " is not found.");
}
}
I found out that this isn't needed since the java.util.Optional class is used. In the oracle documentation I found out that if get() is used and there is no value then NoSuchElementException is thrown. What is the best way I can add my error message to the exception. I am trying to open the Optional class in Eclipse to try change inside it(not sure if this is good practice) but Eclipse will not let me access this class on the other hand I read that this class is also final.
When resolving the Optional value, you can directly throw an Exception if the value is not present:
Optional<StatementBundle> bundleOpt = statementBundleRepository.findById(bundleId);
StatementBundle bundle = bundleOpt.orElseThrow(()
-> new NotFoundException("Statement bundle with id: " + bundleId + " is not found.");
or (single statement):
StatementBundle bundle = statementBundleRepository.findById(bundleId)
.orElseThrow(()
-> new NotFoundException("Statement bundle with id: " + bundleId + " is not found.");
The Optional class does provide a orElseThrow(...) method which takes a Supplier as it's only parameter and therefore allowing us to throw custom exception in case the value is absent.
This enables expressions like:
StatementBundle bundle = bundleOpt.orElseThrow( ()->new NotFoundException("Statement bundle with id: " + bundleId + " is not found.") );
Don't manipulate the NoSuchElementException, wrap it in a custom exception.
try {
try {
// We simulate a failing .get() on an Optional.
throw new NoSuchElementException("message from Optional.get()");
} catch (NoSuchElementException ex) {
// We wrap the exception into a custom exception and throw this.
throw new MyException("my message", ex);
}
} catch (MyException ex) {
// Now we catch the custom exception and can inspect it and the
// exception that caused it.
System.err.println(ex.getClass().getCanonicalName()
+ ": " + ex.getMessage()
+ ": " + ex.getCause().getMessage());
}
Output:
MyException: my message: message from Optional.get()

How to make TestNG continue test execution on an exception?

When i get an exception, the test run immediately ends, and any following test validations are skipped. I would like to catch the exception, handle it, then continue the workflow.
In the below example, If objPage.Method1(); throws an exception, the entire #Test immediately ends. I would like the catch to execute, then move on to objPage.Method2().
#Test (enabled=true)
public void MyClientsFunctions() throws Exception {
ExtentTest t = ReportFactory.getTest();
try {
Login objPage = new PageObject(driver);
//this method throws exception
objPage.Method1();
if (x=y)
t.log(LogStatus.PASS, "Pass message");
else
t.log(LogStatus.FAIL,"Fail message"+ screenshotMethod());
objPage.Method2();
if (a=b)
t.log(LogStatus.PASS, "Pass message");
else
t.log(LogStatus.FAIL,"Fail message"+ screenshotMethod());
} catch (Exception e) {
t.log(LogStatus.ERROR, "Exception found: " + e.getMessage() + screenshotMethod());
}
}
I am using PageFactory and ExtentReports. I am use if statements to report failures. No asserts. I believe if an assert fails, the result is the same, and the test ends.
Write the objPage.Method2() in final block then it will execute.
Credit to #JeffC for pointing me in the right direction.
For my case, I have at least a dozen action methods called from the Page Object class. I can't put them all in their own final block.
What I did was put each workflow (one or more methods, then validation) in it's own try/catch. The catch includes logging/screenshot, then redirects to the page that the next workflow needs to execute. So, we try/catch(login), try/catch(enterHoursWorked) etc... As others have said, it's ugly, but in my case it works. Now the exception is added to the log, and the next workflow executes
public void MyClientsFunctions() throws Exception {
ExtentTest t = ReportFactory.getTest();
try {
Login objPage = new PageObject(driver);
// this method throws exception
try {
objPage.Login();
if (x = y)
t.log(LogStatus.PASS, "Pass message");
else
t.log(LogStatus.FAIL, "Fail message" + screenshotMethod());
} catch (Exception e) {
t.log(LogStatus.ERROR, "Exception found: " + e.getMessage() + screenshotMethod());
objPage.BackToHomePage();
}
try {
objPage.EnterHoursWorked();
if (a = b)
t.log(LogStatus.PASS, "Pass message");
else
t.log(LogStatus.FAIL, "Fail message" + screenshotMethod());
} catch (Exception e) {
t.log(LogStatus.ERROR, "Exception found: " + e.getMessage() + screenshotMethod());
objPage.BackToHomePage();
}
} catch (Exception e) {
t.log(LogStatus.ERROR, "Exception found: " + e.getMessage() + screenshotMethod());
}
}

Validate COMPLETE XML Against XSD

I want to validate my XML against my XSD COMPLETELY, meaning that I want the file to continue validating from the same point where it had thrown an exception.
This is my code :
public void validate(File file) {
try {
Source xmlFile = new StreamSource(file);
try {
System.out.println("Processing : " + file.getAbsolutePath());
System.out.println(validator);
validator.validate(xmlFile);
// stringBuffer.append(" is valid");
} catch (SAXException e) {
fileWriter.write("\n\n\n" + file.getAbsolutePath());
System.out.println(xmlFile.getSystemId() + " is NOT valid");
System.out.println("Reason: " + e.getLocalizedMessage());
fileWriter.write("\nReason: " + e.getLocalizedMessage());
if (e instanceof SAXParseException) {
fileWriter.write(" (Line : "
+ ((SAXParseException) e).getLineNumber()
+ ", Col : "
+ ((SAXParseException) e).getColumnNumber() + ")");
}
fileWriter.flush();
validate(file);
}
} catch (Exception exception) {
exception.printStackTrace(System.out);
}
}
Here according to this snippet, after JUST ONE EXCEPTION the code returns the error and stops validating further XML.. But is there any way to get all the errors of the XML against the XSD? In short to continue validating from the cursor where it had thrown an exception.
ANY WAY OUT??
Thanks!
The behavior of the default error handler is to stop processing after the first fatal error is encountered by throwing a SAXException. To alter this behavior, implement your own ErrorHandler and register it with your validator.
This is an example that just dumps the exceptions to standard output, but you would probably want to replace it with a more intelligent reporting mechanism.
class CustomErrorHandler implements ErrorHandler {
public void fatalError(SAXParseException e) throws SAXException {
System.out.println(e.toString());
}
public void error( SAXParseException e ) throws SAXException {
System.out.println(e.toString());
}
public void warning( SAXParseException e ) throws SAXException {
System.out.println(e.toString());
}
}
And then:
validator.setErrorHandler(new CustomErrorHandler());

How to get the invoker name in EJB interceptor's lifecycle event method

I use Java EE 5. I wrote an interceptor for all EJBs with three methods for logging:
public class DefaultInterceptor {
public static final String PREFIX = "!!!!!!!!!Interceptor:";
#PostConstruct
public void postConstruct(InvocationContext ctx) {
try {
System.out.println(PREFIX + " postConstruct");
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
#PreDestroy
public void preDestroy(InvocationContext ctx) {
try {
System.out.println(PREFIX + " predestroy");
System.out.println(PREFIX + "ctx.preceed=" + ctx.proceed());
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
#AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception {
System.out.println(PREFIX + "method invocation '" + ctx.getMethod().getName() + "'");
System.out.println(PREFIX + "parameters ='" + Arrays.deepToString(ctx.getParameters()) + "'");
System.out.println(Arrays.deepToString(ctx.getContextData().keySet().toArray()));
Object result = null;
try {
result = ctx.proceed();
System.out.println(PREFIX + "Method result='" + result + "'");
return result;
} catch (Exception ex) {
System.out.println(PREFIX + "Method exception ='" + ex.getMessage() + "'");
throw ex;
} finally {
System.out.println(PREFIX + "Method finished");
}
}
}
I want to get the name of EJB which called this interceptor. How can I do it?
I tried ctx.getMethod().getDeclaringClass().getSimpleName() but ctx.getMethod() returns null in postConstruct(-) and predestroy(-) methods.
For lifecycle callbacks ctx.getMethod() returns null. This is documented for example here: http://docs.oracle.com/javaee/5/api/javax/interceptor/InvocationContext.html
That is so, because it is not your EJB, but container who calls lifecycle callback methods.
If you are interested about association between interceptor and bean it belongs to, doesn't ctx.getTarget() method serve your purpose?
On WebLogic server you can use this in postConstructor, etc, to get the EJB name:
ctx.getTarget().getClass().getSuperclass().getName();

Categories

Resources