Continuing the EJAPP Top 10 countdown, it's time to talk about number 8. Apart from leading to badly architected applications, incorrect usage of Java EE can also cause your application to perform poorly. This problem is particularly prevalent in older applications that were developed before the POJO/lightweight revolution a few years back. Lightweight frameworks like Spring allow the developer to pick and choose the infrastructure services (transactions, security, distributed objects) that are needed. Java EE (or J2EE as we used to call it) offers all of them all of the time. Application servers are tuned to not spend a lot of CPU cycles on the infrastructure services that are not used, but some developers succumb to the temptation to use these features when they are not needed. Not helping all this are the "best practices" that came into being with the first J2EE versions, e.g. Sun's J2EE patterns.
Some of the ways in which Java EE is used incorrectly are:
- Using remote EJB's when local EJB's would suffice. Since EJB 2.0 it is possible to give an EJB a local interface thereby introducing call by reference. Most application servers (BEA Welogic 9.2, IBM WebSphere 6, and Oracle OC4J) can be configured to also use call by reference for remote objects. This improves performance but changes the method invocation semantics.
- Using the Session Facade pattern incorrectly. This pattern was introduced to circumvent the latency of remote method calls. If improperly implemented (e.g. by having exactly one session facade to access all EJB's), this session bean becomes a bottle neck when the number of sessions beans is limited.
- The EJB n+1 problem. When following relations, EJB before 2.0 suffered from the problem that to load a table n+1 queries were used: 1 to get the IDs for the objects to be loaded, and then another query for each of those objects to load the data. Of course, this has a huge negative impact on the performance of your application!
- Home grown frameworks. Because Java EE, and especially the older version, offered such a poor programming model, a lot of home grown frameworks have been written. Although these form a central part of the application, not all of them are tested for performance.
There are two remedies to this problem:
- When using Java EE as a programming model, use only the parts you really need and avoid the antipatterns mentioned above (and a lot of others).
- Even better, use a light weight framework such as the Spring framework and use Java EE as an application server interface only. This has the advantage that you can rid of a lot of other obsolete patterns:
- Service Locator and Business Delegate are obsolete when using dependency injection.
- Fast Lane Reader and Transfer Object can be dropped in favour of a proper ORM layer like Hibernate or the Java Persistence API.
- Front Controller because the Spring framework has its own.
- Intercepting Filter makes sense for servlets, but you can AOP for most other stuff.