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