Good idea !
Best Regards, Ying Tang 2009/3/23 Shawn Jiang <[email protected]> > I'm wondering if we should put the GBean samples in this doc to a part of > current geronimo samples. > > On Mon, Mar 23, 2009 at 3:45 PM, <[email protected]> wrote: > >> Page Edited : >> GMOxDOC22<http://cwiki.apache.org/confluence/display/GMOxDOC22>: Developing >> and Deploying a Geronimo >> GBean<http://cwiki.apache.org/confluence/display/GMOxDOC22/Developing+and+Deploying+a+Geronimo+GBean> >> >> Developing and Deploying a Geronimo >> GBean<http://cwiki.apache.org/confluence/display/GMOxDOC22/Developing+and+Deploying+a+Geronimo+GBean>has >> been edited by Ying >> Tang <http://cwiki.apache.org/confluence/display/%7Esophia> (Mar 23, >> 2009). >> >> (View >> changes)<http://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=110931&originalVersion=23&revisedVersion=24> >> Content: >> >> Geronimo is a system framework that can be used to build a variety of >> tailored infrastructure services, with *GBean* providing it with a >> loosely-coupled and configurable runtime environments. GBean is an >> implementation of Inversion of Control (IoC), or the dependency injection, >> which allows the automatic injection of references as they become available. >> Geronimo Kernel and GBean Geronimo kernel >> >> The Geronimo kernel is a framework for kernel services, and controls the >> basic server components with the following services: >> >> - Component configuration >> - Component repository >> - Dependency management >> - Lifecycle management >> >> The basic server componenets, namely *security*, *logging*, *transactions >> *, and *naming*, work with the kernel services to build Java EE server >> components, such as Tomcat, Jetty, and OpenEJB. All these components, >> cooperate with the kernel to support Java EE applications. >> GBeans >> >> Almost everything in Geronimo is a GBean: containers, connectors, >> adapters, applications and so on. A GBean is an atomic unit in Geronimo, >> consisting of the implementation classes (.jar) and a *plan*. >> >> The *plan* is a configuration file through which a GBean relies on the >> kernel for IoC and dependency injection at runtime. Dependencies on other >> GBeans can be configured through the attributes and references in plans. >> Geronimo's configuration builders construct GBeans out of these plans, group >> them as *configurations*, and store them in the *configuration store*. >> >> A *configuration* is a logically coupled collection of one or more GBeans >> and a classloader. The configurations are loaded with the server. The >> *configuration >> store* is the standard Geronimo storage mechanism. >> >> Applications that run in a Java EE container, described by custom *deployment >> descriptors* and Java classes, will be parsed and converted into GBeans >> by the configuration builders of the Geronimo *Deployer*. These GBeans >> are also stored in the configuration store. >> GBean Lifecycle >> >> A GBean can be in any of the three states: stored, loaded, or running. >> >> - Stored: The GBean exists in a plan, or configuration store. >> - Loaded: The GBean is mapped to a non-persistent name when loaded by >> the kernel, allowing multiple instances of the same GBean to exist. >> - Running: The GBean is in the running state, coordinating the >> application classes that it contains. >> >> To participate in the life cycle operations, GBeans implement a * >> GBeanLifecycle* interface. This interface defines three methods, >> doStart(), doStop() and doFail(). The doStart() method is used to start >> the GBean, allocate resources, and implement the GBean operations. The >> doStop() menthods stops the GBean and releases all resources. The >> doFail() method is executed when the GBean fails to start, run or stop, >> and is always used to report the failure and stop the GBean. >> >> package org.apache.geronimo.gbean; >> public interface GBeanLifecycle{ >> void doStart() throws Exception; >> void doStop() throws Exception; >> void doFail(); >> } >> >> If the optional interface GBeanLifecycle is implemented, the >> implementation will get lifecycle callbacks from the kernel. >> GBean methods >> >> The class for a GBean should implement specific methods to support each >> feature of the GBean: >> >> - *GBeanInfo*: A GBean has a method called getGBeanInfo() that returns >> an instance of the GBeanInfo class. GBeanInfo defines the methods that >> should be exposed to the other subsystems, exposes attributes and >> references >> so that they can be injected at runtime, and define information about the >> GBean so that it can be located later. The GBeanInfo object is constructed >> in a static initializer. >> - *Constructor*: The GBean constructor arguments should correspond to >> either attributes or references for the GBean. It is defined by the * >> setConstructor* method in GBeanInfo. >> - *Attributes*: An attribute should have a setter method, a getter >> method, or both. The *addAttribute* method in GBeanInfo should define >> the name of the attribute, its type and whether or not it's persistent, so >> that the attribute can be injected via the Geronimo kernel. >> - *Operations*: Any public method on the GBean that is not a getter or >> setter can be an operation. The operation methods should match the name >> and >> argument types listed by *addOperation* for the operations in the >> GBeanInfo. >> - *References*: A reference, like an attribute, is injected at >> runtime. However, a reference is another GBean rather than a String or an >> integer. >> - *Interfaces*: Adding a reference in GBeanInfo is a faster way of >> adding attributes or operations separately. All of the variables in the >> interface will be added as attributes and all of the methods will be added >> as operations. >> >> Developing a GBean >> >> For developing a GBean, you at least have to go through the following >> steps: >> >> 1. Write a POJO class >> 2. Adding the GBeanInfo part to expose attributes,methods, interfaces, >> and constructors >> 3. Implement GbeanLifecycle inteface to use the Gbean Kernel lifecycle >> callback (*Optional*) >> >> A sample GBean >> >> The sample GBean SimpleServerGBean simply starts a socket on the Geronimo >> server, and retrieves the name of the GBean and the socket port. The >> following code snippet implements the Plain Old Java Object (POJO) section: >> *SimpleServerGBean POJO* >> >> public class SimpleServerGBean implements GBeanLifecycle, InterfaceNamed{ >> >> private final String name; >> private int port; >> >> private boolean started = false; >> private ServerSocket serversocket; >> >> public SimpleServerGBean(String name, int port) { >> this.name = name; >> this.port = port; >> } >> >> public String getName() { >> >> return this.name; >> } >> >> public boolean isStarted() { >> >> return started; >> } >> >> private void printConsoleLog(String log) { >> >> System.out.println(" LOG : " + log); >> } >> >> In the following code snippet, the GBean exposes its attributes, >> operations, interfaces and constructor for the GBEAN_INFO static >> initializer. >> *SimpleServerGBean GBeanInfo* >> >> private static final GBeanInfo GBEAN_INFO; >> >> static { >> GBeanInfoBuilder infoFactory = new GBeanInfoBuilder( >> SimpleServerGBean.class.getName(), SimpleServerGBean.class); >> >> infoFactory.addAttribute("name", String.class, false); >> infoFactory.addAttribute("port", int.class, true); >> >> infoFactory.addOperation("isStarted", "String"); >> >> infoFactory.addInterface(InterfaceNamed.class); >> >> infoFactory.setConstructor(new String[] { "name", "port" }); >> >> GBEAN_INFO = infoFactory.getBeanInfo(); >> } >> >> public static GBeanInfo getGBeanInfo() { >> return GBEAN_INFO; >> } >> >> The SimpleServerGBean Gbean is simple to start up and shutdown. During >> startup, it simply accepts an incoming socket connection requests, and sends >> out the echo message. When being stopped, the GBean closes the resouces that >> it consumes. >> *SimpleServerGBean Lifecycle* >> >> public void doFail() { >> >> started = false; >> printConsoleLog("GBean " + name + " failed"); >> >> } >> >> >> >> public void doStart() throws Exception { >> >> serversocket = new ServerSocket(port); >> started = true; >> >> Thread simpleServerThread = new Thread(new Runnable() { >> >> Socket socket; >> InputStream is; >> OutputStream os; >> >> public void run() { >> >> while (started) { >> try { >> socket = serversocket.accept(); >> is = socket.getInputStream(); >> os = socket.getOutputStream(); >> >> BufferedReader bufferedReader = new BufferedReader( >> new InputStreamReader(is)); >> >> String responseMessage = "simpleServer response :" >> + bufferedReader.readLine(); >> >> os.write(responseMessage.getBytes()); >> >> bufferedReader.close(); >> if (os != null) { >> os.close(); >> } >> if (socket != null && !socket.isClosed()) { >> socket.close(); >> } >> >> } catch (Exception e) { >> //ingore >> } >> } >> } >> }); >> >> simpleServerThread.start(); >> >> printConsoleLog("GBean " + name >> + " started and it's listening on port:" + port); >> } >> >> >> >> public void doStop() throws Exception { >> started = false; >> serversocket.close(); >> printConsoleLog("GBean " + name + " stopped"); >> } >> >> } >> >> For this sample, we still need a class to test the SimpleServerGBean. >> This section creates a socket and sends a connection request to the >> SimpleServerGBean. After the connection has been established, it sends out >> messages and retrieves the echo message from the simpleServerGBean server >> instance. >> >> package org.apache.geronimo.sample; >> import java.io.BufferedReader;import java.io.InputStream;import >> java.io.InputStreamReader;import java.io.OutputStream;import >> java.net.InetSocketAddress;import java.net.Socket; >> import org.junit.Ignore;import org.junit.Test; >> public class SimpleServerTest { >> >> @Test >> @Ignore >> >> public void connectToSimpleServer() throws Exception { >> >> >> Socket socket = new Socket(); >> socket.connect(new InetSocketAddress("127.0.0.1", 7777)); >> >> OutputStream os = socket.getOutputStream(); >> String requestMessage = "Hello simple server"; >> os.write(requestMessage.getBytes()); >> os.write("\n".getBytes()); >> os.flush(); >> >> InputStream is = socket.getInputStream(); >> BufferedReader bufferReader = new BufferedReader(new >> InputStreamReader(is)); >> String responseMessage = bufferReader.readLine(); >> System.out.println(responseMessage); >> >> socket.close(); >> } >> >> } >> >> Before deploying your GBean, you still have to compile the GBean class >> and build a proper .jar file. Maven <http://maven.apache.org/> is used to >> build Geronimo, so it can be used to build your GBean project. You have to >> write a pom.xml file. See Maven website <http://maven.apache.org/> for >> more information about the file. >> *pom.xml* >> >> <project xmlns="http://maven.apache.org/POM/4.0.0" >> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 >> http://maven.apache.org/maven-v4_0_0.xsd"> >> <modelVersion>4.0.0</modelVersion> >> >> <groupId>org.apache.geronimo.sample</groupId> >> <artifactId>simpleServer</artifactId> >> <packaging>jar</packaging> >> <version>1.0</version> >> <name>sample GBean as a simple server</name> >> >> >> <dependencies> >> <dependency> >> <groupId>org.apache.geronimo.framework</groupId> >> <artifactId>geronimo-kernel</artifactId> >> <version>2.1.3</version> >> </dependency> >> >> <dependency> >> <groupId>junit</groupId> >> <artifactId>junit</artifactId> >> <version>4.1</version> >> <scope>test</scope> >> </dependency> >> </dependencies> >> >> <build> >> <plugins> >> >> <plugin> >> <artifactId>maven-compiler-plugin</artifactId> >> <configuration> >> <source>1.5</source> >> <target>1.5</target> >> </configuration> >> </plugin> >> >> </plugins> >> </build> >> </project> >> >> In the POM file above, >> >> - The only dependency you need to develop a GBean is >> >> <dependency> >> <groupId>org.apache.geronimo.framework</groupId> >> <artifactId>geronimo-kernel</artifactId> >> <version>2.1.3</version> >> </dependency> >> >> - We add following section to the POM only for the sake of the >> testing code. >> >> <dependency> >> <groupId>junit</groupId> >> <artifactId>junit</artifactId> >> <version>4.1</version> >> <scope>test</scope> >> </dependency> >> </dependencies> >> >> <build> >> <plugins> >> <plugin> >> <artifactId>maven-compiler-plugin</artifactId> >> <configuration> >> <source>1.5</source> >> <target>1.5</target> >> </configuration> >> </plugin> >> </plugins> >> </build> >> >> >> Deploying a GBean >> >> Follow these steps to deploy your GBean to Geronimo. >> >> 1. Deploy the GBean package. There are two methods to deploy a GBean >> package to Geronimo. >> - Deploy the .jar to the server via the *JAR repository* portlet in >> Geronimo administrative console. For example, you can deploy the >> SimpleServerGBean with the following information: >> - *GroupId*: org.apache.geronimo.sample >> - *ArtifactId*: simpleServer >> - *Version*: 1.0 >> - *Type*: jar >> - Mannually copy the jar file to the GERONIMO_HOME/repository with >> a path and package name rule. >> - Path : GroupId/ArtifactId/Version/ArtifactId-Version.Type >> - Sample: >> >> <GERONIMO_HOME>/repository/org/apache/geronimo/sample/simpleServer/1.0/simpleServer-1.0.jar >> *Note*: If the GBean depends on an external library, you have to >> deploy both .jars into the repository, and list both of them in the >> <dependencies> section of the deployment plan described below. >> 2. The next step is to develop a GBean deployment plan. A >> deployment plan is to define a Geronimo *module* as an .xml file that >> includes the descriptions of one or more instances of exsiting GBeans. >> *simpleServer_deployment_plan.xml* >> >> <?xml version="1.0" encoding="UTF-8"?><module >> xmlns="http://geronimo.apache.org/xml/ns/deployment-1.2"> >> <environment> >> <moduleId> >> <groupId>org.apache.geronimo.sample</groupId> >> <artifactId>simpleServerModule</artifactId> >> <version>1.0</version> >> <type>car</type> >> </moduleId> >> >> <dependencies> >> <dependency> >> <groupId>org.apache.geronimo.sample</groupId> >> <artifactId>simpleServer</artifactId> >> <version>1.0</version> >> </dependency> >> </dependencies> >> >> <hidden-classes /> >> >> <non-overridable-classes /> >> >> </environment> >> >> <gbean name="echoserver" >> class="org.apache.geronimo.sample.SimpleServerGBean"> >> <attribute name="port">7777</attribute> >> <attribute name="name">simpleServer</attribute> >> </gbean></module> >> >> Let's briefly go through this plan. >> - The *<moduleId>* element is used to provide the configuration name >> for the module as deployed in the Geronimo server. It contains >> elements for >> the *groupId*, *artifactId*, *version* and *type*. Module IDs are >> normally printed with slashes between the four components, such as >> GroupID/ArtifactID/Version/Type. In this example, The module ID >> will be org.apache.geronimo.sample/simpleServer/1.0/car. >> - The *<dependencies>* element is used to provide the >> configurations on which the module is dependent upon. In this example, >> the >> module is dependent on org.apache.geronimo.sample/simpleServer/1.0. >> 3. Deploy the deployment plan to the server. There are two methods to >> deploy a GBean Module with a plan to Geronimo. >> - Using the *Deploy New* portlet in the administrative console. >> - Using the >> deployer<http://cwiki.apache.org/confluence/display/GMOxDOC22/deploy#deploy-Deploy>tools >> or >> >> GShell<http://cwiki.apache.org/confluence/display/GMOxDOC22/Deploying+an+Application+to+a+Server+Instance+in+GShell>command. >> 4. If success, you can visit http://localhost:7777 and will get an >> echo from the server. >> >> *Note*: If a GBean implementation (possibly a .jar) already exisits in >> the Geronimo server, you only need to develop a deployment plan and deploy >> it to the server for the GBean instance to work. >> Referencing other GBeans >> >> Other GBeans can be used in a GBean by injecting *Reference* methods. For >> instance, the GBean *SimpleServerGBean* now makes use of another GBean >> named *EchoMessageGBean* with its POJO class and GBeanInfo implemented >> like the following: >> *EchoMessageGBean* >> >> package org.apache.geronimo.sample; >> import org.apache.geronimo.gbean.GBeanInfo;import >> org.apache.geronimo.gbean.GBeanInfoBuilder; >> public class EchoMessageGBean implements EchoMessageInterface { >> private final String msg; >> >> public EchoMessageGBean(String name) { >> this.msg = name; >> } >> >> private static final GBeanInfo GBEAN_INFO; >> >> static { >> GBeanInfoBuilder infoFactory = new GBeanInfoBuilder( >> EchoMessageGBean.class); >> >> infoFactory.addAttribute("msg", String.class, false); >> >> infoFactory.addInterface(EchoMessageInterface.class); >> >> infoFactory.setConstructor(new String[] { "msg" }); >> >> GBEAN_INFO = infoFactory.getBeanInfo(); >> } >> >> public static GBeanInfo getGBeanInfo() { >> return GBEAN_INFO; >> } >> >> public String getEchoMessage() { >> return msg; >> } >> } >> >> This EchoMessageGBean does not implement GbeanLifecycle for simplicity. >> It only exposes an interface *EchoMessageInterface* which retrieves >> predefined echo messages. >> >> To reference the *EchoMessageGBean* in SimpleServerGBean, the following >> steps have to be taken: >> >> 1. SimpleServerGBean now has more private members and a different >> constructor: *Excerpt from SimpleServerGBean POJO* >> >> private final String name;private int port; >> >> /* A new private member */private EchoMessageInterface echo; >> private boolean started = false;private ServerSocket serversocket; >> >> /* Constructor changed */public SimpleServerGBean(String name, int port, >> EchoMessageInterface echomsg) { >> this.name = name; >> this.port = port; >> this.echo= echomsg; >> } >> >> 2. In doStart() of the SimpleServerGBean implementation, we now >> retrieves messages from EchoMessageGBean and reorganizes the reponse >> message: *Excerpt from SimpleServerGBean doStart()* >> >> String appendMessage = echo.getEchoMessage();String responseMessage = >> appendMessage + bufferedReader.readLine(); >> >> 3. Add a *Reference* method to GBeanInfo: *SimpleServerGBean >> GBeanInfo* >> >> private static final GBeanInfo GBEAN_INFO; >> >> static { >> GBeanInfoBuilder infoFactory = new GBeanInfoBuilder( >> SimpleServerGBean.class.getName(), SimpleServerGBean.class); >> >> infoFactory.addAttribute("name", String.class, false); >> infoFactory.addAttribute("port", int.class, true); >> infoFactory.addOperation("isStarted", "String"); >> infoFactory.addInterface(InterfaceNamed.class); >> >> /* Add a reference */ >> infoFactory.addReference("echoMessenger",EchoMessageInterface.class); >> >> /* A different constructor */ >> infoFactory.setConstructor(new String[] { "name", "port", >> "echoMessenger"}); >> >> GBEAN_INFO = infoFactory.getBeanInfo(); >> } >> >> 4. Correspondingly, the dployment plan for SimpleServerGBean has to >> be modified. *Excerpt from simpleServer_deployment_plan.xml* >> >> <gbean name="echoserver" >> class="org.apache.geronimo.sample.SimpleServerGBean"> >> <attribute name="port">7777</attribute> >> <attribute name="name">simpleServer</attribute> >> <reference name="echoMessenger"> >> <name>msgAppender</name> >> </reference></gbean> >> <gbean name="msgAppender" >> class="org.apache.geronimo.sample.EchoMessageGBean"> >> <attribute name="msg">[Echo from server]:</attribute></gbean> >> >> After we add the .jar file to the server, and deploy the plan, the >> test class which initiates a socket on port 7777 will get a reponse >> message >> from the server. >> >> [Echo from server]: Hello simple server >> >> >> The GBean SimpleServerGBean can reference different instances of >> EchoMessageGBean. For instance, the SimpleServerGBean listens on port 7778 >> instead, and gets messages from the instance *msgAppender2*. >> *Excerpt from simpleServer_deployment_plan2.xml* >> >> <gbean name="echoserver" >> class="org.apache.geronimo.sample.SimpleServerGBean"> >> <attribute name="port">7778</attribute> >> <attribute name="name">simpleServer</attribute> >> <reference name="echoMessenger"> >> >> <!-- Reference another instance of EchoMessageGBean --> >> <name>msgAppender2</name> >> </reference></gbean> >> <gbean name="msgAppender" >> class="org.apache.geronimo.sample.EchoMessageGBean"> >> <attribute name="msg">[Echo from server]:</attribute> >> <!--Another instance of EchoMessageGBean --><gbean name="msgAppender2" >> class="org.apache.geronimo.sample.EchoMessageGBean"> >> <attribute name="msg">[Echo from server 2]:</attribute></gbean> >> >> When we deploy this plan (The .jar file does not have to be changed), >> the test class which starts a socket on port 7778 will gets the reponse from >> server 2. >> >> [Echo from server 2]: Hello simple server >> >> Geronimo Bootstrap >> >> When Geronimo starts, the <GERONIMO_HOME>/bin/server.jar is executed with >> org.apache.geronimo.cli.daemon.DaemonCLI as the main class. This will >> boot the Geronimo kernel, and load initial GBeans from module >> j2ee-system-2.1.3.car into the kenel. >> >> Powered by Atlassian >> Confluence<http://www.atlassian.com/software/confluence/default.jsp?clicked=footer>(Version: >> 2.2.9 Build:#527 Sep 07, 2006) - Bug/feature >> request <http://jira.atlassian.com/secure/BrowseProject.jspa?id=10470> >> >> Unsubscribe or edit your notifications >> preferences<http://cwiki.apache.org/confluence/users/viewnotifications.action> >> >> > > > -- > Shawn >
