Single Entry Point to EJB Layer pattern
This pattern forces the client to use a single entry point to perform the calls to EJBs.
Motivation:
Precisely manage the user access to an application with a dynamic verification of security and session state with full transparency for client’s developers.
This architecture was first designed to be used with a heavy client in Swing. It can easily be modified for a web based client.
Solution :
The main components of this architecture are :
User:
This entity represents a user of the application. It holds authorisation informations as well as session state.
SessionManagementService :
This stateless service is a factory of user sessions. Security can be plugged in to verify the authorization to a particular user to obtain a Session.
UserSession :
This stateful bean is the real facade of the application. Each client call is passed through its two main methods :
public Object invoke(EJBDefinition p_service, String p_methodName, Class[] p_paramTypes, Object[] p_args)
public Object invoke(ServiceKey p_serviceKey, String p_methodName,Class[] p_paramTypes ,Object[] p_args)
This facade can check the connection state of the user (an administrator can dynamically lock a user) and the users authorization to perform this call using the User EJB.
This component holds a cache on the services ( stateful or stateless).
The first method is used for the call on SLSB services, the second for SFSB services.
Services :
The services are implemented as stateful or stateless EJB. SLSB services have a ejbCreate method without any argument. SFSB services are created through a call on a SLSB service.
All the SLSB are defined in an interface of constants.
public interface Services {
final static EJBDefinition MESSAGING_SERVICE =
newEJBDefinition("ejb/framework/MessagingService",
"org.z.framework.jms.MessagingServiceHome",
"org.z.framework.jms.MessagingService");
….
UserSessionClient :
This singleton is instantiated only on the client side.
It first asks the SessionManagementService to create a new UserSession and then maintains a reference on this Session to transmit all the client calls.
ClientServiceFactory :
When an object on the client side needs a service to perform a task it asks it to this factory through the call :
messageService = (MessaggingService)ClientServiceFactory.getService(Services.MESSAGGING_SERVICE);
The return of this call is the remote interface of the SLSB service. In fact the object is a dynamic proxy ( see java.lang.reflect.Proxy ) with a ServiceClient as InvocationHandler.
ServiceClient :
This class implements the java.lang.reflect.InvocationHandler and is beside all the remote interface of EJB on the client side.
Every time the client makes a call on an remote interface an instance of this class extracts the method called and the arguments and transmits it to the UserSessionClient.
Normal sequence :
1. A client JVM which needs remote services initiate the session with its UserSessionClient :
UserSessionClient.getInstance().init( userLogin, userPassword);
The SessionManagementService after security checking creates a new UserSession. The remote reference on it is kept in the UserSessionClient.
2. The client needs a service to perform a task. It asks it to the ServiceFactory.
messageService = (MessaggingService)ClientServiceFactory.getService(
Services.MESSAGGING_SERVICE);
A new dynamic proxy is created using the EJBDefinition. The InvocationHandler of this dynamic proxy is a new instance of ServiceClient.
3. The client makes a call on his remote interface.
MessageService.sendMessage("toto");
The ServiceClient transmits all the parameters (the EJBDefinition, the method name, the arguments ) of this call to the UserSessionClient.
The UserSessionClient transmits everything to the UserSession.
The UserSession which does not have any reference on the service performs a lookup to retrieve a reference on the Home of the service and call "create" on it.
Then using reflection it invokes the method.
Consequences :
·The client code to access remote service is extremely simple,
·Any kind of control can be plugged on the client calls.