Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

The COR Pattern Puts Your J2EE Development on the Fast Track : Page 3

Find out how the "Chain Of Responsibility" pattern can rein in your beans and facades to meet evolving business requirements. Route client requests transparently to EJB server components without hardwiring client/server interactions or worrying about low-level plumbing issues.


advertisement
Put COR into Practice
Step 1. Define Your Command Structure
Lay down a common marker interface for all your commands. Ensure your interface extends the Java interface Serializable so that it can be passed over remote boundaries. Your command interface forms the basis for your command hierarchy or structure. It should provide:
  • A mechanism for setting request parameters and getting request results
  • A method to specify whether the command is transactional
  • Any additional methods to assist the COR implementation

Create your Command base interface:

public interface Command extends Serializable{ /** * Get the command params(s) */ public Object getArg(); /** * Get the results of the command being executed */ public Object getResult(); /** * is true if this command should be executed transactionally in the App server * false otherwise */ public boolean isTransactional(); public String getServiceManagerName(); public void setServiceManagerName(String name); }



All commands wishing to make use of the COR component must implement the Command interface. You may define as many command classes as you deem appropriate for your application. Think of your commands as the external interface into your business services, analogous to Session Facades.

Fine-grained vs. Coarse-grained Commands
Be careful with your command granularity. Make them too fine grained and you will have an almost one-to-one correspondence between a command and a method, which will quickly become unsustainable. Being overrun by commands is no different from bloated facades—it's hard to maintain.

Generalize and parameterize your commands. Treat them as common data transfer objects. Define new command classes sparingly to minimize maintenance overheads. Encapsulate the specifics of your request inside the command.

Conversely, if you make your commands too coarse-grained, then they become unwieldy—hard to follow and hard to use. . If you make them too broad, you'll have to spend time packing and unpacking command data. Balance your commands by structuring per horizontal service or by subsystem business component.

Step 2. Define Your COR Manager/Service Contract
The COR Manager/Service contract is the general contract between your COR manager and its constituent-chained services. At a basic level, your interface should define a way of communicating requests and capturing responses. Define a Service interface that takes a Command and returns a Command response:

public interface Service { public Command process(Command command) throws ServiceException; }

Service classes must implement this interface in order to participate in the COR chain.

Step 3. Write Your COR Manager Dispatching Logic
Create your COR Manager class and implement the Service interface. Place your dispatching logic inside the process method:

public class CORManager implements Service { protected List services; ... /** * Routes to first service that responds to command. */ public Command routeCommand(Command command) throws ServiceException { for (int i = 0; i < services.size(); ++i) { Service service = (Service) services.get(i); Command result = service.process(command); if (result != null) { return result; } } // rof throw new ServiceException("No Service found for command " + command); }

Your dispatching logic is responsible for passing the command to each service in turn until it gets a response.

Since you can pass a request to many services, the larger the number of services, the longer the potential turnaround time on a request. COR in itself does not provide constant-time response. For efficient routing, arrange your services in a significant order. Put your most frequently used services higher in the chain than your less frequently used services, so as to minimize routing overheads. Be careful with services that share commands. Depending on the order of the service in the chain and your dispatching logic, the first service may consume a command and prevent a second service from handling it.

Step 4. Plug in Your COR Controller Session Bean
With the basic interfaces and routing logic in place, you need to add a Session Bean to manage transactions. The Bean is responsible for accepting a Command, initiating a transaction, passing the command to the COR Manager again to route inside the server, and finally handling transaction commits and rollbacks. Ensure that your bean is deployed as TX_REQUIRED:

public class CORControllerBean implements javax.ejb.SessionBean { ... public Command process(Command command) throws ServiceException{ try { return ServiceManager.get(command.getServiceManagerName()).routeCommand(command); }catch (ServiceException se) { // Rollback transaction as an application checked exception has been thrown! getSessionContext().setRollbackOnly(); throw se; } } }

Extend the COR Manager so that local commands are dispatched directly to the service chain and commands marked as transactional are passed through to the Session Bean:

public class CORManager implements Service { ... /** * Route a command either to a SessionBean or to a Service class using the * chain of responsibility pattern. */ public Command process(Command command) throws ServiceException { try { if (command.isTransactional()) { // mark with the COR manager name so that the bean can get the
right COR manager instance to pass too
command.setServiceManagerName(name); return ServiceLocator.createCommandController().process( command); } else { return routeCommand(command); } } catch (ServiceException se) { throw se; } catch (Exception e) { throw new ServiceException(e); } }

With the COR Manager, Session Bean, and interfaces in place, you have a working COR framework. All that remains is to write your business functions as COR service implementors and configure them in your COR Manager instances.



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap