I have an .ear
file with dozens of EJB jar files in it.
Each EJB jar file has dozens of EJBs in it.
Each EJB has @EJB
references in it with no other information (no name
attribute, etc.).
At the moment everything Just Works: it just so happens that for any given @EJB
-annotated injection target there is exactly one concrete EJB that is present in the .ear
file to fill the slot.
I need for various reasons to introduce a few more EJB jar files that contain EJBs that could also fill some of these slots.
Hence, I need to tell my Java EE container which EJB to inject into which slot where there are conflicts.
I am familiar with the ejb-jar.xml
deployment descriptor mechanism for overriding EJB references but if that is my only recourse I'm looking at changing possibly thousands of these entries.
I noticed in the application.xml
schema version 6 that there is support for <ejb-local-ref>
elements in there, too, which is in some abstract way what I want. But I cannot figure out how to make use of these elements to do what I want.
In some abstract perfect world, I'd like to somehow say, in one place, "Hey, Java EE container, when you see an @EJB
-annotated field like this:
@EJB
SomeType bean;
...please inject the EJB whose beanName
is fred
into it. Everywhere in this application." How do I do that?
There's no standard way to do it and as far as I know, no common vendor-specific way to do it.
This is something i tried to get in in EJB 3.1 for EJB and JPA refs: if an injection point works using the default rules because there's only one SomeType
bean, but then some day a second SomeType
bean is added... to be blunt, you're hosed :) This problem also exists for @PersistenceContext
and @PersistenceUnit
refs. The idea was/is to have some "this is the default impl of SomeType
option in the standard deployment descriptors and bail people out of these situations.
We should still get this into the specification. If this is your problem, I'll repost that proposal and if you can please follow up with information on how much of a nightmare this is for you, I can almost guarantee we'll get this fixed for EJB.next.
For now, one possible approach is to temporarily deploy this ear in TomEE using the flag openejb.descriptors.output=true
. TomEE/OpenEJB will actually give you all the effective deployment descriptors for your application. Could save you several hours or days if your application is as large as you state. Internally we 1) read in the deployment descriptors, 2) use the annotations to "fill out" the deployment descriptors. The result is we have a tree which is the canonical set of "metadata" for each EJB module. With the openejb.descriptors.output=true
flag set, we will write each of these ejb-jar.xml files to disk and log the location.
Once you have your ejb-jar.xml files in hand, you can modify at will and go back to GlassFish and perhaps have better luck.
In terms of how to actually manage this in Java EE, you have to understand how to be successful in overriding references. There's a critical bit of info one needs to know in how annotation references translate to xml. The goal is to have 1 reference and not N.
When your reference is unnamed like so:
package org.some.awesome.code;
public class Foo {
@EJB
SomeType orange;
... there's a fixed rule that the default name of this must be org.some.awesome.code.Foo/orange
. The class name and package become part of the name so as to give you the most fine grained control in overriding. The following xml will override this reference:
<ejb-local-ref>
<ejb-ref-name>org.some.awesome.code.Foo/orange</ejb-ref-name>
<local>org.some.awesome.code.SomeType</local>
<ejb-link>Fred</ejb-link>
</ejb-local-ref>
This reference will now link to the EJB of type SomeType
with the beanName 'Fred'.
The disadvantage of this is that if you have 100 references like this and you want to change them all, you will need 100 declarations in xml to do so.
There's no way out of this problem that doesn't involve changing your code -- this is where my "use this as the default" proposal has value, it would allow one xml change to handle all 100 cases with no code change. It's as simple as being able to say "when I'm not specific in my code, I really mean use X" via the deployment descriptor.
Perhaps by making it legal to declare overrides in xml using just the type, like so:
<ejb-local-ref>
<local>org.some.awesome.code.SomeType</local>
<ejb-link>Fred</ejb-link>
</ejb-local-ref>
As mentioned, this is currently not legal.
There are a few code change approaches available, but one of them is to give each @EJB
ref the same name. Then you will end up with just 1 reference rather than N.
package org.some.awesome.code;
public class Foo {
@EJB(name "purple")
SomeType orange;
Here the name of the reference is explicitly given so overriding it in xml can be done more simply as follows:
<ejb-local-ref>
<ejb-ref-name>purple</ejb-ref-name>
<local>org.some.awesome.code.SomeType</local>
<ejb-link>Fred</ejb-link>
</ejb-local-ref>
If there are 100 @EJB(name="purple")
references, all of them would be overridden by the above declaration.
Short answer, there's currently no easy way out. You're looking at either extensive xml or extensive code change.
Long term, we can hopefully improve this part of the specification so people aren't punished when they grow out of the default matching rules.