The 8 years old J2EE was designed before annotations and built on interfaces and lots of XML. An average J2EE application used several J2EE Patterns to separate the business logic from the necessary plumbing. The (now ancient) J2EE technology also required the existence of thousands of lines of XML which tied the separate parts together. The XML code, as well as some of the patterns (like Session Facade, Service Activator or Business Delegate) were automatically generated with tools like xdoclet. Some of the patterns like Domain Store, Service Locator were replaced by built-in APIs (e.g. EntityManager, EJB 3.1), others like DAO, BusinessObject or DTO became optional but were not hard to implement.With a pragmatic migration from J2EE to Java EE you can delete more than 60% of the old "pattern" code and the entire XML code without sacrificing any functionality. The deleted code became superfluous, because Java EE 6 is "clean" and does not require any further abstractions, indirections or wrapping. The deleted code was also obvious, trivial, mostly generated and therefore also mostly bug-free. The remaining functionality usually contains non-obvious business logic and so more likely …bugs. This increases significantly the "bugs per kloc" metric. Although the quality and maintainability of a migrated Java EE 6 application is higher, ancient J2EE code looks from the statistical QA-angle better. So beware of metrics. …in worst case you could generate obvious interfaces, XML and indirections to make the "bugs per kloc" statistics better :-). [See also chapter "Retired Patterns", page 131 in Real World Java EE Patterns - Rethinking Best Practices book]
On demand workshops: Java EE 7: Bootstrap, Effective, Testing and Microservices available for streaming.