We are currently in the process of analyzing the technical requirements for a new version of a Java EE application. It's Java EE 6, but moving onto 7 is an option. Until now this was a single application, one EAR, offering well-defined functionality. However, it needs to become possible to define some functionality in a very specific way based on implementation project and/or customer.
For example, some customers are going to have very specific security constraints. A list of messages processed by a framework can be shown. For one customer, it's okay to have users see everything, but another customer would like to show only certain types of messages based on the user's group. That's an example of defining an implementation in a context-specific way, adapting the core functionality. Another possible requirement is that some customers will want to expand on the given functionality, adding new possibilities. So that's the extensible part.
Because of this, it is necessary to have an architecture that defines generic functionality but has pluggable parts, as well as a possibility for extension. For some aspects I have a rough idea of how this could be handled. This question has an answer that would work perfectly for the presentation layer, which we'll do in JSF 2: How to create a modular JSF 2.0 application?
I'm less certain about the business logic layer, security etc. My initial idea would be to define interfaces (a couple of facades) and find the implementation at run-time or deployment time. In much the same way as the service provider mechanism. A default implementation can be offered, with the possibility of defining a custom one. This does feel like a sort of Java SE solution, and I'm wondering if I'm just applying concepts that I'm familiar with from that context and if there's nothing better for EE. I think the @Alternative
annotation serves a purpose like this.
Another possibility might be to use interceptors and decorators. I'm not certain to what extent interceptors are useful outside of logging, auditing and other things that don't touch the core business logic. Decorators seem suitable for allowing an implementation to be extended with custom functionality, and perhaps also the pluggable parts.
Can someone offer some insight into which solution is best for which part of this challenge? Should I combine these methods for various parts of the problem domain? Are there possibilities I'm not seeing?
An important requirement: we want to make it possible to keep the code that is specific to a customer/project separate. We don't want to have a complete version of the application under version control for each implementation, as that would become a maintenance nightmare fast. Ideally, it would also not be necessary to build this as a monolithic EAR, but be capable of adding pluggable parts to some lib folder or deploy them separately.