the EJBServices class contains static fields holding every EJB's jndi name, home class and an INT "code" to identify the EJB.
The class itself may require a bit extra coding work
But in large projects its convenient that:
All changes to jndi names and classes are done in one place
Keeping the service Locator's code generic and clean
And very helpful for the client side developers
example: (try 2 ignore the syntax)
the following example shows the EJBservices Implementation class, it encapsulate ejbs home names and classes
note: the example consist of one ejb - ProcessManager
public class EJBServices{
static final int ProcessManager = 1;//the ejb's "service code"
static final Class ProcessManagerClass = //home's class
ProcessManagerHome.class;
static final String ProcessManagerName = //ejb's jndi name
"ProcessManagerHome";
//this method takes an int code and return the bean's the Home class
public static Class getHomeClass(int service){
switch( service ){
case EJBServices.ProcessManager :
return ProcessManagerClass;
}
return null;
}
//this method again takes the code and return the jndi name
public static String getJndiName(int service){
switch( service ){
case EJBServices.ProcessManager :
return ProcessManagerName;
}
return null;
}
business delegate:
the business delegate simply invoke the serviceLocator's
getService() method to get the EJBObject
public class aDelegate{
ServiceLocator services;
ProcessManager managerEJB; //ejb remote interface
public aDelegate(){
services = new ServiceLocator();
managerEJB = (ProcessManager)
services.getService(EJBServices.ProcessManager);
}
Service Locator:
you all know this pattern
though here i suggest to implement it as a simple pojo
and not as a singleton , since the EJBHome factory is a singletone that caches the home interfaces.
and the Service Locator is also used to gain access to dataSources etc, so in my opinion in an enterprise application it should be a simple pojo
......
EJBObject getService(int service){
Class homeClass = EJBServices.getHomeClass(service);
String jndiName = EJBServices.getJndiName(service);
EJBHome home = EJBHomeFactory.getInstance()
.getHome(homeClass,jndiName);
return home.create();
.......
EJBHomeFactory:
the home factory is simply a singletone that caches the ejb's home in a map.
like -
getHome(Class homeClass,String jndiName){
EJBHome home =
(EJBHome)PortableRemoteObject.narrow(
ctx.lookup(jndiName),homeClass);
looking forward to your opinions
regards
Alon.
-
EJBServices class - encapsulating EJBHomes jndi names & classes (5 messages)
- Posted by: Alon Agmon
- Posted on: November 21 2004 04:38 EST
Threaded Messages (5)
- But JNDI Names are also in DD by Ajith Kallambella on December 01 2004 12:48 EST
- EJBServices class - encapsulating EJBHomes jndi names & cla by Jeff Drost on December 08 2004 17:41 EST
- RE: EJBServices class by Peter Cheng on December 12 2004 08:46 EST
- Another implementation of the pattern by Archimedes Trajano on August 09 2005 21:12 EDT
- EJBServices class - encapsulating EJBHomes jndi names & classes by Rod Johnson on February 28 2005 11:35 EST
-
But JNDI Names are also in DD[ Go to top ]
- Posted by: Ajith Kallambella
- Posted on: December 01 2004 12:48 EST
- in response to Alon Agmon
Good idea!
You say
"All changes to jndi names and classes are done in one place Keeping the service Locator's code generic and clean
And very helpful for the client side developers"
However, JNDI names primarily come from the Deployment descriptor. That makes it two places. It would be nice if EJBServices.java can be generated from the DD, but then you have another level indirection between the JNDI names and the int constants clients use.
I strongly believe there is some scope for auto-generation of either the java file it self, or some sort of an external mapping file.
Cheers,
-Ajith Kallambella -
EJBServices class - encapsulating EJBHomes jndi names & cla[ Go to top ]
- Posted by: Jeff Drost
- Posted on: December 08 2004 17:41 EST
- in response to Alon Agmon
If an EJB gets un-deployed and then redeployed, caching home interfaces can be problematic. If this is really expected to be an expensive call (which it is not *within* most app servers) then you may want to add some retry logic.
Also, why define this numeric mapping rather than a flyweight that contains both the JNDI name and the home interface class?
public static final Foo FOO = new Foo("ProcessManagerHome", ProcessManagerHome.class); -
RE: EJBServices class[ Go to top ]
- Posted by: Peter Cheng
- Posted on: December 12 2004 08:46 EST
- in response to Alon Agmon
IMO, we can use ServiceLocator as a lower-level service and encapulate with EJBService, so that we can invoke EJB more simpler:
For example:
public class EJBService {
private ServiceLocator serviceLocator;
public EJBService (ServiceLocator serviceLocator) {
this.serviceLocator = serviceLocator;
}
public Object getRemoteObject(String jndiName) throws EJBException {
try {
EJBHome ejbHome = serviceLocator.getRemoteHome(jndiName, EJBHome.class);
//get the method of create
Method method = ejbHome.getClass().getDeclaredMethod("create",
new Class[0]);
Object obj = method.invoke(ejbHome, new Object[0]);
return obj;
} catch (ServiceLocatorException e) {
throw new EJBException(e);
} catch (SecurityException e) {
throw new EJBException(e);
} catch (IllegalArgumentException e) {
throw new EJBException(e);
} catch (NoSuchMethodException e) {
throw new EJBException(e);
} catch (IllegalAccessException e) {
throw new EJBException(e);
} catch (InvocationTargetException e) {
throw new EJBException(e);
}
}
}
Use EJBService
public interface FooEJBExample extends EJBObject
{
/**
*
* This gets content
*
* @param name <code>String</code> name for greeting
* @return string which makes up "Hello, name"
*/
public String hello ()
throws RemoteException;
}
FooEjbExample obj =
(FooEjbExample) myEJBService.getObj ("java:comp/env/FooEjbExample");
obj.hello -
Another implementation of the pattern[ Go to top ]
- Posted by: Archimedes Trajano
- Posted on: August 09 2005 21:12 EDT
- in response to Peter Cheng
I wrote up an article/blog entry discussing how to implement the pattern.
http://www.trajano.net/2005/08/ejb-pattern-service-locator-with.html
It is similar to what you already have except I detailed with test cases and a step by step approach of how to get there. Its a multipart article, the next article will be discussing optimizations to the codebase. -
EJBServices class - encapsulating EJBHomes jndi names & classes[ Go to top ]
- Posted by: Rod Johnson
- Posted on: February 28 2005 11:35 EST
- in response to Alon Agmon
Have you seen how Spring handles this: client-side EJB access with zero coding. You simply specify the business interface and JNDI name in a config file, and Spring automatically calls home.create() and generates a proxy. Calling code is decoupled from the EJB API, depending only on the business methods interface (typically the superinterface of the EJB component interface, and typically not aware that EJB will be used to implement it). No more Service Locator or Business Delegate custom code.
Rgds
Rod