![]() |
|
URL of the article:
Geronimo GBean Architecture
Spilling the Bean on GBeans
by Srinath Perera
Geronimo is built on a J2EE agnostic Kernel and is positioned as a general-purpose Inversion of Control (IoC) framework for components called GBeans. This article explains the theoretical aspects of the IoC framework, describes the GBean Life Cycle, GBean States and Dependency Injection with a few examples, and concludes with an explanation of how to write a simple GBean.
Introduction Consider a platform like Linux or Windows, with an operating system core that provides system calls and a set of applications that run on top of it. Geronimo is built on a similar J2EE agnostic core called Geronimo Kernel, and is essentially a framework for components called GBeans. Any complex system can be modeled as a set of components that hold states, a set of relationships among them, and how each component reacts to certain events. The Geronimo Kernel provides a framework for GBeans with the following services:
Almost everything in Geronimo is a GBean: containers, connectors, adapters, applications and so on. The relationship between GBeans can be viewed as a mesh of components, as explained in Figure 1. ![]() Figure 1: The relationship between GBeans Any J2EE Container is comprised of two classes of citizens; the first class of citizens, such as Web Containers and EJB Containers, that provide the core services, and the second class of citizens that are applications, such as EJB's and Servlets, deployed in the first class citizens. Geronimo's architecture can be explained in terms of GBean behaviours. Geronimo is a set of running GBeans, and each first class citizen is a set of GBeans that are related to one another. They are loaded via "plans" which are essentially an XML serialization of GBeans. When the plans are loaded and started, the GBeans included in the plans will be started; that is, the EJB Containers and/or the Web Containers will be started. The applications that run in a J2EE Container are described by Deployment Descriptors and Java Classes that are packed as a J2EE application archive. The Geronimo Deployer parses those archives and constructs GBeans out of them. When GBeans are started, the application is deployed and available. GBeans can be serialized and stored. Therefore, once an application is converted to GBeans and added to Geronimo it will be available automatically even after the server is restarted. GBeans from a Conceptual Point of View Inversion of Control (IoC) provides the base for GBeans framework - the Geronimo Kernel. The essence of IoC or the dependency injection is to create a loosely coupled architecture where the dependencies among components are managed by the framework. When a component has a dependency on another component, the IoC framework will find the correct component and make it available to the first component. The dependency injection name comes from the fact that the framework automatically injects the dependencies to the component. The most simple form of IoC (or Dependency Injection) is performed by special attributes known to the system, usually called Magic attributes. For instance, let us assume that a Web Service (WS) is deployed inside Axis. Assume that Axis will load the following class and call the doit() method: public class WS{
Note that Axis includes a MessageContext that holds all configuration information. To provide a reference of MessageContext to the WS class, Axis can say "if you have a Constructor like XX(MessageContext) or if you have a method like setMessageContext(MessageContext msgctx), I will inject the MessageContext to you." In this simplest form of dependency injection, the framework looks at the method signatures of the class and decides whether that class expected a MessageContext to be injected into it. In other words, the IoC framework inspects the components for certain patterns in methods, parameters, and constructors. When a pattern is found, the IoC framework provides an appropriate service to the component. For instance, in the above example, the service is providing a reference of the MessageContext. Looking at the techniques used to develop loosely coupled systems will give you a better understanding of how IoC is used. It is important to note that the decoupling of the system is all about the interaction among components. Following are some of the techniques employed:
The idea of IoC is to define all relationships among components in terms of framework level configurations. When a component becomes available, the framework will inject the component to other components that references it. For example, let us consider how a GBean G1 obtains a reference to a Configuration Store. G1 is configured specifying the expected patterns of reference: bean.setReferencePatterns("configStore,*:type=configStore,*");
When another Gbean, whose name matches the pattern "*:type=configStore,*", is started, it is automatically injected into G1. Note that this behavior is similar to Aspect Oriented programming (AOP), where the developer tells the framework what needs to be done, rather than how to do it. IoC is not the only way to create decoupled systems. The other three methods listed earlier, are just as useful. It is a matter of choosing the right tool for the occasion, and there are good examples as well as bad examples for each. GBean Life Cycle A GBean can be in any of the three states: stored, loaded, or running. In the stored state, it is saved in a configuration store ("plan"). When it is loaded, the kernel maps it to a name, for keeps. Note that, while each GBean is bound with a name at start up, that name is not persistent. This can be explained by an analogy: consider a 'Gbean' as a Java class, and the 'name' as a variable name that refers to a specific instance of the class. In the same way that the class can have more than one instance, the same GBean can be loaded under more than one name, and stored in many places. State of GBeans GBeans have two types of states: Attributes and References. (We will look at References in the Dependency Injection section, later in the article.) Attributes can be persistent or non-persistent, and the framework supports storing and restoring GBeans. Furthermore, there are special Magic attributes defined by the architecture; the values for the Magic attributes that are loaded depend on the environment the Gbean is loaded on. For example, the Magic attribute "kernel" refers to the Kernel, and when it is specified at the constructor it is automatically injected to the class by the framework. Similarly the ClassLoader attributes inject the current class loader and the ObjectName attributes inject the current name under which the GBean was started. The magic attributes cannot be persistent as they are bound with the environment it is started under. Note: In the Dependency Injection example in the 'GBeans from a Conceptual Point of View' section, where a Web Service is deployed to Axis, the MessageContext is a Magic attribute. A GBean with one attribute (val) looks like this: public class MyGBean implements GBeanLifecycle {
We can start our GBean with the following code: ObjectName myGbeanName = ObjectName.newInstance("Geronimo.my:name=mine");
Dependency InjectionThere are two types of relationships: Single References and Reference Collections. Single References are injected to a GBean in one of the two ways: the getter/setter injection and the constructor injection. The names are based on how the dependencies are injected in to the Java Class that is used to implement the GBean:
The second approach is more preferable as GBeans support the so-called good citizen pattern, ensuring the GBean is in a usable state once it is started. Geronimo supports both methods, but is moving towards the complete constructor injection. Following is a simple GBean that uses constructor injection: public class MyGBean implements GBeanLifecycle {
In the code snippet, line (A) denotes a reference to GBean1 and line (B) registers the matching constructor (C). In the following code, the developer specifies the reference instance of GBean1, and starts GBeans. When MyGBean is started, an instance of GBean1 is injected via the constructor: ObjectName GBean1= ObjectName.newInstance("Geronimo.my:name=gb1");
The second method, the Reference Collections allows a collection of references to be referenced. The only difference when the Reference Collection comes in to play is replacing GBean1 references (in the above example) with Collection, and specifying the name of the referenced GBeans as a pattern, with "*" and "?". The following code segment, instructs the framework to inject all the GBeans with the Domain name "Geronimo.my:" as references to the GBean denoted by bean variable. When a GBean that matches the pattern is started, it is automatically injected to the GBean denoted by bean variable: bean.setReferencePatterns("Geronimo.my:*");
The kernel supports kernel.invoke("objectName","methodName",...), using which one can call any method in any other GBean. But use of this technique is discouraged, as method names are strings, and use of this technique is akin to using reflection to invoke Java methods. For example, say GBean G1 needs to call the doit() on GBean G2. The crude way to do it is: kernel.invoke("G2Name","doit");
The accepted way to do it is to register a reference pattern and obtain the instance of the GBean G2Name injected in to the place where the code is written in and using Java style code: class G1 implements GBeanLifeCycle{
In line (A) of the code snippet, there is a reference to G2. At line (B), adding a constructor that injects G2 and G1, will obtain a reference to G2. The logic is implemented using simple Java code. GBeans have interfaces that make the GBean implement a given method. Sample Code Download the Sample file to find sample GBeans and test cases that demonstrate their use. Note that, you should have Apache Maven installed on your machine, to run the test case. Summary The GBean architecture is J2EE agnostic and a general framework for developing a loosely coupled System with IoC. It can be used outside Geronimo and has the potential to be a generic Architecture for loosely coupled systems. Srinath earned his B.sc. in Computer Science and Engineering from the University of Moratuwa, Sri Lanka. He is a committer for Apache Geronimo, Apache Axis2, Apache EWS, and Apache Axis projects. His areas of expertise are Web services, J2EE and XML processing technologies. He is currently one of the core developers for Apache Axis2 working under a fellowship from Lanka Software. Links and Literature
|
||
|