exceptions irst
TRANSCRIPT
Exceptions First
"Both optimists and pessimists contribute to society. The optimist invents the airplane, the pessimist invents the parachute."
— George Bernard Shaw
Exceptional Cases This CANNOT be covered in requirements, its developers' sole
responsibility
For a single happy scenario, You may need 10 erroneous scenarios, which makes your effort 11 times bigger than what you think.
Always fear about the failure during the development. What if the input becomes null? this transaction failed? Should we roll back? this checked exception happens? Should I handle it? Or propagate
back? There is a runtime exception? Can the system handle? Who builds the
system anyway?
Tom, JK & Harry’s codestry {
//do something;
} catch (IOException e) {
e.printStackTrace();
}
Tom, JK & Harry’s codestry {
//do something;
} catch (IOException e) {
//This is it
}
Tom, JK & Harry’s codestry {
return something;
} catch (IOException e) {
return “”;
}
Tom, JK & Harry’s codes
if(something wrong){ throw new Exception(“Error”);
}
Unchecked Vs Checked Exceptions
Unchecked exceptions represent conditions that, generally speaking, reflect errors in your program's logic and cannot be reasonably recovered from at run time
Do not handle the exception, but prevent it There are exceptions for this! Subclasses of ‘RuntimeException’
Checked exceptions caused due to genuine error scenarios happened outside the control of the system
Connection Issues Input Issues Resourcing Issues Subclasses of ‘Exception’
Unchecked Exceptions: Prevent Them
private static int mod(int a, int b) {
return a % b;
}
Is it correct?
Unchecked Exceptions: Prevent Them
private static int mod(int a, int b) { try { return a % b; } catch (Exception e) {
logger.error(“Error in calculating mod function”, e)
return 0; } }
Is it Correct?
Unchecked Exceptions: Prevent Them
private static int mod(int a, int b) { try { return a % b; } catch (Throwable e) {
logger.error(“Error in calculating mod function”, e)
throw new IllegalArgumentException("Divisior can not be zero for mod operation");
} }
Is it correct?
Unchecked Exceptions: Prevent Them
private static int mod(int a, int b) { if(0 == b){
throw new IllegalArgumentException("Divisior can not be zero for mod operation");
} return a % b;}
Unchecked exception is prevented The handling part of exceptional case is not the responsibility of the
method Its caller’s responsibility to handle zero cases
Unchecked Exceptions: Prevent Them
public static void main(String[] args) { int a = 1; int b = 1; //read a //read b if(0 == b){ // tell user the number is not acceptable } int mod = mod(a, b); }Its over to user at the end!
Checked exception: don't handle, but propagate back
public boolean isAvailable(String id) throws PipeException{
Object a = query(id);
return null != a;
}
private Object query(String id) throws PipeException;
It not isAvailable method's responsibility
Checked exception: You handle it, Your Responsibility
try { if (condition) { throw new AppNotAvailableException("The recipient is null", AppNException.INVALID_SHORTCODE); } //do something targetService.execute(sdpRequestMessage, sdpMessageContext);} catch (AppNotAvailableException e) { sdpMessageContext = new SdpMessageContextImpl(); sdpMessageContext.setShortcode(shortcode); e.setShortcode(shortcode);exceptionHandlerService.onMessagingException(sdpRequestMessage, sdpMessageContext, e);
} catch (Throwable th) { exceptionHandlerService.onMessagingException(sdpRequestMessage, sdpMessageContext, th); } }
So Simple Haa?
Its simple, but we don't do simple things simple! Kinda people who ship a system if it compiles! Kinda people who touch our code even when TCs failing Some frameworks make simple things complex
ORM(Spring, hibernate, JPA) exceptions are RUNTIME: Why? But most of us don't know why! Result?
DB Connection Error at UI. System at stalemate when a integrity violation happens. Genuine errors causing so many troubles.
Some developers even don't know there can be ORM exception!
Contd... Propagating Checked Exceptions across modules
creates coupling Always catch and re throw module specific exceptionpublic void delete(String appId) throws
QueryByTransactionIdException { try {
jdbcTemplate.update(query); } catch (DataAccessException e) { throw new QueryByTransactionIdException("Error while adding the TransactionStatus", e); } }
Contd…protected ModelAndView processFinish(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Object command, BindException bindException) {
//do something try
{ serviceLocator.getAmaFieldTypeConfigurationService().addNewAmaFieldType(amafieldType);
return new ModelAndView(successView); } catch (MetadataException dae) { getServiceLocator().getMetadataServiceManagerStub().reInitMBean(); bindException.reject("globle.error.meta.access.exception"); bindException.getModel(); return showPage(httpServletRequest, bindException, 0); } catch (Throwable dae) { bindException.reject("globle.error.unexcepected.exception"); bindException.getModel(); return showPage(httpServletRequest, bindException, 0); } }
Use Finally for cleansing
public void dataAccessCode() { Connection conn = null; try { conn = getConnection(); //some code that throws SQLException } catch (SQLException ex) { throw new JKException("Error while accessing data ", ex) } finally { try { DBUtil.closeConnection(conn); } catch (Throwable e) { //do nothing or throw RuntimeException } } }
Good Practices
Use error logging effectively Genuine or Not, its our support going to struggle. logger.error(“Put some valuable message”, e)
Always catch Throwable at the end Trust nobody including you Handle the checked exception and the keep a catch clause for
Throwable INCASE Sending traps: Be proactive & sensible Keep the exception class directly under root package of the
module Log exception only once
WORRY ABOUT EXCEPTIONS
Decide which method to handle and which one to propagate (Throw early catch late )
Think about the complete flow with the exception and handle it at the right place
Write testcases for exceptional cases
Spend an hour to work on the UIs with exceptional scenarios Error code mapping to error pages Exception class mapping to error pages Error message resource bundles What happens to session when this happen? Should we enable back button? Should we keep a home button?
DANKE!