| Sign In/My Account | View Cart |
Java Component Development: A Conceptual Framework
Pages: 1, 2
A component should have just one and only one instance running at a time, so the Singleton design pattern, which ensures having only instance in a JVM, is an appropriate choice. But while this works in a single-JVM scenario, it's a problem when multiple JVMs are used. If this component needs in multiple nodes of a cluster, each node will have its own instance. But it is still acceptable if the configuration information, loaded at component startup, doesn't need to change and it deals with completely static information.
If we assume that the component will be running in a single JVM, then ComponentControllerFactory will
look like Figure 3:
Figure 3. Component controller factory in a single JVM
The methods provided by the singleton controller factory are:
getXXXService(): This method returns the service provider
implementation class defined by the XML file. getXXXAdapter(): This method returns the adapter implementation
class defined by the XML file. If a component is immutable, each cluster node will have an identical copy of the singleton instance; but if it is not immutable and the configuration information needs to be changed dynamically, we need something different.
There are two probable scenarios when dynamic configuration change may happen:
If application will run in a single JVM, things are simpler. As we know, SingletonControllerFactory will
always have a single instance in the JVM, so whenever any changes are made
to the configuration file, the factory object will need to be reloaded,
based on some notification mechanism, which will load the Java serializable
configuration object in turn.
Here is the ConfigManager class. It is based on the Observer-Observable
pattern and performs two activities:
Figure 4 shows the methods of the ConfigManager.
Figure 4. ConfigManager
The ConfigManager class acts as an Observer;
when it's notified by the Observable, its update method
will be called. The update() method will call the reload() method
of SingletonControllerFactory so that the newly created Java
object will reload its configuration information.
ConfigurationChangeNotifier acts as an Observable and
starts a thread, which notifies the ConfigManager if any change
occurs in the timestamp of the configuration XML file, which may indicate
a change in its contents. Figure 5 shows this relationship.
Figure 5. ConfigurationChangeNotifier
In a multiple JVM scenario, things are not so simple. We have to have:
Using JNDI combined with RMI is one option to ensure having one and only one instance running in a particular node (JVM) of multiple nodes of a clustered environment. A RMI service needs to be written and a RMI stub would be generated out of this RMI service. This generated RMI stub needs to be bound in the JNDI tree of the application server. This object will sit on one container, which will make the object available throughout the cluster.
To deal with this situation, we need to introduce ConfigManager, which
will do the following tasks:
Serializable object from the XML file.
Serialization and de-serialization can be done by different components.Figure 6 shows the RMI service interface and its implementation.
Figure 6. RMI service
In the multiple-JVM scenario, the ConfigManager will look
like Figure 7:
Figure 7. ConfigManager in a multiple-JVM scenario
The ConfigManagerMultipleJVM class acts as a Observer.
When it is notified by the Observable, its update method will
be called. Within the update() method, the rebindRMIService() method
will be called so that the newly created object (with the latest configuration
information) will be reloaded.
SingletonControllerFactory will act as a wrapper for the
RMI service, returning the appropriate, configured object.
The problem with this approach is that since there will be just one instance,
it has a single point of failure. The ConfigManager component
needs to be more robust to handle the failover.
But there is also another approach that will synchronize a cached configuration object in a different node of a cluster, with the help of MDB and JMS. In this case, RMI service is not required. Here are the steps to implement this approach:
SingletonControllerFactory initializes and starts
up the component with the configuration object. ConfigManager's Observer-Observable model tracks any
change in the configuration of the XML file with its notification mechanism. If a change is found, it publishes the message to the JMS topic. onMessage() and loads the changed configuration Java
object. If the component depends on third-party integration to get a service, the third-party API should not be directly used in the implementation class. The best strategy would be to develop an adapter and isolate third-party calls to the adapter implementations.
Figure 8 shows an example adapter used by the logger component, which shows how it can adapt to different third-party APIs easily.
Figure 8. Application logger interface
The advantage of using this adapter pattern is to incorporate different third-party APIs easily. Furthermore, if those APIs change, the adapter implementation will need to be changed, but the service that uses the adapter interface will not need to change.
Choosing from several adapters is facilitated with a configuration XML file, as described in the "A Component Should Be Configurable" section above.
Each component will have its own exception-handling class, which will help to catch the proper exceptions. It's assumed that we will have a separate component, specific to the business at hand, to handle exceptions. This component-specific exception class (Underwriter exception) will take the required service out of the exception-handling component.
Figure 9. Component exception handling
This exception class is very specific to the Underwriter service and it extends the enterprise base exception class. Its job is to wrap the exception that occurred in this service class and re-throw it.
|
Related Reading
Head First EJB |
To summarize, here are the basic steps to put it together:
ConfigManager will
read the different configuration XML files for different components with
the help of XMLizer (a separate component used for XML-to-Java object
conversion) and bind the configuration Java object with the JNDI tree
of an application server node. ConfigManager will
read the changed XML and rebind the configuration object. Coming back to where we started: a component framework can be effective in adapting to changes in business and technology when you are planning to develop a robust system. The best part of this conceptual framework is that it completely isolates the component management/life cycle process from the business logic and different third-party APIs, by introducing the concept of different plug-and-play service providers. Even when changes are made, you do not have to worry about the rest of the code, other than changing/replacing the service provider. This in turn makes the application more maintainable, adaptable, and robust.
Palash Ghosh is a software architect with six years of expertise architecting, designing, and developing Java/J2EE solutions.
Return to ONJava.com.
Showing messages 1 through 5 of 5.
I do agree with the fact that some component should have properties that you have mentioned in the article however this may not be applicable to all components. Specifically properties like life cycle of the component and life cycle methods like stop and initialize and I also do not agree with the single instance of the component. I can have one component with multiple instances running in the system.
The decision about the properties would change based on the scenarios. We can add properties like location transparency etc.
Best Regards,
Chintan.