A user pointed out a couple days ago that we weren't supporting
inheritance of business interfaces, which we totally should be. I
thought since we were delayed on the 3.0 release that I would get this
fixed.
Our support for ejb inheritance in general has been pretty weak so
I've cooked up a simple test case like the following:
http://svn.apache.org/repos/asf/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/config/InheritenceTest.java
In the process of trying to get that implemented with the code the way
we have it structured now (i.e. translating annotations to xml,
respecting overriding rules, and dealing only with xml thereafter), it
occurred to me the subject of how xml and annotations relate to
inheritance and overriding was unclear at best.
I finally wrapped my head around the subject and realized the spec is
incomplete in this regard. Below is a chunk of text I sent to the EJB
3.1 EG which I thought I'd share with everyone so we can all become
experts in this particular area of EJB. Obviously, the discussion
that ensues on the Expert Group I cannot share, so don't ask for
updates -- you'll have to wait for public spec reviews like everyone
else :)
As far as OpenEJB is concerned what I detailed in Point 1 is simply
more specific than than what is already in the spec and we can
actually implement now without breaking compliance. We can add and
use the proposed <class> element of <method> internally, marking it as
@XmlTransient so it can't be read or written. It will allow us to
implement the inheritance rules already in the spec without having to
have separate rules for annotations versus xml. Should it become part
of the spec some day, we can yank the @XmlTransient flag and the
feature will instantly be available to users to use in their ejb-
jar.xml.
A very detailed heads up, and of course thoughts are welcome.
-David
- - - - - - -
Point 1: There is no equivalent ability in the xml to respect
inheritance.
- - - - - - -
Here's the transaction example from section 13.3.7.1:
@TransactionAttribute(SUPPORTS)
public class SomeClass {
public void aMethod () {...}
public void bMethod () {...}
...
}
@Stateless public class ABean extends SomeClass implements A {
public void aMethod () {...}
@TransactionAttribute(REQUIRES_NEW)
public void cMethod () {...}
...
}
Assuming aMethod, bMethod, cMethod are methods of interface A, their
transaction attributes are REQUIRED, SUPPORTS, and REQUIRES_NEW
respectively.
Given an xml override like the following, I would expect the
transaction attributes of aMethod, bMethod and cMethod to change to
MANDATORY, MANDATORY, and REQUIRES_NEW respectively.
<container-transaction>
<trans-attribute>Mandatory</trans-attribute>
<method>
<ejb-name>ABean</ejb-name>
<method-name>*</method-name>
</method>
</container-transaction>
There is no ability to override/specify the transaction attribute of
SomeClass class specifically, leaving ABean untouched. Yes, one could
add individual method xml overrides for every single method of
SomeClass, but that is brittle; easy to add or remove and forget to
update the xml and making sure you've covered every method could be a
very manual, time consuming, and error prone process.
The same applies to security constraints.
We should consider adding a <class> element to <method> so a given
class in the inheritance chain could be targeted, such as:
<container-transaction>
<trans-attribute>Mandatory</trans-attribute>
<method>
<ejb-name>ABean</ejb-name>
<class>SomeClass</class>
<method-name>*</method-name>
</method>
</container-transaction>
Which would change the transaction attributes of aMethod, bMethod and
cMethod to change to REQUIRED, MANDATORY, and REQUIRES_NEW respectively.
- - - - - - -
Point 2: There is no ability in annotations to disregard inheritance.
- - - - - - -
Given the same example above with ABean subclassing from SomeClass,
via xml we have the ability to set the base transaction attribute for
both in one swoop as follows:
<container-transaction>
<trans-attribute>Mandatory</trans-attribute>
<method>
<ejb-name>ABean</ejb-name>
<method-name>*</method-name>
</method>
</container-transaction>
There is no equivalent way to do the same via annotations on just the
ABean class. Yes, it is possible to use java overriding in ABean
class on each method of SomeClass, but this is also a bit brittle;
it's easy for someone to add a method to SomeClass and forget to
revisit every subclass of SomeClass and add the required override
which again is error prone and time consuming.
Again, the same applies to security annotations.
I'm not sure on a good name, but we could add another attribute to the
transaction and security annotations that allow the user to state
they'd like the annotation to apply to the annotated class and all
ancestors as well which would achieve the same result as the above xml
declaration.