Apache Wicket has become on of the most popular web frameworks of these days. Especially developers with a strong Java background benefit from its Java-centric approach because all object-oriented features can be applied. This results in highly reusable code.
On the other side Cocoon implementing the pipe/filter pattern has its merits in the field of generating resources in different output formats.
The Cocoon-Wicket integration module bridges between those two web application frameworks in order to use the strenghts of both. This integration supports the integration of Cocoon into Wicket as well as the integration of Wicket into Cocoon.
Note: This is not an introduction into Apache Wicket. This documentation explains to the experienced Wicket user what needs to be done to integrate Cocoon 3 into a Wicket application.
The integration of Cocoon into Wicket is available in several ways:
A Cocoon sitemap can be mounted as
IRequestTargetUrlCodingStrategy
A single Cocoon pipeline can be mounted as IRequestTargetUrlCodingStrategy
(not implemented yet)
A CocoonSAXPipeline Wicket component can be added to a
WebPage
Whatever approach is chosen, the first step is adding cocoon-wicket
and all
its transitive dependencies to your project's classpath:
<dependency> <groupId>org.apache.cocoon.wicket</groupId> <artifactId>cocoon-wicket</artifactId> <version>3.0.0-alpha-2</version> </dependency>
Mounting in the context of Wicket means a class implementing IRequestTargetUrlCodingStrategy
is added to a Wicket web application. This interface is implemented by CocoonSitemap
:
import org.apache.cocoon.wicket.target.CocoonSitemap; import org.apache.wicket.protocol.http.WebApplication; public class SomeWebApplication extends WebApplication { @Override protected void init() { ... this.mount(new CocoonSitemap("/sitemap", "/sitemap.xmap.xml")); ... } }
The first parameter is the mount path which is a part of the request URI that should be
handled by |
Additionally you have to make sure that all Spring bean definitions provided by the Cocoon modules are
loaded into the web application's Spring application context. Cocoon's own bean definitions are located in
META-INF/cocoon/spring/*.xml
.
The simplest solution for this task is referring to the Cocoon Spring Configurator in your main Spring application context,
which is usually located in [servlet-context-base-directory]/WEB-INF/applicationContext.xml
. It will
automatically load all bean definitions located in META-INF/cocoon/spring/*.xml
of all libraries
on the classpath.
The
Cocoon Spring Configurator documentation contains further details.
Note that the Spring Configurator is one of the transitive dependencies of cocoon-wicket
.
That's it! Everything else is the same as using Cocoon 3 outside of Wicket except that the
servlet:/
protocol won't work in this environment.
NOTE: This hasn't been implemented yet!
Mounting a Cocoon pipeline follows the same idea as mounting a whole sitemap. However, it's only a single pipeline that is added to Wicket's URI path and that this can be done without having to write any XML.
All that needs to be done is subclassing from org.apache.cocoon.wicket.AbstractCocoonPipeline
and implementing its addComponents
method:
import com.mycompany.MyCocoonPipeline; import org.apache.wicket.protocol.http.WebApplication; public class SomeWebApplication extends WebApplication @Override protected void init() { ... this.mount(new MyCocoonPipeline("/my-pipeline")); ... } }
The only parameter is the path where the pipeline should be be mounted by Wicket. |
In MyCocoonPipeline
all that needs to be done is subclassing from
org.apache.cocoon.wicket.AbstractCocoonPipeline
and implementing its abstract method
addComponents
:
package com.mycompany; import org.apache.cocoon.wicket.AbstractCocoonPipeline; import org.apache.wicket.protocol.http.WebApplication; public class MyCocoonPipeline extends org.apache.cocoon.wicket.AbstractCocoonPipeline<SAXPipelineComponent> @Override protected void addComponents() { this.addComponent(new FileGenerator(this.getClass().getResource("test.xml"))); this.addComponent(new XSLTTransformer(this.getClass().getResource("test.xsl"))); this.addComponent(new XMLSerializer()); } }
Add all pipeline components that are required. |
The third alternative of using Cocoon in Wicket is adding a Cocoon pipeline as
WebComponent
.
This is as simple as instantiating CocoonSAXPipeline
and adding
all generators and transformers that are required:
import org.apache.cocoon.pipeline.NonCachingPipeline; import org.apache.cocoon.sax.SAXPipelineComponent; import org.apache.cocoon.sax.component.StringGenerator; import org.apache.cocoon.sax.component.XSLTTransformer; import org.apache.cocoon.wicket.CocoonSAXPipeline; import org.apache.wicket.markup.html.WebPage; public class Homepage extends WebPage { public Homepage() { CocoonSAXPipeline pipeline = new CocoonSAXPipeline("cocoon-pipeline-component", new NonCachingPipeline<SAXPipelineComponent>()); pipeline.addComponent(new StringGenerator("<b>hello, Cocoon!</b>")); pipeline.addComponent(new XSLTTransformer( this.getClass().getResource("transform.xslt"))); this.add(pipeline); } }
Instantiate the component | |
Adding SAX pipeline components |
The pipeline's result is added to the HTML produced by this page. This is the reason why only generators and transformers can be added to this component because the pipeline is always serialized as XHTML. An XHTMLSerializer is added implicitly to each pipeline.
Note: The integration of Wicket into Cocoon os mostly a proof of concept. It is experimental and has neither been optimized nor tested yet.
The integration of Wicket into Cocoon means that the output of Wicket is added to the content stream of a pipeline. The currently available solution is a reader but alternatively a generator or a transformer would offer an even more alternatives.
As pointed out for the Wicket-Cocoon integration, the first step in every case is adding cocoon-wicket
and all
its transitive dependencies to your project's classpath:
<dependency> <groupId>org.apache.cocoon.wicket</groupId> <artifactId>cocoon-wicket</artifactId> <version>3.0.0-alpha-2</version> </dependency>
By using the Wicket reader a servlet request is referred to a Wicket web application. The current implementation expects exactly one Wicket web application being available as Spring bean:
<beans> <bean id="wicketWebapp" class="com.mycompany.MyWicketWebapp"/> </beans>
By adding the bean definition file as resource into META-INF/cocoon/spring
the
Wicket web application bean will be loaded automatically.
Then the Wicket reader has be to used in the sitemap:
<map:sitemap> <map:pipelines> <map:pipeline type="noncaching"> <map:match wildcard="my-wicket-app/**"> <map:read type="wicket" base-path="/my-wicket-app" /> </map:match> </map:pipeline> </map:pipelines> </map:sitemap>
Use a | |
The name of the reader is |