The Managed Container

 

Author: Eike Stepper

An IManagedContainer combines a factory registry with a registry of named runtime elements. A product group identifies a service family, a factory type selects an implementation, and a description carries the instance key or configuration (for example, a TCP endpoint). A lookup that needs an absent product can create it through the matching factory; a put retains an already-created object. Container events report additions and removals. The container coordinates lifecycle for elements it owns, including dependencies acquired by factory products. Choose the shared OSGi container for bundle-managed server applications and an independent initialized container for a standalone application. Do not deactivate the shared plugin container.

1 Factories, Product Groups, and Lookup
2 Lifecycle and Configuration
3 Standalone Container Example

1  Factories, Product Groups, and Lookup

Register an factory before asking a raw, unprepared container to create its product. An registered factory is selected by its own product group and type; an OSGi application's declarative factories are contributed by bundles and become available through the plugin container. Use IManagedContainer.getProductGroups() and IManagedContainer.getFactoryTypes(String) for discovery, and use component constants rather than literal keys. getElement resolves a factory, creates the product if necessary, retains it under the group/type/description key, and activates lifecycle products. getElementOrNull only returns an existing element; putElement retains a caller-created element. A factory can obtain dependencies from the same container, which makes container ownership extend to the assembled runtime graph.

Repositories use RepositoryFactory.PRODUCT_GROUP and are normally obtained with CDOServerUtil.getRepository(IManagedContainer, String). The factory creates a repository; the container locates and owns the registered instance. The short lookup form is shown in

RepositoryLookup.java      
return CDOServerUtil.getRepository(container, repositoryName);

.

2  Lifecycle and Configuration

ContainerUtil.createContainer() returns an empty, inactive ManagedContainer; it has no CDO/Net4j factory contributions until the application registers or prepares them. For ordinary standalone use, ContainerUtil.createInitializedContainer() creates a distinct container, loads available platform and declarative factory/element-processor contributions, initializes it, and activates it for immediate lookup. “Initialized” does not mean that the application's repositories or acceptors already exist: factories are ready, while products are created as requested. The convenience method is current; do not call deprecated ContainerUtil.prepareContainer, CDOServerUtil.prepareContainer, or component-specific preparation methods on its result. A deliberately raw container can instead be prepared through the supported OMBundle mechanism and activated by its owner. In OSGi, the shared plugin container is managed globally.

Products created through the container are activated as they are created and stopped when removed or when the owner deactivates. Products inserted with putElement are retained and become container-owned; do not independently close a product after transferring ownership. For server XML, use the repository configurator described in CDO Server Application and Startup, not generic container configuration. Deactivate an application-owned container at shutdown so its elements and dependencies are released.

3  Standalone Container Example

The initialized container is the owner of the acceptor created through it. The caller's work runs while that acceptor is active; deactivating the container releases it even when the work fails.

WithStandaloneAcceptor.java      
IManagedContainer container = ContainerUtil.createInitializedContainer();
try
{
  ITCPAcceptor acceptor = TCPUtil.getAcceptor(container, endpoint);
  serverWork.accept(acceptor);
}
finally
{
  container.deactivate();
}