cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Robby Pelssers <>
Subject RE: possible design flaw in linking of pipelines (C3)
Date Fri, 07 Dec 2012 15:21:12 GMT
Just for the sake of it.... You wouldn't run into this issue if you set the system property
and just left the factoryclassname null.  


Because in that case TRAX_FACTORY will ALWAYS create a new instance using the same TransformerFactory


-----Original Message-----
From: Robby Pelssers [] 
Sent: Friday, December 07, 2012 4:12 PM
Subject: possible design flaw in linking of pipelines (C3)

Hi guys,

Sorry if I make unnecessary noise here due to my incompetence. But I was trying to refactor
org.apache.cocoon.sax.component.XSLTTransformer by enabling users to choose a transfomerfactory
of their choice. I added a new constructor and did some basic refactoring.  

    public XSLTTransformer(final URL source, final Map<String, Object> attributes, final
String factoryClassName) {
        this.loadXSLT(source, attributes, factoryClassName);

private void loadXSLT(final URL source, final Map<String, Object> attributes, final
String factoryClassName) {
            SAXTransformerFactory transformerFactory;
            if (factoryClassName != null) {
                //we need to use factoryclassname
                transformerFactory = createNewSAXTransformerFactory(factoryClassName, null);
            } else {
                //we need to check for attributes
                if (attributes == null || attributes.isEmpty()) {
                    //we can use static factory
                    transformerFactory = TRAX_FACTORY;
                } else {
                    //we need to instantiate new default factory
                    transformerFactory = createNewSAXTransformerFactory();

    private static SAXTransformerFactory createNewSAXTransformerFactory() {
        return (SAXTransformerFactory) TransformerFactory.newInstance();

    private static SAXTransformerFactory createNewSAXTransformerFactory(final String factoryClassName,
final ClassLoader classLoader) {
       return (SAXTransformerFactory) TransformerFactory.newInstance(factoryClassName, classLoader);

But then I hit a brick wall while running the unit test below:

    public void testPipelineWithMultipleXSLTProcessors() throws Exception {
             .setStarter(new XMLGenerator(getClass().getResource("/movies.xml")))
             .addComponent(new XSLTTransformer(this.getClass().getResource("/moviesByDirector.xslt"),
null, "net.sf.saxon.TransformerFactoryImpl"))
             .addComponent(new XSLTTransformer(this.getClass().getResource("/indent.xslt"),
null, "org.apache.xalan.processor.TransformerFactoryImpl"))
             .setFinisher(new XMLSerializer())

Don’t look at linenumbers as I have different code now of course (and I added saxon as dependency
to test this):

org.apache.cocoon.pipeline.SetupException: Could not initialize transformer handler.
	at org.apache.cocoon.sax.component.XSLTTransformer.setSAXConsumer(
	at org.apache.cocoon.sax.AbstractSAXProducer.setConsumer(
	at org.apache.cocoon.pipeline.AbstractPipeline.linkComponents(
	at org.apache.cocoon.pipeline.AbstractPipeline.setupComponents(
	at org.apache.cocoon.pipeline.AbstractPipeline.setup(
	at org.apache.cocoon.pipeline.CachingPipeline.setup(
	at org.apache.cocoon.pipeline.AbstractPipeline.setup(
	at org.apache.cocoon.pipeline.builder.PipelineBuilder$1$1$1$1.setup(
	at org.apache.cocoon.sax.PipelineTest.testPipelineWithMultipleXSLTProcessors(
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(
	at com.intellij.rt.execution.junit.JUnitStarter.main(
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(
	at com.intellij.rt.execution.application.AppMain.main(
Caused by: java.lang.ClassCastException: net.sf.saxon.Controller cannot be cast to org.apache.xalan.xsltc.trax.TransformerImpl
	at org.apache.xalan.xsltc.trax.TransformerFactoryImpl.newTransformerHandler(
	at org.apache.cocoon.sax.component.XSLTTransformer.setSAXConsumer(
	... 30 more

This is probably due to 

    protected void setSAXConsumer(final SAXConsumer consumer) {
        TransformerHandler transformerHandler;
        try {
            transformerHandler = TRAX_FACTORY.newTransformerHandler(this.templates);
        } catch (Exception e) {
            throw new SetupException("Could not initialize transformer handler.", e);

I think we shouldn’t just ALWAYS create a new transformerhandler using the default TRAX_FACTORY
but it should the same SAXTransformerFactory we created in loadXSLT.

But setSAXConsumer is called from within AbstractPipeline.setConsumer which again translates
to AbstractSAXProducer.setConsumer which sets the SaxConsumer.

mmmm....   Anyone who is expert in this matter?  

View raw message