Java Component Development: A Conceptual Frameworkby Palash Ghosh
Let's introduce a few business scenarios that need attention while architecting and designing a solution to accommodate continuous changes in business:
- A company wants to move its document repository from Documentum to FileNet.
- A company wants to change its security provider.
- An insurance company has to change its policy issuance process to a large extent because there is a tremendous change in economic situation.
One thing is clear: requirements change very fast as business and technology change. But with every change, big or small, do we need to throw away the complete system and start over? Not necessarily--a little thought, a good strategy, and best practices during architecting and designing a new solution could adapt the existing architecture to those changes without much hassle.
In object-oriented programming and distributed object technology, a component is a set of classes and interfaces to fulfill requirements (functional and non-functional) with a reusable external API. Components should be able to run in a distributed network environment to form a network application. Component-based design and development is not a new topic at all to professionals who are following Object-oriented analysis and design (OOAD) methodology.
The goal of this article is to arrive at a common conceptual framework to develop a Java component step by step, following Java best design practices, and starting from scratch. The expected audience of this article needs to have prior knowledge of Java and UML, and Java/J2EE design patterns. The key areas to be addressed in the this article are:
- The basic properties of a component.
- How to achieve those basic properties in Java component design, using Java design best practices (design patterns), and arrive at a conceptual basic component development framework, which can be used in any component development.
Basic Properties of a Component
To meet the definition, a component must satisfy the following requirements:
- A component must have a service interface (API) so that other components can interact with it.
- A component should have a proper life cycle mechanism (start, stop, initialize, etc.).
- A component should be configurable.
- Only one instance of the component should run in the enterprise.
- Changes in the configuration should be dynamic (on the fly).
- A component should have a proper third-party integration mechanism.
- A component should have a proper error-handling mechanism.
How to Achieve Basic Component Properties
A Component Must Have a Service Interface (API)
Whenever we write 100 to 1000 lines of code in a single class or number of classes, ultimately the work product (the class or the combination of classes) provides some basic high-level services. Thinking backwards, we can identify those basic high-level services we are trying to achieve, even before implementing them.
Let's give an example from the insurance domain, where an underwriter does the following tasks in his day-to-day activities:
- Checking an insurance proposal.
- Assessing and gathering background information.
- Calculate the premium using the company's existing rule set.
- Gathering information and various types of reports (medical, etc.) from other departments.
- Writing and preparing a policy.
So now if we try to write an Underwriter business component, we will have to have a service interface and its implementation, as seen in Figure 1:
Figure 1. Underwriter service interface
When another component requests a service from the Underwriter component, it doesn't need to worry about what is happening inside of the component. Encapsulating its business logic within itself makes the component more maintainable and extensible.
The Service component will have one main implementation service class (an implementation of the Service interface) and this class may make use of helper classes that are part of this component, and perhaps use other components, too.
In product development, we may have many components providing different types of services. For example, in the insurance field, we could have a "claim-processing component," a "policy-holder service component," and more. So we must have a strategy to register those service components in the enterprise solution, in order to be able to enable or disable those services according to the specific needs of the enterprise.
Here is an example XML structure, which can handle this service registration process automatically.
<Services> <Service> <Serviceid>S001</Serviceid> <ServiceName>UnderwriterService</ServiceName> <ServiceImplClass> com.org.service.UnderWriterServiceImpl </ServiceImplClass> </Service> <Service> <ServiceId>S002</ServiceId> <Servicename>PolicyHolderService</ServiceName> <ServiceImplClass> com.org.service.PolicyHolderServiceImpl </ServiceImplClass> </Service> </Services>
A Component Should Have a Proper Life Cycle Mechanism
The component also needs a built-in, visible, independent mechanism in its
life cycle so it can be started and stopped as needed. This
a singleton, since only one instance is needed. This factory is responsible
for creating instances of a class for different providers based on the configuration
ComponentControllerFactory plays a dual role: first it manages
the component life cycle with its
methods (which is why it's a "controller"), and secondly it instantiates the
class based on the parameter passed to it (which is why it's a "factory").
Figure 2 shows its methods.
Figure 2. Component controller factory
The component life cycles methods are:
doStart(): Starts the component
doInitialize(): Helps to read from the
Configurationobject created from XML configuration file and is responsible of creating an instance of the appropriate class.
doStop(): Stops the component
reload(): If changes occur in configuration XML file when the component has been started already, this method will read the configuration XML file once again and restart the component.
getInstance(): Returns the instance of the
A Component Should Be Configurable
Generally, every component will have its own configurable parameters, which
are not required to change often. For example, suppose we need to write a
which needs to be refreshed every hour to load some semi-static data from a
database. The value of the refresh time should come from a configuration
file, so that the value of that the parameter can be changed without touching the
Here is one example of a configuration XML file for a logger component, which takes care of logging throughout all the layers of an enterprise.
<LoggingServiceProvider> <Provider> <ProviderName>Apache</ProviderName> <AdapterImpl>com.org.integration.adapter.Log4jAdapter </AdapterImpl> <Enable>true</Enable> </Provider> <Provider> <ProviderName>WebLogic</ProviderName> <AdapterImpl>com.org.integration.adapter.WebLogicAdapter </AdapterImpl> <Enable>false</Enable> </Provider> </LoggingServiceProvider>
Pages: 1, 2