I have the following below piece of code when I am running SonarQube for code quality check on it after integrating it with Maven.
However, Sonar is complaining that I should Either log or rethrow this exception.
What am I missing here? Can some one help me please.
Code
public ShippingResponse processShipping(ShippingRequest request) {
log.debug("Processing Reservation Request ....");
try{
return helper.processShippingMethod(request);
} catch (ServiceException serviceException) {
log.error(RESERVATION_EXCE, ExceptionUtils.getStackTrace(serviceException));
throw serviceException;
} catch (Exception e) {
throw new ServiceException(ErrorMessages.EPO_SM_ERR_03, e.getMessage());
}
}
The point that Sonar is trying to make is that you ideally print or keep the root cause of your exception, so basically the stack. You keep it by passing the exception object because if you only keep the message you lose all that information. To make sonar happy you either print the stack trace (log.error(ErrorMessages.EPO_SM_ERR_03, e)), or re-throw a new exception passing the Throwable object to the constructor.
So the ideal solution would be to use the ServiceException like this;
public class ServiceException extends Exception {
public ServiceException(String message, Throwable cause) {
super(message, cause);
}
}
throw new ServiceException(ErrorMessages.EPO_SM_ERR_03, e);
Related
I am doing a simple experiment for debugging purpose.
First I insert serveral records to database, and then I do a invalid data conversion which will throw DataIntegrityViolationException, but I will catch the exception.
I expected the records being successfully inserted into the db, since I catch the checked exception. But the whole thing is rolled back.
I do the experiment again using TransactionTemplate instead of using annotation, same result.
My questions are:
is this the expected behavior?
If anwser to No.1 is yes, then I catch the exception, how is it possible that spring knows an exception is thrown?
Here is my code:
public void insertValue() {
jdbcTemplate.execute("insert into people (person_id, name) values (4, 'asjkdhadsjkqhweqkewhkashdkahd')");
jdbcTemplate.execute("insert into people (person_id, name) values (5, 'tttqqq')");
}
// this should throw exception
public void truncateValue() {
jdbcTemplate.execute("alter table people alter column name varchar(7)");
}
public void jdbc_calls() {
insertValue();
try {
truncateValue();
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println("Finish");
}
public void run() {
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
transactionTemplate.execute(transactionStatus -> {
try {
jdbc_calls();
} catch (RuntimeException e) {
throw e;
} catch (Throwable e) {
throw new RuntimeException(e);
}
return null;
});
}
More about question No.2.
Here is the source code of TransactionTemplate.execute()
From my understanding, if I don't throw an exception, rollbackOnException won'r be triggered.
public <T> T execute(TransactionCallback<T> action) throws TransactionException {
Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
}
else {
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try {
result = action.doInTransaction(status);
}
catch (RuntimeException | Error ex) {
// Transactional code threw application exception -> rollback
rollbackOnException(status, ex);
throw ex;
}
catch (Throwable ex) {
// Transactional code threw unexpected exception -> rollback
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
}
this.transactionManager.commit(status);
return result;
}
}
is this the expected behavior?
Yes, it is.
If anwser to No.1 is yes, then I catch the exception, how is it possible that spring knows an exception is thrown?
When an exception occurs, spring will mark your transaction as rollbackOnly.
So even when you catch your exception, at the end of your method, your transaction still rolled back.
In your case, I don't get why you use #Transaction since you want to commit regardless if exception occurs.
Edit
When you're using transaction with DB, the transaction invocation is delegated to EntityManager.
Look at AbstractEntityManagerImpl#handlePersistenceException:
#Override
public void handlePersistenceException(PersistenceException e) {
if ( e instanceof NoResultException ) {
return;
}
if ( e instanceof NonUniqueResultException ) {
return;
}
if ( e instanceof LockTimeoutException ) {
return;
}
if ( e instanceof QueryTimeoutException ) {
return;
}
try {
markForRollbackOnly();
}
catch ( Exception ne ) {
//we do not want the subsequent exception to swallow the original one
LOG.unableToMarkForRollbackOnPersistenceException(ne);
}
}
When exception occurs, the EntityManager mark your transaction as rollbackOnly before throws out the exception for you to catch.
After the exception is catched in your service, the AbstractPlatformTransactionManager will try to commit (because, as you know, no exception is detected there), but the EntityManager refuses to commit because its detect that the transaction marked as rollback-only.
If you read the exception, you will see something like:
javax.persistence.RollbackException: Transaction marked as rollbackOnly
Log exception details in Spring AOP with empty catch block.
For example:
try {
int data = 50 / 0;
} catch (Exception e) {
}
Exception not printing stack trace in spring aop for empty catch methods
I am using "#AfterThrowing" but its not working. Please find below code:
#AfterThrowing(pointcut ="catsServiceLevelLog()",throwing = "ex")
public void exceptionAdvice(Throwable ex) throws Throwable
{
}
assylias explain well about final rethrow.
I added final to method3.
public void method4() throws IOException {
try {
throw new IOException("1");
} catch (final Exception e) {
e = new IOException("2"); //does not compile
throw e; //does not compile
}
}
I set my compiler to 1.7. method4 have two compile errors :
final exception can neither be reassigned nor throw precise exception.
So, explicit final exception is only used to prevent modify?
Exception of catch block is implicitly final that doesn't mean you can not reassign it. If you specifically make it final then compiler will not allow you to modify that reference. To make throw compile exception instance must be final or effectively final as already covered in linked answer.
public void method4() throws IOException {
try {
throw new IOException("1");
} catch (final Exception e) {
e = new IOException("2");// You can not modify final reference
throw e;
}
}
so explicit final exception is only used to prevent modify?
Yes exactly, in case of exception, final modifier is redundant. It is always recommended to throw or log the exception. Modification of any exception is an anti pattern according to me. Generally speaking even in case of custom exception we should not modify the thrown exception unless and until you have very strong reason to do so.
I am trying to implement a generic class that executes a callable asynchronously, but I am not sure about the semantics.
#Component
public class MyCallerImpl implements MyCaller {
#Async
#Override
public <T> Future<T> runAsync(Callable<T> callable) throws Exception {
return new AsyncResult<T>(callable.call());
}
}
Basically, this component executes arbitrary actions from any callable asynchronously using the #Async annotation.
I am unsure about the Exception in the throws clause of the method signature.
A Junit test:
#ContextConfiguration("classpath:test-config.xml")
#RunWith(SpringJUnit4ClassRunner.class)
public class RunnerTest{
#Resource(name="myCallerImpl")
private MyCaller myCaller;
#Test
public void testException(){
final Callable<String> callable = new Callable<String>(){
#Override
public String call() throws Exception{
throw new MyException("foobar");
}
};
try
{
final Future<String> future = myCaller.runAsync(callable); // this can throw Exception due to Callable.call()
future.get(); // this can throw InterruptedException and ExecutionException
}
catch (final InterruptedException ie)
{
// do someting
}
catch (final ExecutionException ee)
{
// we want to check the cause
final Throwable cause = ee.getCause();
assertTrue(cause instanceof MyException);
}
catch (final Exception e)
{
// Not sure what to do here.
// Must be caught as it is declared to
// be thrown from the MyCaller.runAsync() method
// but nothing will really ever get here
// since the method is #Async and any exception will be
// wrapped by an ExecutionException and thrown during Future.get()
fail("this is unexpected);
}
My question is what to do about the Exception declared in the throws clause of MyCallerImpl.runAsync()?
The only reason I have declared it is because of the way I am calling the callable. Originally I had the following in the async method:
FutureTask<T> futureTask = new FutureTask<T>(callable);
futureTask.run();
return futureTask;
But when an exception is thrown from the callable in that instance, it gets wrapped twice in an ExecutionException, the first time when FutureTask.run() is called eventually FutureTask.Sync.innerRun() catches the exception and calls innnerSetException() and a second time when the AsyncExecutionIntercepter gets the result from the Future via Future.get(), which eventually again checks if there is an exception and throws a new ExecutionException wrapping the ExecutionException caught in innerRun()
I also tried to do the following in the method:
FutureTask<T> futureTask = new FutureTask<T>(callable);
return futureTask;
I had figured that since the AsyncExecutionInterceptor calls Future.get(), that the callable would be called immediately, but that was not the case. It just hangs on FutureTask.acquireSharedInterruptibly() and never returns.
Maybe I'm in over my head here. It works how I have it set-up with the callable now, but I rather not have the method signature declare a throws Exception.
Any advice? Should I forget about this generic way of doing async calls with a callable?
There are 2 layers of exception here.
one:
the exception leading to the calling of the Callable
if (string.equals("X")){ callable.call();}
two:
the exception caused when calling the callable.call() method (your "throw new MyException("foobar");")
since you do not have any other code prior to "callable.call();", it would be safe to remove the checked exception.
Change
public <T> Future<T> runAsync(Callable<T> callable) throws Exception
to
public <T> Future<T> runAsync(Callable<T> callable)
additionally, you can code it this way
final Future<String> future = myCaller.runAsync(callable);
try
{
future.get(); // this can throw InterruptedException and ExecutionException
}
catch (final InterruptedException ie)
{
// do someting
}
catch (final ExecutionException ee)
{
// we want to check the cause
final Throwable cause = ee.getCause();
assertTrue(cause instanceof MyException);
}
Is there any way to throws an standard or custom exception with Apex method as,
private void createNewJob() throws RecordNotFoundException {
try {
// Some DML operation
} catch (Exception e) {
System.Debug('Error: Object not found');
throw new RecordNotFoundException('Object not found');
}
}
Yes.
Define the exception class. Minimally, :
public class RecordNotFoundException extends Exception { }
Your throw statement looks fine.
Also, there's no need to declare that the method throws an exception type.
I think following can help you. It has complete example of SFDC APEX standard and custom exceptions
http://share-salesforce.blogspot.in/2013/05/salesforce-apex-exception-handling-and_29.html
We should not explicitly throw those standard or custom exceptions with Apex, code it self done that.
#Method that throws some custom exception (RecordNotFoundException)
private void createNewJob(){
try {
// Some DML operation
} catch (Exception e) {
System.Debug('Error: Object not found');
throw new RecordNotFoundException('Object not found');
}
}
#Can handle that exception as follow,
private void callingMethod() {
try {
createNewJob(); // Call above method
} catch (RecordNotFoundException e) {
System.Debug('Error:Record not found exception ['+ e.getMessage()+']');
}
}