...
- OpenEJB provides a default JNDI name to your EJB.
- You can customize the JNDI name.
Default JNDI name
The default JNDI name is in the following format:
Code Block |
---|
{deploymentId}{interfaceType.annotationName}
|
Lets try and understand the above format.
...
Both deploymentId
...
and interfaceType
...
.annotationName are pre-defined variables. There are other pre-defined variables available which you could use to customize the JNDI name format
...
- deploymentId:
- interfaceType:
- annotationName:
...
title | BACK IT UP |
---|
.
JNDI Name Formatting
Excerpt | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
The openejb.jndiname.format property allows you to supply a template for the global JNDI names of all your EJBs. With it, you have complete control over the structure of the JNDI layout can institute a design pattern just right for your client apps. See the Service Locator doc for clever ways to use the JNDI name formatting functionality in client code.
|
Setting the JNDI name
It's possible to set the desired jndi name format for the whole server level, an ejb-jar, an ejb, an ejb's "local" interface (local/remote/local-home/home), and for an individual interface the ejb implements. More specific jndi name formats act as an override to any more general formats. The most specific format dictates the jndi name that will be used for any given interface of an ejb. It's possible to specify a general format for your server, override it at an ejb level and override that further for a specific interface of that ejb.
Via System property
The jndi name format can be set on a server level via a system property, for example:
Panel | ||
---|---|---|
| ||
$ ./bin/openejb start "-Dopenejb.jndiname.format={ejbName}/{interfaceClass}" |
As usual, other ways of specifying system properties are via the conf/system.properties file in a standalone server, or via the InitialContext properties when embedded.
Via properties in the openejb-jar.xml
It's possible to set the openejb.jndiname.format for an ejb-jar jar in a META-INF/openejb-jar.xml file as follows
The short answer is:
- {deploymentId}/{interfaceClass.simpleName}
And typically, deploymentId will be your bean's ejb-name unless you've explicitly set it to something else via an openejb-jar.xml or set the openejb.deploymentId.format to something else.
...
:
Code Block | ||||
---|---|---|---|---|
| ||||
<session><openejb-jar><ejb-name>Calculator</ejb-name> <properties><home>org openejb.acme.CalculatorRemoteHome</home> deploymentId.format = {ejbName}<remote>org openejb.acme.CalculatorRemote</remote> <local-home>org.acme.CalculatorLocalHome</local-home> jndiname.format = {deploymentId}{interfaceType.annotationName}
</properties>
</openejb-jar>
|
Via the <jndi> tag for a specific ejb
The following sets the name specifically for the interface org.superbiz.Foo.
Code Block | ||||
---|---|---|---|---|
| ||||
<openejb-jar> <ejb-deployment ejb-name="FooBean"> <jndi<local>org.acme.CalculatorLocal</local> <ejb-class>org.acme.CalculatorImpl</ejb-class> <business-local>org.acme.CalculatorBusinessLocal</business-local> <business-local>org.acme.CalculatorBusinessLocalTwo</business-local> <business-remote>org.acme.CalculatorBusinessRemote</business-remote> <business-remote>org.acme.CalculatorBusinessRemoteTwo</business-remote> </session> The following names will be bound into JNDI and accessible via the LocalInitialContextFactory:
And these would be available via the RemoteInitialContextFactory
This is the same list minus any interfaces of a local nature as they aren't accessible over a network. Changing the JNDI name formatThe JNDI name format can actually be changed. At current date this can be done on a server-wide basis, but in the future it will be changeable on an application and individual bean basis. To set it for the server, there is a system property called openejb.jndiname.format which understands the following variables:
More variables will be added in the future, such as prettier varieties of ejbType and interfaceType. If there are any you'd like added, feel free to write the dev list. With this you can create a layout for the ejbs in global jndi namespace how ever you like. A couple examples could be:
You are responsible for ensuring the names don't conflict. I.e. if you used something as simple as just "{interfaceClass.simpleName}" for your format it would only work as long as you didn't reuse the interface for any other beans in your app or any other app deployed in the server. If you used "{ejbName}{interfaceClass.simpleName}" you could reuse the interface in other beans but you'd have to guarantee that the ejbName is not already used by another bean in a different app. The default of "{deploymentId}/{interfaceClass.simpleName}" is a pretty safe bet as deploymentId is guaranteed to be globally unique across all apps and beans, however the use of simpleName could cause conflicts if the bean had two interfaces like org.package1.Foo and org.package2.Foo. The safest bet, though not the default as we wanted something short, is to use the fully qualified name of the interface "{deploymentId}/{interfaceClass}". JNDI Name DefaultsMore on the jndi name issue as it relates to proxies.
This is the part that has changed. *Now* we no longer have two separate approaches (all-in-one-proxy vs single-interface-proxy) we have a sort of hybrid approach. In the new approach we still create one proxy per each business interface, but we *also* include all the other business interfaces implemented by the bean class provided none of them conflict. So a bean with four business interfaces gets 4 proxies, each possibly containing all four business interfaces. Recap: each proxy has all the business interfaces your bean implements (provided no conflicts are found), plus the interface the proxy is dedicated to (regardless if the bean implemented it). We create one such proxy for each business interface you have. So what are these conflicts? Business interfaces extending java.rmi.Remote. If you do not have any business interfaces extending java.rmi.Remote *and* you implemented all your business interfaces in your bean class, you are good to go and do not need to be concerned; all your proxies will be guaranteed to be 'all in one' proxies you can cast it to any of the other business interfaces of the same type (type=local vs remote) that bean implements. What's the deal with java.rmi.Remote? The specific issue with java.rmi.Remote interfaces is that pername="foo" interface="org.superbiz.Foo"/>
</ejb-deployment>
</openejb-jar>
|
Or more generally...
Code Block | ||||
---|---|---|---|---|
| ||||
<openejb-jar>
<ejb-deployment ejb-name="FooBean">
<jndi name="foo" interface="Remote"/>
</ejb-deployment>
</openejb-jar>
|
Or more generally still...
Code Block | ||||
---|---|---|---|---|
| ||||
<openejb-jar>
<ejb-deployment ejb-name="FooBean">
<jndi name="foo"/>
</ejb-deployment>
</openejb-jar>
|
The 'name' attribute can still use templates if it likes, such as:
Code Block | ||||
---|---|---|---|---|
| ||||
<openejb-jar>
<ejb-deployment ejb-name="FooBean">
<jndi name="ejb/{interfaceClass.simpleName}" interface="org.superbiz.Foo"/>
</ejb-deployment>
</openejb-jar>
|
Multiple <jndi> tags
Multiple <jndi> tags are allowed making it possible for you to be as specific as you need about the jndi name of each interface or each logical group of iterfaces (Local, Remote, LocalHome, RemoteHome).
Given an ejb, FooBean, with the following interfaces:
- business-local: org.superbiz.LocalOne
- business-local: org.superbiz.LocalTwo
- business-remote: org.superbiz.RemoteOne
- business-remote: org.superbiz.RemoteTwo
- home: org.superbiz.FooHome
- local-home: org.superbiz.FooLocalHome
The following four examples would yield the same jndi names. The intention with these examples is to show the various ways you can isolate specific interfaces or types of interfaces to gain more specific control on how they are named.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<openejb-jar>
<ejb-deployment ejb-name="FooBean">
<jndi name="LocalOne" interface="org.superbiz.LocalOne"/>
<jndi name="LocalTwo" interface="org.superbiz.LocalTwo"/>
<jndi name="RemoteOne" interface="org.superbiz.RemoteOne"/>
<jndi name="RemoteTwo" interface="org.superbiz.RemoteTwo"/>
<jndi name="FooHome" interface="org.superbiz.FooHome"/>
<jndi name="FooLocalHome" interface="org.superbiz.FooLocalHome"/>
</ejb-deployment>
</openejb-jar>
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<openejb-jar>
<ejb-deployment ejb-name="FooBean">
<!-- applies to LocalOne and LocalTwo -->
<jndi name="{interfaceClass.simpleName}" interface="Local"/>
<!-- applies to RemoteOne and RemoteTwo -->
<jndi name="{interfaceClass.simpleName}" interface="Remote"/>
<!-- applies to FooHome -->
<jndi name="{interfaceClass.simpleName}" interface="RemoteHome"/>
<!-- applies to FooLocalHome -->
<jndi name="{interfaceClass.simpleName}" interface="LocalHome"/>
</ejb-deployment>
</openejb-jar>
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<openejb-jar>
<ejb-deployment ejb-name="FooBean">
<!-- applies to RemoteOne, RemoteTwo, FooHome, and FooLocalHome -->
<jndi name="{interfaceClass.simpleName}"/>
<!-- these two would count as an override on the above format -->
<jndi name="LocalOne" interface="org.superbiz.LocalOne"/>
<jndi name="LocalTwo" interface="org.superbiz.LocalTwo"/>
</ejb-deployment>
</openejb-jar>
|
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<openejb-jar>
<ejb-deployment ejb-name="FooBean">
<!-- applies to LocalOne, LocalTwo, RemoteOne, RemoteTwo, FooHome, and FooLocalHome -->
<jndi name="{interfaceClass.simpleName}"/>
</ejb-deployment>
</openejb-jar>
|
Changing the Default Setting
You are responsible for ensuring the names don't conflict.
Conservative settings
A very conservative setting such as "{deploymentId}/{interfaceClass}" would guarantee that each and every single interface is bound to JNDI. If your bean had a legacy EJBObject interface, three business remote interfaces, and two business local interfaces, this pattern would result in six proxies bound into JNDI.
Similarly conservative settings would be:
- {deploymentId}/{interfaceClass.simpleName}
- {moduleId}/{ejbName}/{interfaceClass}
- {ejbName}/{interfaceClass}
- {moduleId}/{ejbClass}/{interfaceClass}
- {ejbClass}/{interfaceClass}
- {ejbClass}/{interfaceClass.simpleName}
- {ejbClass.simpleName}/{interfaceClass.simpleName}
- {interfaceClass}/{ejbName}
Bordeline optimistic:
- {moduleId}/{interfaceClass}
- {interfaceClass}
The above two settings would work if you the interface wasn't shared by other beans.
Pragmatic settings
A more middle ground setting such as "{deploymentId}{interfaceType.annotationName}" would guarantee that at least one proxy of each interface type is bound to JNDI. If your bean had a legacy EJBObject interface, three business remote interfaces, and two business local interfaces, this pattern would result in three proxies bound into JNDI: one proxy dedicated to your EJBObject interface; one proxy implementing all three business remote interfaces; one proxy implementing the two business local interfaces.
Similarly pragmatic settings would be:
- {moduleId}/{ejbClass}/{interfaceType.annotationName}
- {ejbClass}/{interfaceType.xmlName}
- {ejbClass.simpleName}/{interfaceType.xmlNameCc}
- {interfaceType}/{ejbName}
- {interfaceType}/{ejbClass}
Optimistic settings
A very optimistic setting such as "{deploymentId}" would guarantee only one proxy for the bean will be bound to JNDI. This would be fine if you knew you only had one type of interface in your beans. For example, only business remote interfaces, or only business local interfaces, or only an EJBObject interface, or only an EJBLocalObject interface.
If a bean in the app did have more than one interface type, one business local and one business remote for example, by default OpenEJB will reject the app when it detects that it cannot bind the second interface. This strict behavior can be disabled by setting the openejb.jndiname.failoncollision system property to false. When this property is set to false, we will simply log an error that the second proxy cannot be bound to JNDI, tell you which ejb is using that name, and continue loading your app.
Similarly optimistic settings would be:
- {ejbName}
- {ejbClass}
- {ejbClass.simpleName}
- {moduleId}/{ejbClass.simpleName}
- {moduleId}/{ejbName}
Advanced Details on EJB 3.0 Business Proxies (the simple part)
If you implement your business interfaces, your life is simple as your proxies will also implement your business interfaces of the same type. Meaning any proxy OpenEJB creates for a business local interface will also implement your other business local interfaces. Similarly, any proxy OpenEJB creates for a business remote interface will also implement your other business remote interfaces.
Advanced Details on EJB 3.0 Business Proxies (the complicated part)
Info | ||||
---|---|---|---|---|
| ||||
Read this section of either of these two apply to you:
If neither of these two items describe your apps, then there is no need to read further. Go have fun. |
Not implementing business interfaces
If you do not implement your business interfaces it may not be possible for us to implement all your business interfaces in a single interface. Conflicts in the throws clauses and the return values can occur as detailed here. When creating a proxy for an interface we will detect and remove any other business interfaces that would conflict with the main interface.
Business interfaces extending javax.rmi.Remote
Per spec rules many runtime exceptions (container or connection related) are thrown
...
from javax.rmi.Remote proxies as java.rmi.RemoteException which is not a runtime exception and must be throwable via the proxy as a checked exception. The issue is that conflicting throws clauses are actually removed for two interfaces sharing the same method signature. For example
...
two
...
methods such as these:
...
- InterfaceA: void doIt() throws Foo;
...
- InterfaceB: void doIt() throws RemoteException;
can be implemented by
...
trimming out
...
the
...
conflicting throws clauses as follows:
- Implementation: void doIt(){}
This is fine for a bean class as it
...
does not need to throw the RMI required javax.rmi.RemoteException.
...
However if we create a proxy from these two interfaces it will also wind up with a 'doIt(){}' method that cannot throw javax.rmi.RemoteException.
...
This is very bad as the container does need to throw RemoteException
...
to any business interfaces extending java.rmi.Remote
...
for any container related issues or connection issues. If the container attempts to throw a RemoteException from the proxies 'doIt(){}' method, it will result in an UndeclaredThrowableException thrown by the VM.
...
The only way to guarantee the proxy has the 'doIt() throws RemoteException {}' method of InterfaceB is to cut out InterfaceA when we create the proxy dedicated to InterfaceB
...
.
Excerpt |
---|