Questions Applicable to All Scenarios Above
- What is the application assembler supposed to do in general here?
- How does she know what configuration properties are being requested by the Jakarta EE components?
- How does she know that each component is expecting a different sort of thing or behavior under the same name?
- How does she know what Converters are in the picture? Can she somehow override them? (Remember, in case it matters, that the application assembler as defined in the Platform Specification doesn't write or compile code.)
- How does she reconcile all this? That is, how does she, or someone playing the configuration author role, write appropriate configuration for each scenario that satisfies each component?
- What if component-supplied Converters have priorities of Integer.MAX_VALUE? (How would she know?)
In order to try and address these questions, I'll coerce them into draft use cases/user stories. Note that the following are drafts; I'm not endorsing any particular use case (yet) unless stated specifically within each use case. This is mainly a way to try and capture the ideas presented above in this format.
As a component developer, I must be able to specify which configuration properties are required and which are optional, along with their types, so that the configuration may be validated.
Yes. This story is part of the Jakarta EE platform already and manifested currently via the (apparently clunky, tedious) capabilities of JNDI, the @Resource annotation, and various deployment descriptors that can override those annotations.
This is the foundational capability which enables all of these requirements. Without this type of validation, it is not possible to know what properties are being requested, and which are required.
Yes. It should also be noted that the namespace and names involved in this story are those of the component, not necessarily of the application (see Story 4). The scenarios I chose featured (deliberately) components asking for different semantic configuration named with the same name. Jakarta EE via JNDI provides a way to remap such configuration without requiring changes to the components. For example, you can say @Resource(name = "x") and the deployer can, using various other clunky Jakarta EE features and deliberately unstandardized features of her product/appserver, map that to "y". The @Resource annotation itself was updated some time ago to permit this kind of remapping to occur from within the component in the case that the remapping and product are already known by the component developer (@Resource(name = "x", mappedName = "y")).
As an application assembler, I must be able to know which configuration properties are expected by each component so that I can ensure that all of the necessary configuration can be provided.
Yes. Additionally, when component 1 asks for "status", and component 2 asks for "status", but "means" something different by "status", I the application assembler must be able to do something about this incompatible state of affairs (Story 4 again). Jakarta EE currently enables this, or at least waves its hands at it, via a combination of the name, description and type attributes of the @Resource annotation (together with the various deployment descriptor ways of overriding this). Because the binding-of-things-into-the-JNDI-tree-for-a-given-product is (deliberately) not standardized, the application assembler and deployer have some flexibility here currently.
As Laird noted, the assembler may not be able or willing to examine the source code of the component (it is not part of their role).
Right. The Jakarta EE platform as currently (9.1) constituted is a binary artifact platform, so it deliberately presumes throughout that no one but the component developer has the source code.
Thus, if this is a valid use case, there would need to be some kind of tooling or automated means for the assembler to examine the total set of properties that are required by an application which is available *before* deployment.
That's right. Did such a tool ecosystem ever emerge in "classic" Java EE? Not to my knowledge but I'm not an appserver guy of any particular kind.
I'm not sure that I agree with this use case. It is arguably useful, but it might not be practical to implement.
It's in the platform already. We can choose to break with this aspect of the platform, of course, and say, well, you just have to "know" what the properties are via documentation or something else. We must do this deliberately if we do it, especially if we do not provide any means for remapping of component namespaces to application namespaces.
As an application deployer, I must know that the configuration of the component is valid before deployment completes, in order to prevent the application from starting with an incorrect or inconsistent configuration, or even worse, a security vulnerability.
Yes. If you look carefully at the separation of the deployer and assembler roles, the broad work here really happens in application assembly. In classic Java EE, the application assembler would, as an arbitrary but related example, remap component namespace references to security roles into an application-defined security role (so component 1's "admin" and component 2's "superuser" become the application's "god", and all the deployer "sees" and has to worry about is mapping "god" to her LDAP system's "root". No code changes; no archives are cracked—a big concern back in the day.).
As an application assembler, I must have a means to resolve namespace conflicts between components, so that I can package components that are not aware of each others' namespace usage.
It is proposed above that it is feasible that two components may consume properties with the same name but with different types and/or semantics. Presumably, without a means to resolve such an ambiguity, the burden would fall on the component developers to be aware of one another and to coordinate property names and namespaces among themselves - something which may or may not be feasible.
That's right; a classic Java EE issue that shows up throughout the platform.
Nevertheless I am not sure I agree with this use case. On the one hand, it may be possible to resolve the problem by (for example) providing the application assembler with a means to namespace each component, or to somehow provide distinct configurations on a per-component basis. I don't think that this is the right solution to the problem though; both would add a burden of complexity to the assembly job while not really addressing the fundamental cause of the problem - rather working around it.
It's in the platform today in several places for good or bad.
Laird, do these use cases adequately capture all of the ideas you are trying to convey? Is something missing or misrepresented?
Nothing is misrepresented, and basically nothing is missing; you've reformulated my questions well; thanks for that.
As I hope I've pointed out above, there are some use cases that you (and others) are hesitant to implement, but that are in the platform today for better or for worse, so maybe one other nuance here is that we need to say something like: the underpinnings of the Jakarta EE platform that are currently required to be present in all Profiles of the Platform according to the Platform Specification (JNDI and Transactions) are no longer relevant, because time has shown that binary-component-oriented development with all of the remapping headaches is something no one cares about anymore. (If the answer to most questions is, "change [or look at] the source code", then great hunks of the existing platform go right out the window for better or for worse.)
To put it another way: given that you can implement a tree-structured arbitrarily-typed key-value configuration lookup system today in JNDI with arbitrary object binding semantics and any backend you want, why would you use anything else? There are, of course, answers. (I hope the answers are better than "because Context returns Object from some lookup() methods and it looks ugly to me".)
For clarity: I'm not defending JNDI the product or JNDI the API, but just noting that it is currently a part of all profiles in the platform and has these binary-component-oriented use cases at its core and addresses them. If we're looking to replace JNDI for configuration, then we are honor-bound to make sure we handle the same use cases, or adjust the platform so that those use cases are no longer required to be supported.