Patterns are the problem/solution pairs to enable reuse of software designs and techniques. There are probably many differing software design patterns we all use regularly, some without even knowing. Here we focus on the Service Locator and Service Delegate design patterns.
The J2EE pattern
Use a Service Locator object to abstract all JNDI usage and to hide the complexities of initial context creation, EJB home object lookup, and EJB object re-creation. Multiple clients can reuse the Service Locator object to reduce code complexity, provide a single point of control, and improve performance by providing caching facility.
The Service Locator provides and caches the InitialContext and simplifies access to the session bean remote interface using the remote JNDI name lookup. It does also provides the facility to get the local interface.
When a client or the presentation tier requires access to the business tier, it makes use of the Business Delegate pattern. Business Delegates, or Service Delegates here, use the Service Locator object to locate business components. This provides loose coupling and increased manageability from the client/web tier to the business tier.
Until web containers provide the means to inject session beans within their processing context, the best way to invoke business logic is via service delegates.
The EJB3 cartridges cuts down the service delegates which references the service locator and provides the ability to invoke all available methods on the appropriate view interface of the session bean.
The following example is taken directly from the exception howto. Only the relevant files are referenced here.
The following is an example of how you can use the Service Delegate RentalServiceDelegate above in a client or in the web tier.
Properties prop = new Properties(); prop.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory"); prop.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces"); prop.put("java.naming.provider.url", "localhost:1099"); RentalServiceDelegate manager = new RentalServiceDelegate(prop); try { manager.getCustomersByName("john"); } catch (RentalException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (manager != null) { manager.close(); } }
In circumstance where you have manageable entities, a ManageableServiceLocator class will also be generated with similar logic as the ServiceLocator class, except it used the remote interface of the manageable service bean.
To find out how you can use interceptors in entity, session and message-driven beans, click here.