MetaBoss Programming Model Guide.
System Componentisation.
Index
Introduction
Reasons to have yet another componentisation framework
MetaBoss componentisation description
Usage of the componentisation mechanism
Introduction
System Componentisation is a design approach where the whole system is split into many stand alone isolated
components. Such a split allows us to loosen the coupling between various componentised parts of the system and
therefore decrease the ripple effect of changes. Some elements of this approach are:
- Components must have an Id unique within the scope of the system.
- A Component must present itself to outside world via an interface. This interface lists all the operations available to outside user.
Definitions of data types and exceptions used in component interface may accompany interface definition (e.g. located in the same package)
- Client programs must have some means of obtaining "live" instance of the component at run time by specifying Component Id.
- The Component implementor must have the freedom to alter the implementation of the component without requiring a
rebuild of client programs. Note that this is only true for implementation changes. Client programs
must be made aware of Component interface changes.
- The Component deployer must have the freedom to deploy alternative implementations of the same component without
redeployment of client programs.
Systems generated by MetaBoss are componentised using MetaBoss's own framework, which is
built on top of the Java Naming and Directory Interface (JNDI)
Reasons to have yet another componentisation framework
Most of existing technologies offer some form of componentisation framework. In the Microsoft Windows world it's COM, DCOM
ActiveX etc. In the Java world the most popular technologies are Java Beans and Enterprise Java Beans (J2EE).
In addition CORBA also offers componentisation solution.
At MetaBoss, we believe that most of the known solutions do not go far enough towards having a total separation of component interface and implementation
and the complete technology independence of component interface specifications.
Take for example J2EE. In J2EE the component is presented by two interfaces, Home and Remote - this separation, in our view, is
technology related (operations in the Home interface are run locally and operations in the Remote interface are run remotely) and is not really necesary.
An Enterprise Java Bean client would be happy to lookup a EJB and execute its operations regardless of where the actual execution takes place.
In fact this separation may even force client program rework if EJB developers will decide to move some operations between the Home and Remote interfaces (some performance improvement tips suggest doing just that).
Another aspect of the EJB specification is that Home and Remote interfaces must extend javax.ejb.EJBHome and javax.ejb.EJBObject respectively. Operations on these interfaces are also
declared to throw java.rmi.RemoteException. This also has the effect of giving technology too much prominence in the component interface, which
may make it more difficult to replace J2EE with something else (e.g. RMI, CORBA, Web Services).
Contrary to what it might seem from above discussion, we actually do believe that J2EE/Java is a good platform to develop and run distributed solutions - we just think that the level
it is at is too low level for componentisation. This, by the way is true for most of existing technologies.
MetaBoss componentisation description
MetaBoss componentisation is based on the Java Naming and Directory Interface (JNDI) standard mechanism and has the
following features:
- Each and every component is presented to clients as one and only one "pure" Java interface. "Pure" here
means that the component interface is not extending any other interface and is not required to use any
prescribed exceptions, method parameters, method names etc. Absolutely any interface (for as long as it compiles)
out of any Java book is good enough to be used as component interface.
- Each and every component has a unique URL. The Component URL is of the form :
- "
component:/full Java name of the component interface "
Component URL is used to identify the component in JNDI lookup operations
- MetaBoss coding style recommends one more not essential rule:
It is highly recommended to provide public static constant named COMPONENT_URL which contains the Component URL string.
For example:
package com.hatmaker.crm;
..................
..................
public interface BSDataManagement
{
public static final String COMPONENT_URL = "component:/com.hatmaker.crm.BSDataManagement";
..................
..................
public SomeResult someOperation(SomeInput pOperationInput) throws SomeException;
..................
..................
}
- Component clients need only use the Component Interface class and a standard JNDI facility to
look up the instance of the component at run time. The effort on the client side is minimal - all a client has to do
is to lookup the Component Interface and use it! For example:
import javax.naming.*;
import com.someenterprise.somesystem.services.someservicemodule.*;
............
............
Context lNamingContext = new InitialContext();
BSSomeService lService = (BSSomeService)lNamingContext.lookup(BSSomeService.COMPONENT_URL);
............
............
SomeOperationInput lOperationInput = new SomeOperationInput();
SomeOperationResult lResult = lService.someOperation(lOperationInput);
if (lOperationResult.getSomeField() != null)
System.out.println(lOperationResult.getSomeField());
if (lOperationResult.getSomeMessage() != null)
System.out.println(lOperationResult.getSomeMessage());
............
............
- Components may have an unlimited number of various implementations. Each and every Component Implementation
may have a different implementation strategy, design, features or technologies it is based on. For example
one implementation may target a local file, another one may target a remote relational database and another one may delegate all work to the Web Service!
At run time, at the time when a client looks up the component - a special piece of software - the Component URL Resolver provided by MetaBoss - will
locate an object factory associated with a particular implementation and will ask this factory to instantiate the implementation (This may sound complex,
and may be it is, but this stuff is straight out of the JNDI SPI specification). The Component URL Resolver is using ComponentURL-to-ComponentImplementation
mapping instructons to determine the desired implementation. Maintenance of these mapping instructions is a responsibility of the
system deployer. See the separate Configuring JNDI Component interface/implementation mapping guide for more details.
- One special type of implementation is a proxy. The proxy is an implementation of the
component, which adresses only a certain (usually non core / secondary in nature) aspect of the component functionality and delegates
processing further to another implementation, which is also looked up via JNDI. For example a logging or profiling proxy might log the
start and end of every execution of every operation and delegate actual operation to
another implementation of the same component. One of the powerful aspects of the MetaBoss Component URL Resolver is the ability
to configure "chains" of proxy implementations, so any number of proxies with different agendas
can be invoked before or after the actual core implementation code is executed.
- In order to develop a legitimate Component Implementation, the component developer has to
do the following:
- Choose a dedicated package for each kind of Component Implementation. It is also a good idea to place these implementation packages under the package, where
the Component Interface is located. This requirement is dictated by Component URL Resolver and in particular
by the ComponentURL-to-ComponentImplementation mapping instructions syntax. It is still possible to place the implementations of different components in one package, but it is not
possible to place more than one implementation of the same component in the one package.
- Each Component Implementation class must implement the Component Interface. The Name and other features of
the class are not important, although it is a good idea to give it a descriptive name.
- The Component Implementation Factory which implements JNDI's javax.naming.spi.ObjectFactory must be created for each
component implementation and located in the same package as the corresponding component implementation. This factory
is a very simple mechanism, which serves instances of components on request from JNDI. The name of this factory
class must be the same as the name of the Component Interface with suffix "Factory"
Some examples:
package com.hatmaker.crm.someimpl;
import com.hatmaker.crm;
..................
..................
class BSDataManagementSomeSortOfImpl implements BSDataManagement
{
..................
..................
public SomeResult someOperation(SomeInput pOperationInput) throws SomeException
{
..................
..................
}
..................
..................
}
package com.hatmaker.crm.someimpl;
import javax.naming.Name;
import javax.naming.Context;
import java.util.Hashtable;
public class BSDataManagementFactory implements javax.naming.spi.ObjectFactory
{
public Object getObjectInstance(Object pObj, Name pName, Context pCtx, Hashtable pEnv)
throws Exception
{
return new BSDataManagementSomeSortOfImpl();
}
}
package com.hatmaker.crm.someimpl;
import javax.naming.Name;
import javax.naming.Context;
import java.util.Hashtable;
public class BSDataManagementFactory implements javax.naming.spi.ObjectFactory
{
private BSDataManagementSomeSortOfImpl mTheOnlyInstance = new BSDataManagementSomeSortOfImpl();
public Object getObjectInstance(Object pObj, Name pName, Context pCtx, Hashtable pEnv)
throws Exception
{
return mTheOnlyInstance;
}
}
Usage of the componentisation mechanism
MetaBoss uses the componentisation mechanism extensively throughout all parts of the suite, which
achieves high flexibility of the end product. The places most interesting to application developers
are:
- The Enterprise Services layer is componentised. Each Business Service is a component and
has its own component interface. For the client systems developer it means that Enterprise Services must be looked up via JNDI as described above.
For the service implementation developer it means that any number of service implementations can be developed for as long as
they follow a few simple JNDI rules explained above (Implementation must implement an interface and
Factory must be present). Some of these implementations are available from various MetaBoss generators:
- The Thransaction Proxy provides J2EE style transaction management in environments without a J2EE container.
- The Simulator Implementation is able to simulate operation outputs based on operation inputs and XML / XSL files.
- The J2EE Distribution Proxy delegates execution of all operations to J2EE container.
- The Domain Objects layer is componentised. Each System Domain has an entry point object called
BODomain. This object is a component and can be looked up. Typically the Enterprise Service implementation developer
will look up the domain entry point and navigate whole domain from this component.
This involves executing JNDI lookup of the required component as described above.
MetaBoss fully generates the interface and implementation of this layer from the domain model and we hope that there
are few reasons to manually code or alter anything here. However, because this layer is
componentised, in theory other implementations or proxies can easily be plugged in.
- The Storage layer is componentised. Each Storage Service is a component and
has its own component interface. Typically generated implementations of the Domain Objects layer
will lookup Storage Services via JNDI and use them for storage operations. While
MetaBoss fully generates the interface and implementation of this layer, the ability to plugin
any implementation or proxy here is very important as it allows an easy switch to different
make and model of the database engine, different remoting technology etc, etc, etc.
The same mechanism is also extensively used inside MetaBoss itsef. Many parts of MetaBoss (e.g code generators,
code generation stylesheet etc) are components and their implementation can easlily be altered without sending "shivers" throughout
the whole suite.
|
Copyright © 2000-2005 Softaris Pty.Ltd. All Rights Reserved. MetaBoss is the registered trademark of Softaris Pty.Ltd. Java, Enterprise JavaBeans, JDBC, JNDI, JTA, JTS, JCA and other Java related APIs are trademarks or registered trademarks of Sun Microsystems, Inc. MDA, UML, MOF, CORBA and IIOP are trademarks or registered trademarks of the Object Management Group. Microsoft, .NET and C# are trademarks or registered trademarks of the Microsoft Corporation. All other product names mentioned herein are trademarks of their respective owners.
|