Page History
This article refers to components as in java objects that make up the foundation of the system and is not to be confused with "page components" in templating.
Table of Contents |
---|
Abstract
Terms
- Container, responsible for managing components.
- Component, anything that's configured in and managed by a container.
- ComponentProvider, is our container abstraction.
...
The key method provided by ComponentProvider is getComponent()
which is used to get the component for a specific type.
Code Block |
---|
public interface ComponentProvider {
T getComponentClass<T> type);
}
|
...
The module descriptor can specify components for different containers. This is done using the id
tag. You will rarely use a container other than main
. Here is how the XML is structured:
Code Block |
---|
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module SYSTEM "module.dtd">
<module>
...
<components>
<id>main</id>
<configurer>
...
</configurer>
<component>
...
</component>
<type-mapping>
...
</type-mapping>
</components>
</module>
|
...
A typical component definition
Code Block |
---|
<component>
<type>info.magnolia.cms.filters.FilterManager</type>
<implementation>info.magnolia.cms.filters.FilterManagerImpl</implementation>
<scope>singleton</scope>
<lazy>true</lazy>
</component>
|
...
Component via provider
Code Block |
---|
<component>
<type>info.magnolia.cms.beans.config.ServerConfiguration</type>
<provider>info.magnolia.cms.beans.config.ServerConfiguration$InstanceFactory</provider>
<scope>singleton</scope>
</component>
|
...
Components from JCR
Code Block |
---|
<component>
<type>info.magnolia.cms.beans.config.URI2RepositoryManager</type>
<workspace>config</workspace>
<path>/server/URI2RepositoryMapping</path>
<observed>true</observed>
<scope>singleton</scope>
</component>
|
...
A type mapping is defined in the module descriptor alongside components:
Code Block |
---|
<type-mapping>
<type>info.magnolia.cms.core.AggregationState</type>
<implementation>info.magnolia.module.templatingkit.ExtendedAggregationState</implementation>
</type-mapping>
|
The ComponentProvider has a method for creating instances using these mappings:
Code Block |
---|
public interface ComponentProvider {
T newInstance(Class<T> type);
}
|
...
ComponentProvider can also take a set of additional arguments that will be used as constructor arguments in addition to those resolved using dependency injection.
Code Block |
---|
public interface ComponentProvider {
T newInstance(Class<T> type, Object... parameters);
}
|
It is also possible to pass in a list of custom parameter resolvers that will then assist in resolving the parameters to use.
Code Block |
---|
public interface ComponentProvider {
T newInstance(Class<T> type, ParameterResolver... parameters);
}
|
...
This is an example of what it used to look like:
Code Block |
---|
<properties>
<property>
<name>info.magnolia.module.templatingkit.sites.SiteManager</name>
<value>info.magnolia.module.templatingkit.sites.STKSiteManager</value>
</property>
<property>
<name>info.magnolia.cms.core.AggregationState</name>
<value>info.magnolia.module.templatingkit.ExtendedAggregationState</value>
</property>
</properties>
|
The equivalent component definition looks like this:
Code Block |
---|
<components>
<id>main</id>
<component>
<type>info.magnolia.module.templatingkit.sites.SiteManager</type>
<implementation>info.magnolia.module.templatingkit.sites.STKSiteManager</implementation>
<scope>singleton</scope>
<lazy>true</lazy>
</component>
<type-mapping>
<type>info.magnolia.cms.core.AggregationState</type>
<implementation>info.magnolia.module.templatingkit.ExtendedAggregationState</implementation>
</type-mapping>
</components>
|
...
This is an example of all three:
Code Block |
---|
public class RenderingEngine {
@Inject
private TemplateRegistry templateRegistry;
@Inject
public SomeComponent(ModuleManager moduleManager) { ... }
@Inject
public void setRendererRegistry(RendererRegistry rendererRegistry) { ... }
}
|
...
It is also possible to inject properties like this:
Code Block |
---|
@Inject
@Named("magnolia.develop")
private Provider<String> developmentMode;
|
...
When accessing an object in a lesser scope, inject a Provider
and call it when you need the object. For instance AggregationStateBasedRenderingContext
is scoped with @RequestScoped
. To access it the rendering engine depends on it like this:
Code Block |
---|
public class RenderingEngine {
public RenderingEngine(Provider<RenderingContext> renderingContextProvider) { ... }
}
|
life cycle callbacks
...
Component life cycle
A component has a life cycle with these steps
- Instantiation, the constructor annotated with
@Inject
is called with arguments resolved by the container or the default no-args constructor is used. - Fields annotated with
@Inject
are filled. - Methods annotated with
@Inject
are called with arguments resolved by the container. @PostConstruct
is called.- Component is in use.
@PreDestroy
is called when the container is closed down.
Google Guice integration
...