Some simplification fell out of the work David Jencks and I are doing on the 1.1 branch, and I wanted to run it by everyone. I figured the easiest way to show some code. You can find the example code here also (http://svn.apache.org/viewcvs.cgi/geronimo/branches/1.1/modules/ kernel/src/test/org/apache/geronimo/kernel/SimpleGBeanTest.java? view=markup).

* The kernel is booted in the same old way

public class SimpleGBeanTest extends TestCase {
    public void test() throws Exception {
        // boot the kernel
Kernel kernel = KernelFactory.newInstance().createKernel ("test");
        kernel.boot();


* One big change is the use of ConfigurationData to load GBeans. The code creates defines a new Configuration passing in an Artifact which uniquely identifies this configuration within the kernel, and it also sets the naming system to use when generating names. The naming system is a new concept. It is used to generate GBean names with a lot less information than was in the object name. We make it pluggable so we hopefully we aren't tied to Jsr77 names forever.

        // load the configuration manager bootstrap service
ConfigurationData bootstrap = new ConfigurationData(new Artifact("bootstrap", "bootstrap", "", "car"), kernel.getNaming());

* Notice the GBean is added using a just a simple string name "ConfigurationManager".

bootstrap.addGBean("ConfigurationManager", KernelConfigurationManager.GBEAN_INFO);

* The loadBootstrapConfiguration method on ConfigurationUtil is used to load the first configuration since you do not have a configuration manager yet. This method will load and start the configuration including all services. If all services do not start an exception is thrown.

ConfigurationUtil.loadBootstrapConfiguration(kernel, bootstrap, getClass().getClassLoader());

* Notice we are getting the GBean instance directly here. This is not a proxy, so you must be careful to not leak a hard reference. Also notice that the configuration manager is obtained using a type query. If more than one service was found implementing that class an exception is thrown.

ConfigurationManager configurationManager = (ConfigurationManager) kernel.getGBean(ConfigurationManager.class);

* Now we create a second configuration to contain our test beans. Of course we could have put it in the bootstrap config but then I couldn't show you how to use the configuration manager.

        // create a configuration for our test bean
ConfigurationData configurationData = new ConfigurationData (new Artifact("test", "test", "", "car"), kernel.getNaming()); GBeanData mockBean1 = configurationData.addGBean("MyBean", TestGBean.getGBeanInfo());
        mockBean1.setAttribute("value", "1234");

* We load and start the configuration using the configuration manager. As above the if the configuration does not completely start an exception will be thrown. It will also load all parents and start all service parents.

        // load and start the configuration
Configuration configuration = configurationManager.loadConfiguration(configurationData);
        configurationManager.startConfiguration(configuration);

* Here we get the test bean instance using the short name and invoke some methods. Note it is possible to have two beans with the same short name, in which case you will get an exception.

        // invoke GBean directly
        TestGBean testGBean = (TestGBean) kernel.getGBean("MyBean");
        assertEquals("1234", testGBean.getValue());
        assertEquals("1234", testGBean.fetchValue());

* Now we invoke the bean using the kernel and the short name of the bean.

        // invoke GBean by short name
        assertEquals("1234", kernel.getAttribute("MyBean", "value"));
        assertEquals("1234", kernel.invoke("MyBean", "fetchValue"));

* Invoke the bean using the kernel and the type.

        // invoke GBean by type
assertEquals("1234", kernel.getAttribute(TestGBean.class, "value")); assertEquals("1234", kernel.invoke(TestGBean.class, "fetchValue"));

* Finally, we invoke the bean using the kernel, short name and type.

        // invoke GBean by name and type
assertEquals("1234", kernel.getAttribute("MyBean", TestGBean.class, "value")); assertEquals("1234", kernel.invoke("MyBean", TestGBean.class, "fetchValue"));

* Unload the configuration using the configuration manager.

        // stop and unload configuration
        configurationManager.stopConfiguration(configuration);
        configurationManager.unloadConfiguration(configuration);

* Shutdown the kernel as usual.

        // stop the kernel
        kernel.shutdown();
    }

*  There are a few changes to the GBeanInfo declaration...

    public static class TestGBean {
        private final String value;

        public TestGBean(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        public String fetchValue() {
            return value;
        }


        private static final GBeanInfo GBEAN_INFO;
        static {

* We automatically declare all interfaces and super classes of the GBean class in the GBeanInfo. This means that all attributes and operations are automatically declared, so there is no reason to declare them again. You still have to declare references, but this example doesn't have any.

GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(TestGBean.class);

* When you declare the constructor arg names, the GBeanInfoBuilder automatically marks them as persistent attributes. If you want to declare additional persistent attributes or manageable attributes there are two new methods on GBeanInfoBuilder setPersistentAttributes and setManageableAttributes.

            infoBuilder.setConstructor(new String[] {"value"});
            GBEAN_INFO = infoBuilder.getBeanInfo();
        }

        public static GBeanInfo getGBeanInfo() {
            return GBEAN_INFO;
        }
    }
}


In 1.2, I'd like to add code to auto generate the GBean info, so don't waste your time cleaning up GBeanInfo declarations. I would like us to update test cases to not use the kernel unless it is a kernel test, and in that case use the simpler code above... but we can hold off on that until this stuff is merged into HEAD.

-dain

Reply via email to