SlideShare a Scribd company logo
1 of 66
Download to read offline
10 Typical Problems in
     (Enterprise) Java Applications
     Eberhard Wolff, Architecture & Technology Manager, adesso AG
     Blog: http://ewolff.com
     Twitter: @ewolff http://www.slideshare.net/ewolff




04.07.11
Why this talk?
►    I do a lot of reviews
►    There are some common problems you see over and
     over again


►    So: Here are 10
      >  …not necessarily the most common
      >  ...but certainly with severe effects
#1


public class Service {	
	
      private CustomerDao customerDao;	
      private PlatformTransactionManager transactionManager;	
	
      public void performSomeService() {	
         TransactionStatus transactionStatus = transactionManager	
          .getTransaction(new DefaultTransactionDefinition());	
         customerDao.doSomething();	
         customerDao.doSomethingElse();	
         transactionManager.commit(transactionStatus);	
      }	
	
}	
  
#1 Weak Transaction Handling


public class Service {	
	
      private CustomerDao customerDao;	
      private PlatformTransactionManager transactionManager;	
	
      public void performSomeService() {	
         TransactionStatus transactionStatus = transactionManager	
          .getTransaction(new DefaultTransactionDefinition());	
         customerDao.doSomething();	
         customerDao.doSomethingElse();	
         transactionManager.commit(transactionStatus);	
      }	
	 ►  What happens to the transaction if the DAO
}	
  throws an exception?
  ►  We might never learn...

  ►  ...or learn the hard way
Weak Transaction Handling: Impact
►    Hard to detect, has effects only if exception is thrown
►    …but then it can lead to wired behavior and data loss
     etc.


►    Protection against failures is why you are using
     transactions in the first place
►    This is compromised
Solution
►    Declarative transactions

public class Service {	
	
      private CustomerDao customerDao;	
	
      @Transactional	
      public void performSomeService() {	
         customerDao.doSomething();	
         customerDao.doSomethingElse();	
      }	
	
}	
  

     •  Exception is caught, transaction is rolled back (if it is a
        RuntimeException)
     •  Exception handling can be customized
A different solution…


public void performSomeService() {	
  TransactionTemplate template = new TransactionTemplate(	
   transactionManager);	
  template.execute(new TransactionCallback() {	
	
    public Object doInTransaction(TransactionStatus status) {	
       customerDao.doSomething();	
       customerDao.doSomethingElse();	
       return null;	
    }	
	
   });	
}
     Allows for multiple transactions in one method
     More code – more control
     Rather seldomly really needed
#2 Exception Design
►    Get all the details from a system exception!
►    Each layer must only use its own exceptions!
►    Exceptions have to be checked – then they must be
     handled and the code is more secure.


►    Sounds reasonably, doesn't it?
public class OrderDao {	
   public void createOrder(Order order) throws SQLException {	
      // some ugly JDBC code	
      // that I am not going to show	
   }	
}	
                       public class SomeService {	
                          public void performService()	
Get all the details!         throws ServiceException {	
Use checked                  try {	
exceptions!                     orderDao.createOrder(new Order());	
                             } catch (SQLException e) {	
                                throw new ServiceException(e);	
Service must only            }	
throw                     }	
ServiceException!      }	       public class SomeController {	
                                  public void handleWebRequest() {	
                                     try {	
 What am I supposed to do               someService.performService();	
 now?                                } catch (Exception e) {	
 No real logging                        e.printStackTrace();	
                                     }	
 And I don’t care about the       }	
 specific ServiceException    }
Impact
►    Lots of useless exception handling code
►    Lots of exception types without specific handling of
     that type
►    In the end all you get is a log entry
►    …and lots of code


►    And what should the developer do?
      >  All he knows "Something went wrong"
      >  Does not really care and can not really handle it
Why is this commonplace?
    Very few languages have checked exceptions (Java - CLU and
     Modula-3 had similar concepts)
    Checked exception force developers to handle an exception –
     very rigid
    How often can you really handle an exception?
    Checked exceptions seem more secure
    But: Checked exceptions are overused – also in Java APIs


    In many cases there are even no wrong exception concepts in
     projects – there are just none.
Solution
    Use more unchecked exceptions aka RuntimeExceptions
    Remember: A lot of languages offer only unchecked
     exceptions


    Avoid wrap-and-rethrow – it does not add value
    Don't write too many exception classes – they often don't add
     value
    An exception classes is only useful if that exception should be
     handled differently
Solution

public class OrderDao {	
   public void createOrder(Order order) {	
      jdbcTemplate.update("INSERT INTO T_ORDER ...");	
   }	
}	



                     public class SomeService {	
Where is the            public void performService() {	
                           orderDao.createOrder(new Order());	
exception               }	
                     }	
handling?
                                public class SomeController {	
                                  public void handleWebRequest() {	
                                     someService.performService();	
                                  }	
                                }
AOP in one Slide
@Aspect	
public class AnAspect {	
	
   // do something before the method hello	
   // is executed	
   @Before("execution(void hello())")	
   public void doSomething() {	
   }	
	
   // method hello(), arbitrary return type	
   // in a the class MyService in package de.adesso	
   @Before("execution(* de.adesso.MyService.hello())")	
   public void doSomethingElse2() {	
   }	
	
   // do something before any method in a class	
   // that ends in Service in any package or subpackage	
   @Before("execution(* *..*Service.*(..))")	
   public void doSomethingElse2() {	
   }	
	
}
Aspect for Logging


@Aspect	
public class ExceptionLogging {	
	
   @AfterThrowing(value="execution(* *..*Service.*(..))",	
    throwing="ex")	
   public void logRuntimeException(RuntimeException ex) {	
      System.out.println(ex);	
   }	
	
}	


►    Logs every exception – 100% guaranteed!
Handle only specific cases

     public class SomeService {	
        public void performService() {	
           try {	
              orderDao.createOrder(new Order());	
           } catch (OptimisticLockingFailureException ex) {	
              orderDao.createOrder(new Order());	
           }	
        }	
     }	
►    Everything else will be handled somewhere else
►    Can handle specific error conditions using catch with
     specific types
►    Can be done with AOP
Generic Exception Handling


 public class MyHandlerExceptionResolver	
   implements HandlerExceptionResolver {	
 	
    public ModelAndView resolveException(	
     HttpServletRequest request,	
     HttpServletResponse response, Object handler, Exception ex) {	
       return new ModelAndView("exceptionView", "exception", ex);	
    }	
 	
 }
►    In the web layer
►    Handle all the (Runtime)Exceptions not handled
     elsewhere
#3 Exception Handling



  public void someMethod() {	         Exception is not logged
    try {	
  	                                   just written to stdout
    } catch (Exception ex) {	         operations might not notice
       ex.printStackTrace();	
    }	
    try {	
  	
    } catch (Exception ex) {	
       log.error(ex.getMessage());	
                                      Stack trace will be lost
    }	
    try {	
  	
    } catch (Exception ex) {	         Exception is swallowed
       // should never happen	        comment suggests it would be
    }	
  }                                   serious error
Impact
    Related to #2: Bad Exception design will cause more bad
     exception handling


    In the end you just get a message on the console and the
     application continues.
    All kinds of wired behavior
    i.e. exception is swallowed
    You will have a hard time finding problems in the code
    Potentially a huge problem – so worth its own explanation


    Usually detected by Findbugs, PMD and the like
Solution
    At least log exceptions including stack trace
    Rethink: Is it really OK to continue after the exception is
     thrown? Might be better to let a generic handler handle it.
    Introduce generic handling at least for RuntimeException
     (AOP, web front end, etc)
    Enforce logging using
     Findbugs, PMD etc.
    And: Improve the
     exception design (#2)                 public void someMethod() {	
                                             try {	
                                           	
                                             } catch (Exception ex) {	
                                                log.error(ex);	
                                             }	
                                           }
#4


    Table of packages
     and the relations
     between them
    Everything in red is
     part of a cycle
    This is actual code
     from an Open
     Source project
Dependency Graph
►    Overview
Dependency Graph


►    Just a small part
►    Red line show
     circular references
What is Architecture?
►    Architecture is the decomposition of systems in parts


►    No large or complex parts
►    No cyclic dependencies
Normal Dependencies


►    B dependes on A, i.e. it uses
     classe, methods etc.
►    Changes in A impact B           Component A
►    Changes in B do not impact A




                                     Component B
Cyclic Dependency


►    B depends on A and A on B
►    Changes in A impact B
►    Changes in B impact A            Component A
►    A and B can only be changed as
     one unit
►    …even though they should be
     two separate units
                                      Component B
Bigger cyclic dependencies




         Component A


                             Component B


         Component C
#4: Architecture Mess
    This is effectively one
     big unstructured pile
     of mud
    Maintenance will be
     hard
    Concurrent
     development will be
     hard
    Changes will have
     unforeseeable results
Solution
    Very hard if you have this state
    Therefore: Manage dependencies from the start
    Consider Sonargraph or Structure 101
    Can even simulate refactorings
    Otherwise you are looking at a major restructuring of your application
    …which might not be worth it
    Effort for restructuring pays off by lower effort for maintenance
    …might take a long time to amortize


    Throwing away + redevelopment means that you have to migrate to a new
     solution -> complex and risky
The Real Problem: Where Are You Steering?
►    What is the status of your project?
►    Also need to understand test coverage, complexity, coding
     rules etc
►    Technical debt


►    Should be measured
►    Should not increase


►    Consider Sonar
►    Historized consolidated data from multiple sources
►    Is it getting better or worse?

03.07.11   30
03.07.11   31
03.07.11   32
Metrics are not everything
    If everything is in one package there will be no cycles
    If packages for technical artifact (DAOs, services) might hide
     cycles in the functional decomposition
    If interfaces and implementation are in the same package
     dependencies to the implementation might slip in.
    A cycle with one dependency in the "wrong" direction is
     different from one with 40 in both directions.
    Think about the structure – don't let metric fool you.
    Don’t manage or program to the metrics.


    Use it as a hint
#5

public class ServiceAdaptor {	
   public void performService(OrderDTO orderDTO) {	
      logger.trace("Entering performService");	
      try {	
         if (orderDTO == null) {	
            throw new NullPointerException("order must not be null");	
         }	
         if (youAreNotAllowedToDoThis()) {	
            throw new IllegalStateException(	
             "You are not allowed to call this!");	
         }	
         OrderEntity order = new OrderEntity();	
         order.setCustomer(orderDTO.getCustomer()); // ...	
         service.performService(order);	
         commandLog.add(new Command("performService",	
          service,order));	
      } finally {	
         logger.trace("Leaving performanceService");	
      }	
   }	
}
#5: Adaptor Layer
►    Adds to a service:
      >  Security
      >  Tracing
      >  Check for null arguments
      >  Log for all commands (auditing, replay…)
      >  Conversion from DTO to internal representation
►    Lots of boilerplate code for each service
►    Changes to tracing etc. hard: lots of methods to
     change
Solution: Tracing with AOP
►    …or use Spring's predefined TraceInterceptor,
     DebugInterceptor etc.


     @Aspect	
     public class TraceAspect {	
     	
       @Before("execution(* *..*Service.*(..))")	
       public void traceBegin(JoinPoint joinPoint) {	
         System.out.println("entering method "	
           + joinPoint.getSignature().getName());	
        }	
     	
        @After("execution(* *..*Service.*(..))")	
        public void traceEnd(JoinPoint joinPoint) {	
           System.out.println("leaving method "	
            + joinPoint.getSignature().getName());	
        }	
     }
Solution: Null Checks with AOP
 @Aspect	
 public class NullChecker {	
 	
   @Before("execution(* *..*Service.*(..))")	
   public void checkForNull(JoinPoint joinPoint) {	
      for (Object arg : joinPoint.getArgs()) {	
         if (arg==null) {	
           throw new NullPointerException("Argument was null!");	
         } 	
      }	
   }	
 	
 }

►    Security can be handled with Spring Security or AOP
►    Command log also possible
What is left…
public class ServiceAdaptor {	
	
  public void performService(OrderDTO orderDTO) {     	
     OrderEntity order = new OrderEntity();	
     order.setCustomer(orderDTO.getCustomer()); // ...	
     service.performService(order);	
  }	
	
}
     You should probably switch to Dozer

     http://dozer.sf.net

     Can externalize mapping rules

     i.e. the layer can be more or less eliminated

     Everything (mapping, security, tracing…) is now implemented in one place (DRY)

     Often services just delegate to DAOs –
      same issue
#6: No DAO
public class SomeService {	
	
  @PersistenceContext	
  private EntityManager entityManager;	
	
  public void performSomeService() {	
     List<Order> list = entityManager.	
      createQuery("select o from Order").getResultList();	
     for (Order o : list) {	
        // ...	
        if (o.shouldBeProcessed()) {	
           o.process();	
        }	
     }	
  }	
}
►    We don't need to abstract away from JPA – it's a
     standard, right?
#6: Even worse
public class SomeServiceJdbc {	
	
private OrderDao someDoa;	
	
  public void performSomeService() throws SQLException {	
     ResultSet rs = someDoa.getOrders();	
     while (rs.next()) {	
        //...	
     }	
  }	
	
}
►    Service depends on JDBC
►    …and throws SQLException
►    Persistence visible in the service layer and beyond
Impact
    Code is impossible to test without a database
    …so no unit tests possible


    Service depends on persistence – cannot be ported


    How do you add data dependent security?


    No structure
Solution
►    Use a DAO (Data Access Object)
      >  Separate persistence layer
      >  Technical motivation


►    …or a Repository
      >  Interface to existing objects
      >  Non technical motivation: Domain Driven Design,
         Eric Evans


►    Basically the same thing
Solution


public class SomeServiceDAO {	
	
  public void performSomeService() {	
     List<Order> list = orderDao.getAllOrders();	
     for (Order o : list) {	
       // ...	
       if (o.shouldBeProcessed()) {	
          o.process();	
       }	
      }	
  }	
}
►    Clear separation
►    Tests easy
Solution: Test


public class ServiceTest {	
  @Test	
  public void testService() {	
     SomeService someService = new SomeService();	
     someService.setOrderDao(new OrderDao() {	
	
       public List<Order> getAllOrders() {	
          List<Order> result = new ArrayList<Order>();	
          return result;	
       }	
     });	
     someService.performSomeService();	
     Assert.assertEquals(expected, result);	
  }	
	
}
#7
►    No Tests
#7 Or bad tests


    No asserts           public class MyUnitTest {	
                            private Service service = new Service();	
    System.out: results 	
     are checked manually @Test	
                            public void testService() {	
    Tests commented out: Order order = new Order();	
     They did not run any      service.performService(order);	
                               System.out.print(order.isProcessed());	
     more and were not      }	
     fixed                	
                            // @Test	
    No mocks, so no real // public void testOrderCreated() {	
     Unit Tests             // Order order = new Order();	
                            // service.createOrder(order);	
    No negative cases      // }	
                          	
                          }
Impact
►    Code is not properly tested
►    Probably low quality – testable code is usually better
     designed
►    Code is hard to change: How can you know the change
     broke nothing?
►    Design might be bad: Testable usually mean better
     quality
►    Code might be considered tested – while in fact it is
     not.
Solution
►    Write proper Unit Tests!

public class MyProperUnitTest {	
   private Service service = new Service();	
	
   @Test	
   public void testService() {	
      Order order = new Order();	
      service.performService(order);	
      Assert.assertTrue(order.isProcessed());	
   }	
	
   @Test(expected=IllegalArgumentException.class)	
   public void testServiceException() {	
      Order order = new BuggyOrder();	
      service.performService(order);	
   }	
	
}
Wow, that was easy!
The real problem…
    The idea of Unit tests is over 10 years old
    Still not enough programmer actually do real unit tests
    Even though it should greatly increased trust and confidence in
     your code
    …and make you much more relaxed and therefore improve
     quality of life…


    Original paper: Gamma, Beck: "Test Infected – Programmers
     Love Writing Tests"
    Yeah, right.
Solution
►    Educate
      >  Show   how to write Unit Test
      >  Show   how to build Mocks
      >  Show   aggressive Testing
      >  Show   Test First / Test Driven Development
►    Coach / Review
►    Integrate in automatic build
►    Later on: Add integration testing, functional testing,
     FIT, Fitnesse etc.
►    …or even start with these
What does not really work
    Measuring code coverage
      >  Can be sabotaged: No Asserts…
       public class MyProperUnitTest {	
         private Service service = new Service();	
       	
         @Test	
         public void testService() {	
            Order order = new Order();	
            service.performService(order);	
         }	
       }


    Let developers just write tests without education
      >  How should they know how to test properly?
      >  Test driven development is not obvious
#8:




  public class OrderDAO {	
  	
    private SimpleJdbcTemplate simpleJdbcTemplate;	
  	
    public List<Order> findOrderByCustomer(String customer) {	
       return simpleJdbcTemplate.query(	
        "SELECT * FROM T_ORDER WHERE name='"	
        + customer + "'", new OrderRowMapper());	
    }	
  	
  }
Impact
►    Performance is bad:
      >  Statement is parsed every time
      >  Execution plan is re created etc.
Impact: SQL Injection
►    Pass in
     a' or 't'='t'
►    Better yet:
     a'; DROP TABLE T_ORDER; SELECT * FROM
     ANOTHER_TABLE

 public class OrderDAO {	
 	
   private SimpleJdbcTemplate simpleJdbcTemplate;	
 	
   public List<Order> findOrderByCustomer(String customer) {	
      return simpleJdbcTemplate.query(	
       "SELECT * FROM T_ORDER WHERE name='"	
       + customer + "'", new OrderRowMapper());	
   }	
 	
 }
Solution


     public class OrderDAO {	
     	
       private SimpleJdbcTemplate simpleJdbcTemplate;	
     	
       public List<Order> findOrderByCustomer(String customer) {	
          return simpleJdbcTemplate.query(	
           "SELECT * FROM T_ORDER WHERE name=?",	
           new OrderRowMapper(), customer);	
       }	
     	
     }
►    … and white list the allowed characters in name
►    to avoid bugs in DB driver etc.
#9
►    "What about Performance?"
►    "Well, we figured the response time should be 2s."
►    "How many request do you expect?"
►    "…"
►    "What kind of requests do you expect?"
►    "..."
#9
    Software is in the final functional test
    Then the performance test start
    Performance is too bad to be accepted
    You can hardly do anything:
      >  Changes might introduce functional errors after testing
      >  Too late for bigger changes
    The results might be wrong if the performance test is on
     different hardware than production.
    You can't test on production hardware: Too expensive.
Impact
►    You have to get bigger hardware
      >  Prerequisite: The software is scalable
      >  Otherwise: Tough luck


►    Worse: You can't go into production
Solution
    Get number of requests, expected types of requests,
     acceptable response times
    Pro active performance management:
      >  Estimate performance before implementation
      >  …by estimating the slow operations (access to other
         systems, to the database etc)
      >  Measure performance of these operation in production
    Get data from production
    Practice performance measurements and optimizations before
     performance test
#10


      public class SomeService {	
      	
      private Map cache = new HashMap();	
      private Customer customer;	
      	
        public Order performService(int i) { 	
           if (cache.containsKey(i)) {	
              return cache.get(i);	
           }	
           Order result;	
           customer = null;	
           cache.put(i, result);	
           return result;	
        }	
      	
      }
#10 Multiple threads, memory leaks


public class SomeService {	
	                                          The cache is filled –
  private Map<Integer,Order> cache =	      is it ever emptied?
   new HashMap<Integer, Order>();	
  private Customer customer;	              HashMap is not
	
  public Order performService(int i) { 	
                                           threadsafe
     if (cache.containsKey(i)) {	
        return (Ordercache.get(i);	
                                           customer is an
     }	                                    instance variable –
     Order result;	                        multi threading will
     customer = null;	
     ...	
                                           be a problem
     cache.put(i, result);	
     return result;	
  }	
	
}
Impact
►    System working in small tests
►    In particular Unit tests work


►    But production fails
►    …probably hard to analyze / fix
►    Almost only by code reviews
►    …or extensive debugging using thread dumps
Solution
    Use WeakHashMap to
     avoid memory leaks       public class SomeServiceSolution {	
                              	
    Synchronize                private Map<Integer, Order> cache =	
    Prefer local variables      new WeakHashMap<Integer, Order>();	
                              	
    Usually services can store public Order performService(int i) {	
                                   synchronized (cache) {	
     most things in local             if (cache.containsKey(i)) {
     variables                           return cache.get(i);	
                                      }	
                                   }	
                                   Order result = null;	
                                   Customer customer = null;	
                                   synchronized (cache) {	
                                      cache.put(i, result);	
                                   }	
                                   return result;	
                                }	
                              }
Solution
►    Also consider ConcurrentHashMap
►    or http://sourceforge.net/projects/high-scale-lib
Sum Up

 ►  #1 Weak Transaction    ►  #8 Creating SQL
    Handling                  queries using
 ►  #2 Exception Design
                              String
                              concatenation
 ►  #3 Exception
                           ►  #9 No
    Handling
                              performance
 ►  #4 Architecture Mess      management
 ►  #5 Adaptor Layer
                           ►  #10 Multiple
 ►  #6 No DAO                 threads / memory
 ►  #7 No or bad tests
                              leaks

More Related Content

What's hot

Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with Mockito
Richard Paul
 
Unit testing with Easymock
Unit testing with EasymockUnit testing with Easymock
Unit testing with Easymock
Ürgo Ringo
 
JavaScript and AJAX
JavaScript and AJAXJavaScript and AJAX
JavaScript and AJAX
Frane Bandov
 

What's hot (20)

Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with Mockito
 
201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing201913046 wahyu septiansyah network programing
201913046 wahyu septiansyah network programing
 
JMockit Framework Overview
JMockit Framework OverviewJMockit Framework Overview
JMockit Framework Overview
 
Android testing
Android testingAndroid testing
Android testing
 
Exceptions
ExceptionsExceptions
Exceptions
 
Unit testing with Easymock
Unit testing with EasymockUnit testing with Easymock
Unit testing with Easymock
 
ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for Programmers
 
Enterprise js pratices
Enterprise js praticesEnterprise js pratices
Enterprise js pratices
 
Mockito a simple, intuitive mocking framework
Mockito   a simple, intuitive mocking frameworkMockito   a simple, intuitive mocking framework
Mockito a simple, intuitive mocking framework
 
Mockito intro
Mockito introMockito intro
Mockito intro
 
Exception Handling in Java
Exception Handling in JavaException Handling in Java
Exception Handling in Java
 
Mockito intro
Mockito introMockito intro
Mockito intro
 
TDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving TestingTDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving Testing
 
JavaScript and AJAX
JavaScript and AJAXJavaScript and AJAX
JavaScript and AJAX
 
Introduction to Software Testing
Introduction to Software TestingIntroduction to Software Testing
Introduction to Software Testing
 
Mock your way with Mockito
Mock your way with MockitoMock your way with Mockito
Mock your way with Mockito
 
Redux for ReactJS Programmers
Redux for ReactJS ProgrammersRedux for ReactJS Programmers
Redux for ReactJS Programmers
 
Easymock Tutorial
Easymock TutorialEasymock Tutorial
Easymock Tutorial
 
Some testing - Everything you should know about testing to go with @pedro_g_s...
Some testing - Everything you should know about testing to go with @pedro_g_s...Some testing - Everything you should know about testing to go with @pedro_g_s...
Some testing - Everything you should know about testing to go with @pedro_g_s...
 
Mockito with a hint of PowerMock
Mockito with a hint of PowerMockMockito with a hint of PowerMock
Mockito with a hint of PowerMock
 

Viewers also liked (20)

Software Requirements
Software RequirementsSoftware Requirements
Software Requirements
 
Lecture13
Lecture13Lecture13
Lecture13
 
Book figureschs6 10slides
Book figureschs6 10slidesBook figureschs6 10slides
Book figureschs6 10slides
 
Or mapping
Or mappingOr mapping
Or mapping
 
Cmpm chuong 9-14 12-2009
Cmpm   chuong 9-14 12-2009Cmpm   chuong 9-14 12-2009
Cmpm chuong 9-14 12-2009
 
7 data management design
7 data management design7 data management design
7 data management design
 
6 class design
6 class design6 class design
6 class design
 
5 transition to design
5 transition to design5 transition to design
5 transition to design
 
4a domain model
4a domain model4a domain model
4a domain model
 
3 analysis and design overview
3 analysis and design overview3 analysis and design overview
3 analysis and design overview
 
OSCh9
OSCh9OSCh9
OSCh9
 
2b writing good use cases
2b writing good use cases2b writing good use cases
2b writing good use cases
 
Book figureschs1 5slides
Book figureschs1 5slidesBook figureschs1 5slides
Book figureschs1 5slides
 
Lecture19
Lecture19Lecture19
Lecture19
 
User Interface Design
User Interface DesignUser Interface Design
User Interface Design
 
SECh1214
SECh1214SECh1214
SECh1214
 
4b use-case analysis
4b use-case analysis4b use-case analysis
4b use-case analysis
 
Lecture 4
Lecture 4Lecture 4
Lecture 4
 
Live a life_that_matters
Live a life_that_mattersLive a life_that_matters
Live a life_that_matters
 
Library management system
Library management systemLibrary management system
Library management system
 

Similar to 10 Typical Enterprise Java Problems

Java exception handling
Java exception handlingJava exception handling
Java exception handling
BHUVIJAYAVELU
 
Exception handling and logging best practices
Exception handling and logging best practicesException handling and logging best practices
Exception handling and logging best practices
Angelin R
 
Unit II Java & J2EE regarding Java application development
Unit II Java & J2EE regarding Java application developmentUnit II Java & J2EE regarding Java application development
Unit II Java & J2EE regarding Java application development
rohitgudasi18
 

Similar to 10 Typical Enterprise Java Problems (20)

10 Typical Java Problems in the Wild
10 Typical Java Problems in the Wild10 Typical Java Problems in the Wild
10 Typical Java Problems in the Wild
 
Exception handling in java
Exception handling in javaException handling in java
Exception handling in java
 
2. Design patterns. part #2
2. Design patterns. part #22. Design patterns. part #2
2. Design patterns. part #2
 
java exception.pptx
java exception.pptxjava exception.pptx
java exception.pptx
 
JAVA PROGRAMMING- Exception handling - Multithreading
JAVA PROGRAMMING- Exception handling - MultithreadingJAVA PROGRAMMING- Exception handling - Multithreading
JAVA PROGRAMMING- Exception handling - Multithreading
 
Java-Exception Handling Presentation. 2024
Java-Exception Handling Presentation. 2024Java-Exception Handling Presentation. 2024
Java-Exception Handling Presentation. 2024
 
Exception Handling In Java Presentation. 2024
Exception Handling In Java Presentation. 2024Exception Handling In Java Presentation. 2024
Exception Handling In Java Presentation. 2024
 
Java exception handling
Java exception handlingJava exception handling
Java exception handling
 
exceptionhandlinginjava-140224181412-phpapp02.pptx
exceptionhandlinginjava-140224181412-phpapp02.pptxexceptionhandlinginjava-140224181412-phpapp02.pptx
exceptionhandlinginjava-140224181412-phpapp02.pptx
 
Comp102 lec 10
Comp102   lec 10Comp102   lec 10
Comp102 lec 10
 
Exception handling and logging best practices
Exception handling and logging best practicesException handling and logging best practices
Exception handling and logging best practices
 
17 exceptions
17   exceptions17   exceptions
17 exceptions
 
Java -Exception handlingunit-iv
Java -Exception handlingunit-ivJava -Exception handlingunit-iv
Java -Exception handlingunit-iv
 
Exception handling in java
Exception handling in javaException handling in java
Exception handling in java
 
Exceptions overview
Exceptions overviewExceptions overview
Exceptions overview
 
Unit II Java & J2EE regarding Java application development
Unit II Java & J2EE regarding Java application developmentUnit II Java & J2EE regarding Java application development
Unit II Java & J2EE regarding Java application development
 
Exception
ExceptionException
Exception
 
JDK Power Tools
JDK Power ToolsJDK Power Tools
JDK Power Tools
 
Training material exceptions v1
Training material   exceptions v1Training material   exceptions v1
Training material exceptions v1
 
Exception handling
Exception handlingException handling
Exception handling
 

More from Eberhard Wolff

More from Eberhard Wolff (20)

Architectures and Alternatives
Architectures and AlternativesArchitectures and Alternatives
Architectures and Alternatives
 
Beyond Microservices
Beyond MicroservicesBeyond Microservices
Beyond Microservices
 
The Frontiers of Continuous Delivery
The Frontiers of Continuous DeliveryThe Frontiers of Continuous Delivery
The Frontiers of Continuous Delivery
 
Four Times Microservices - REST, Kubernetes, UI Integration, Async
Four Times Microservices - REST, Kubernetes, UI Integration, AsyncFour Times Microservices - REST, Kubernetes, UI Integration, Async
Four Times Microservices - REST, Kubernetes, UI Integration, Async
 
Microservices - not just with Java
Microservices - not just with JavaMicroservices - not just with Java
Microservices - not just with Java
 
Deployment - Done Right!
Deployment - Done Right!Deployment - Done Right!
Deployment - Done Right!
 
Data Architecture not Just for Microservices
Data Architecture not Just for MicroservicesData Architecture not Just for Microservices
Data Architecture not Just for Microservices
 
How to Split Your System into Microservices
How to Split Your System into MicroservicesHow to Split Your System into Microservices
How to Split Your System into Microservices
 
Microservices and Self-contained System to Scale Agile
Microservices and Self-contained System to Scale AgileMicroservices and Self-contained System to Scale Agile
Microservices and Self-contained System to Scale Agile
 
How Small Can Java Microservices Be?
How Small Can Java Microservices Be?How Small Can Java Microservices Be?
How Small Can Java Microservices Be?
 
Data Architecturen Not Just for Microservices
Data Architecturen Not Just for MicroservicesData Architecturen Not Just for Microservices
Data Architecturen Not Just for Microservices
 
Microservices: Redundancy=Maintainability
Microservices: Redundancy=MaintainabilityMicroservices: Redundancy=Maintainability
Microservices: Redundancy=Maintainability
 
Self-contained Systems: A Different Approach to Microservices
Self-contained Systems: A Different Approach to MicroservicesSelf-contained Systems: A Different Approach to Microservices
Self-contained Systems: A Different Approach to Microservices
 
Microservices Technology Stack
Microservices Technology StackMicroservices Technology Stack
Microservices Technology Stack
 
Software Architecture for Innovation
Software Architecture for InnovationSoftware Architecture for Innovation
Software Architecture for Innovation
 
Five (easy?) Steps Towards Continuous Delivery
Five (easy?) Steps Towards Continuous DeliveryFive (easy?) Steps Towards Continuous Delivery
Five (easy?) Steps Towards Continuous Delivery
 
Nanoservices and Microservices with Java
Nanoservices and Microservices with JavaNanoservices and Microservices with Java
Nanoservices and Microservices with Java
 
Microservices: Architecture to Support Agile
Microservices: Architecture to Support AgileMicroservices: Architecture to Support Agile
Microservices: Architecture to Support Agile
 
Microservices: Architecture to scale Agile
Microservices: Architecture to scale AgileMicroservices: Architecture to scale Agile
Microservices: Architecture to scale Agile
 
Microservices, DevOps, Continuous Delivery – More Than Three Buzzwords
Microservices, DevOps, Continuous Delivery – More Than Three BuzzwordsMicroservices, DevOps, Continuous Delivery – More Than Three Buzzwords
Microservices, DevOps, Continuous Delivery – More Than Three Buzzwords
 

Recently uploaded

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 

Recently uploaded (20)

Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 

10 Typical Enterprise Java Problems

  • 1. 10 Typical Problems in (Enterprise) Java Applications Eberhard Wolff, Architecture & Technology Manager, adesso AG Blog: http://ewolff.com Twitter: @ewolff http://www.slideshare.net/ewolff 04.07.11
  • 2. Why this talk? ►  I do a lot of reviews ►  There are some common problems you see over and over again ►  So: Here are 10 >  …not necessarily the most common >  ...but certainly with severe effects
  • 3. #1 public class Service { private CustomerDao customerDao; private PlatformTransactionManager transactionManager; public void performSomeService() { TransactionStatus transactionStatus = transactionManager .getTransaction(new DefaultTransactionDefinition()); customerDao.doSomething(); customerDao.doSomethingElse(); transactionManager.commit(transactionStatus); } }  
  • 4. #1 Weak Transaction Handling public class Service { private CustomerDao customerDao; private PlatformTransactionManager transactionManager; public void performSomeService() { TransactionStatus transactionStatus = transactionManager .getTransaction(new DefaultTransactionDefinition()); customerDao.doSomething(); customerDao.doSomethingElse(); transactionManager.commit(transactionStatus); } ►  What happens to the transaction if the DAO }  throws an exception? ►  We might never learn... ►  ...or learn the hard way
  • 5. Weak Transaction Handling: Impact ►  Hard to detect, has effects only if exception is thrown ►  …but then it can lead to wired behavior and data loss etc. ►  Protection against failures is why you are using transactions in the first place ►  This is compromised
  • 6. Solution ►  Declarative transactions public class Service { private CustomerDao customerDao; @Transactional public void performSomeService() { customerDao.doSomething(); customerDao.doSomethingElse(); } }   •  Exception is caught, transaction is rolled back (if it is a RuntimeException) •  Exception handling can be customized
  • 7. A different solution… public void performSomeService() { TransactionTemplate template = new TransactionTemplate( transactionManager); template.execute(new TransactionCallback() { public Object doInTransaction(TransactionStatus status) { customerDao.doSomething(); customerDao.doSomethingElse(); return null; } }); }   Allows for multiple transactions in one method   More code – more control   Rather seldomly really needed
  • 8. #2 Exception Design ►  Get all the details from a system exception! ►  Each layer must only use its own exceptions! ►  Exceptions have to be checked – then they must be handled and the code is more secure. ►  Sounds reasonably, doesn't it?
  • 9. public class OrderDao { public void createOrder(Order order) throws SQLException { // some ugly JDBC code // that I am not going to show } } public class SomeService { public void performService() Get all the details! throws ServiceException { Use checked try { exceptions! orderDao.createOrder(new Order()); } catch (SQLException e) { throw new ServiceException(e); Service must only } throw } ServiceException! } public class SomeController { public void handleWebRequest() { try { What am I supposed to do someService.performService(); now? } catch (Exception e) { No real logging e.printStackTrace(); } And I don’t care about the } specific ServiceException }
  • 10. Impact ►  Lots of useless exception handling code ►  Lots of exception types without specific handling of that type ►  In the end all you get is a log entry ►  …and lots of code ►  And what should the developer do? >  All he knows "Something went wrong" >  Does not really care and can not really handle it
  • 11. Why is this commonplace?   Very few languages have checked exceptions (Java - CLU and Modula-3 had similar concepts)   Checked exception force developers to handle an exception – very rigid   How often can you really handle an exception?   Checked exceptions seem more secure   But: Checked exceptions are overused – also in Java APIs   In many cases there are even no wrong exception concepts in projects – there are just none.
  • 12. Solution   Use more unchecked exceptions aka RuntimeExceptions   Remember: A lot of languages offer only unchecked exceptions   Avoid wrap-and-rethrow – it does not add value   Don't write too many exception classes – they often don't add value   An exception classes is only useful if that exception should be handled differently
  • 13. Solution public class OrderDao { public void createOrder(Order order) { jdbcTemplate.update("INSERT INTO T_ORDER ..."); } } public class SomeService { Where is the public void performService() { orderDao.createOrder(new Order()); exception } } handling? public class SomeController { public void handleWebRequest() { someService.performService(); } }
  • 14. AOP in one Slide @Aspect public class AnAspect { // do something before the method hello // is executed @Before("execution(void hello())") public void doSomething() { } // method hello(), arbitrary return type // in a the class MyService in package de.adesso @Before("execution(* de.adesso.MyService.hello())") public void doSomethingElse2() { } // do something before any method in a class // that ends in Service in any package or subpackage @Before("execution(* *..*Service.*(..))") public void doSomethingElse2() { } }
  • 15. Aspect for Logging @Aspect public class ExceptionLogging { @AfterThrowing(value="execution(* *..*Service.*(..))", throwing="ex") public void logRuntimeException(RuntimeException ex) { System.out.println(ex); } } ►  Logs every exception – 100% guaranteed!
  • 16. Handle only specific cases public class SomeService { public void performService() { try { orderDao.createOrder(new Order()); } catch (OptimisticLockingFailureException ex) { orderDao.createOrder(new Order()); } } } ►  Everything else will be handled somewhere else ►  Can handle specific error conditions using catch with specific types ►  Can be done with AOP
  • 17. Generic Exception Handling public class MyHandlerExceptionResolver implements HandlerExceptionResolver { public ModelAndView resolveException( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { return new ModelAndView("exceptionView", "exception", ex); } } ►  In the web layer ►  Handle all the (Runtime)Exceptions not handled elsewhere
  • 18. #3 Exception Handling public void someMethod() { Exception is not logged try { just written to stdout } catch (Exception ex) { operations might not notice ex.printStackTrace(); } try { } catch (Exception ex) { log.error(ex.getMessage()); Stack trace will be lost } try { } catch (Exception ex) { Exception is swallowed // should never happen comment suggests it would be } } serious error
  • 19. Impact   Related to #2: Bad Exception design will cause more bad exception handling   In the end you just get a message on the console and the application continues.   All kinds of wired behavior   i.e. exception is swallowed   You will have a hard time finding problems in the code   Potentially a huge problem – so worth its own explanation   Usually detected by Findbugs, PMD and the like
  • 20. Solution   At least log exceptions including stack trace   Rethink: Is it really OK to continue after the exception is thrown? Might be better to let a generic handler handle it.   Introduce generic handling at least for RuntimeException (AOP, web front end, etc)   Enforce logging using Findbugs, PMD etc.   And: Improve the exception design (#2) public void someMethod() { try { } catch (Exception ex) { log.error(ex); } }
  • 21. #4   Table of packages and the relations between them   Everything in red is part of a cycle   This is actual code from an Open Source project
  • 23. Dependency Graph ►  Just a small part ►  Red line show circular references
  • 24. What is Architecture? ►  Architecture is the decomposition of systems in parts ►  No large or complex parts ►  No cyclic dependencies
  • 25. Normal Dependencies ►  B dependes on A, i.e. it uses classe, methods etc. ►  Changes in A impact B Component A ►  Changes in B do not impact A Component B
  • 26. Cyclic Dependency ►  B depends on A and A on B ►  Changes in A impact B ►  Changes in B impact A Component A ►  A and B can only be changed as one unit ►  …even though they should be two separate units Component B
  • 27. Bigger cyclic dependencies Component A Component B Component C
  • 28. #4: Architecture Mess   This is effectively one big unstructured pile of mud   Maintenance will be hard   Concurrent development will be hard   Changes will have unforeseeable results
  • 29. Solution   Very hard if you have this state   Therefore: Manage dependencies from the start   Consider Sonargraph or Structure 101   Can even simulate refactorings   Otherwise you are looking at a major restructuring of your application   …which might not be worth it   Effort for restructuring pays off by lower effort for maintenance   …might take a long time to amortize   Throwing away + redevelopment means that you have to migrate to a new solution -> complex and risky
  • 30. The Real Problem: Where Are You Steering? ►  What is the status of your project? ►  Also need to understand test coverage, complexity, coding rules etc ►  Technical debt ►  Should be measured ►  Should not increase ►  Consider Sonar ►  Historized consolidated data from multiple sources ►  Is it getting better or worse? 03.07.11 30
  • 31. 03.07.11 31
  • 32. 03.07.11 32
  • 33. Metrics are not everything   If everything is in one package there will be no cycles   If packages for technical artifact (DAOs, services) might hide cycles in the functional decomposition   If interfaces and implementation are in the same package dependencies to the implementation might slip in.   A cycle with one dependency in the "wrong" direction is different from one with 40 in both directions.   Think about the structure – don't let metric fool you.   Don’t manage or program to the metrics.   Use it as a hint
  • 34. #5 public class ServiceAdaptor { public void performService(OrderDTO orderDTO) { logger.trace("Entering performService"); try { if (orderDTO == null) { throw new NullPointerException("order must not be null"); } if (youAreNotAllowedToDoThis()) { throw new IllegalStateException( "You are not allowed to call this!"); } OrderEntity order = new OrderEntity(); order.setCustomer(orderDTO.getCustomer()); // ... service.performService(order); commandLog.add(new Command("performService", service,order)); } finally { logger.trace("Leaving performanceService"); } } }
  • 35. #5: Adaptor Layer ►  Adds to a service: >  Security >  Tracing >  Check for null arguments >  Log for all commands (auditing, replay…) >  Conversion from DTO to internal representation ►  Lots of boilerplate code for each service ►  Changes to tracing etc. hard: lots of methods to change
  • 36. Solution: Tracing with AOP ►  …or use Spring's predefined TraceInterceptor, DebugInterceptor etc. @Aspect public class TraceAspect { @Before("execution(* *..*Service.*(..))") public void traceBegin(JoinPoint joinPoint) { System.out.println("entering method " + joinPoint.getSignature().getName()); } @After("execution(* *..*Service.*(..))") public void traceEnd(JoinPoint joinPoint) { System.out.println("leaving method " + joinPoint.getSignature().getName()); } }
  • 37. Solution: Null Checks with AOP @Aspect public class NullChecker { @Before("execution(* *..*Service.*(..))") public void checkForNull(JoinPoint joinPoint) { for (Object arg : joinPoint.getArgs()) { if (arg==null) { throw new NullPointerException("Argument was null!"); } } } } ►  Security can be handled with Spring Security or AOP ►  Command log also possible
  • 38. What is left… public class ServiceAdaptor { public void performService(OrderDTO orderDTO) { OrderEntity order = new OrderEntity(); order.setCustomer(orderDTO.getCustomer()); // ... service.performService(order); } }   You should probably switch to Dozer   http://dozer.sf.net   Can externalize mapping rules   i.e. the layer can be more or less eliminated   Everything (mapping, security, tracing…) is now implemented in one place (DRY)   Often services just delegate to DAOs – same issue
  • 39. #6: No DAO public class SomeService { @PersistenceContext private EntityManager entityManager; public void performSomeService() { List<Order> list = entityManager. createQuery("select o from Order").getResultList(); for (Order o : list) { // ... if (o.shouldBeProcessed()) { o.process(); } } } } ►  We don't need to abstract away from JPA – it's a standard, right?
  • 40. #6: Even worse public class SomeServiceJdbc { private OrderDao someDoa; public void performSomeService() throws SQLException { ResultSet rs = someDoa.getOrders(); while (rs.next()) { //... } } } ►  Service depends on JDBC ►  …and throws SQLException ►  Persistence visible in the service layer and beyond
  • 41. Impact   Code is impossible to test without a database   …so no unit tests possible   Service depends on persistence – cannot be ported   How do you add data dependent security?   No structure
  • 42. Solution ►  Use a DAO (Data Access Object) >  Separate persistence layer >  Technical motivation ►  …or a Repository >  Interface to existing objects >  Non technical motivation: Domain Driven Design, Eric Evans ►  Basically the same thing
  • 43. Solution public class SomeServiceDAO { public void performSomeService() { List<Order> list = orderDao.getAllOrders(); for (Order o : list) { // ... if (o.shouldBeProcessed()) { o.process(); } } } } ►  Clear separation ►  Tests easy
  • 44. Solution: Test public class ServiceTest { @Test public void testService() { SomeService someService = new SomeService(); someService.setOrderDao(new OrderDao() { public List<Order> getAllOrders() { List<Order> result = new ArrayList<Order>(); return result; } }); someService.performSomeService(); Assert.assertEquals(expected, result); } }
  • 45. #7 ►  No Tests
  • 46. #7 Or bad tests   No asserts public class MyUnitTest { private Service service = new Service();   System.out: results are checked manually @Test public void testService() {   Tests commented out: Order order = new Order(); They did not run any service.performService(order); System.out.print(order.isProcessed()); more and were not } fixed // @Test   No mocks, so no real // public void testOrderCreated() { Unit Tests // Order order = new Order(); // service.createOrder(order);   No negative cases // } }
  • 47. Impact ►  Code is not properly tested ►  Probably low quality – testable code is usually better designed ►  Code is hard to change: How can you know the change broke nothing? ►  Design might be bad: Testable usually mean better quality ►  Code might be considered tested – while in fact it is not.
  • 48. Solution ►  Write proper Unit Tests! public class MyProperUnitTest { private Service service = new Service(); @Test public void testService() { Order order = new Order(); service.performService(order); Assert.assertTrue(order.isProcessed()); } @Test(expected=IllegalArgumentException.class) public void testServiceException() { Order order = new BuggyOrder(); service.performService(order); } }
  • 49. Wow, that was easy!
  • 50. The real problem…   The idea of Unit tests is over 10 years old   Still not enough programmer actually do real unit tests   Even though it should greatly increased trust and confidence in your code   …and make you much more relaxed and therefore improve quality of life…   Original paper: Gamma, Beck: "Test Infected – Programmers Love Writing Tests"   Yeah, right.
  • 51. Solution ►  Educate >  Show how to write Unit Test >  Show how to build Mocks >  Show aggressive Testing >  Show Test First / Test Driven Development ►  Coach / Review ►  Integrate in automatic build ►  Later on: Add integration testing, functional testing, FIT, Fitnesse etc. ►  …or even start with these
  • 52. What does not really work   Measuring code coverage >  Can be sabotaged: No Asserts… public class MyProperUnitTest { private Service service = new Service(); @Test public void testService() { Order order = new Order(); service.performService(order); } }   Let developers just write tests without education >  How should they know how to test properly? >  Test driven development is not obvious
  • 53. #8: public class OrderDAO { private SimpleJdbcTemplate simpleJdbcTemplate; public List<Order> findOrderByCustomer(String customer) { return simpleJdbcTemplate.query( "SELECT * FROM T_ORDER WHERE name='" + customer + "'", new OrderRowMapper()); } }
  • 54. Impact ►  Performance is bad: >  Statement is parsed every time >  Execution plan is re created etc.
  • 55. Impact: SQL Injection ►  Pass in a' or 't'='t' ►  Better yet: a'; DROP TABLE T_ORDER; SELECT * FROM ANOTHER_TABLE public class OrderDAO { private SimpleJdbcTemplate simpleJdbcTemplate; public List<Order> findOrderByCustomer(String customer) { return simpleJdbcTemplate.query( "SELECT * FROM T_ORDER WHERE name='" + customer + "'", new OrderRowMapper()); } }
  • 56. Solution public class OrderDAO { private SimpleJdbcTemplate simpleJdbcTemplate; public List<Order> findOrderByCustomer(String customer) { return simpleJdbcTemplate.query( "SELECT * FROM T_ORDER WHERE name=?", new OrderRowMapper(), customer); } } ►  … and white list the allowed characters in name ►  to avoid bugs in DB driver etc.
  • 57. #9 ►  "What about Performance?" ►  "Well, we figured the response time should be 2s." ►  "How many request do you expect?" ►  "…" ►  "What kind of requests do you expect?" ►  "..."
  • 58. #9   Software is in the final functional test   Then the performance test start   Performance is too bad to be accepted   You can hardly do anything: >  Changes might introduce functional errors after testing >  Too late for bigger changes   The results might be wrong if the performance test is on different hardware than production.   You can't test on production hardware: Too expensive.
  • 59. Impact ►  You have to get bigger hardware >  Prerequisite: The software is scalable >  Otherwise: Tough luck ►  Worse: You can't go into production
  • 60. Solution   Get number of requests, expected types of requests, acceptable response times   Pro active performance management: >  Estimate performance before implementation >  …by estimating the slow operations (access to other systems, to the database etc) >  Measure performance of these operation in production   Get data from production   Practice performance measurements and optimizations before performance test
  • 61. #10 public class SomeService { private Map cache = new HashMap(); private Customer customer; public Order performService(int i) { if (cache.containsKey(i)) { return cache.get(i); } Order result; customer = null; cache.put(i, result); return result; } }
  • 62. #10 Multiple threads, memory leaks public class SomeService { The cache is filled – private Map<Integer,Order> cache = is it ever emptied? new HashMap<Integer, Order>(); private Customer customer; HashMap is not public Order performService(int i) { threadsafe if (cache.containsKey(i)) { return (Ordercache.get(i); customer is an } instance variable – Order result; multi threading will customer = null; ... be a problem cache.put(i, result); return result; } }
  • 63. Impact ►  System working in small tests ►  In particular Unit tests work ►  But production fails ►  …probably hard to analyze / fix ►  Almost only by code reviews ►  …or extensive debugging using thread dumps
  • 64. Solution   Use WeakHashMap to avoid memory leaks public class SomeServiceSolution {   Synchronize private Map<Integer, Order> cache =   Prefer local variables new WeakHashMap<Integer, Order>();   Usually services can store public Order performService(int i) { synchronized (cache) { most things in local if (cache.containsKey(i)) { variables return cache.get(i); } } Order result = null; Customer customer = null; synchronized (cache) { cache.put(i, result); } return result; } }
  • 65. Solution ►  Also consider ConcurrentHashMap ►  or http://sourceforge.net/projects/high-scale-lib
  • 66. Sum Up ►  #1 Weak Transaction ►  #8 Creating SQL Handling queries using ►  #2 Exception Design String concatenation ►  #3 Exception ►  #9 No Handling performance ►  #4 Architecture Mess management ►  #5 Adaptor Layer ►  #10 Multiple ►  #6 No DAO threads / memory ►  #7 No or bad tests leaks