cancel
Showing results for 
Search instead for 
Did you mean: 

Using Ant to perform content conversions

dafletcha
Champ in-the-making
Champ in-the-making
I'm trying to hook up the DITA Open Toolkit (which runs on Ant) to Alfresco. For now, I just want to enable XML->PDF transforms.

I've created a "my-transformers-context.xml file", but I have some questions. Here's how my transform bean is defined:

(I've edited my original post. I'm now using a 2-step transform: xml to fo, fo to pdf)

<bean     id="transformer.DITA-OT.xml2fo"
         class="org.alfresco.repo.content.transform.RuntimeExecutableContentTransformer"
        parent="baseContentTransformer">
      <property name="transformCommand">
         <bean class="org.alfresco.util.exec.RuntimeExec">
            <property name="commandMap">
                <map>
                    <entry key="Windows.*">
         <value>c:\ant\bin\workday_publish -f workday_build.xml -DAlfresco.input.filename='${source}' -DAlfresco.output.filename='${target}' dita.Alfresco.xml2fo</value>
                    </entry>
                </map>
            </property>
            <property name="errorCodes">
               <value>2</value>
            </property>
         </bean>
      </property>
      <property name="explicitTransformations">
         <list>
            <bean class="org.alfresco.repo.content.transform.ContentTransformerRegistry$TransformationKey" >
                <constructor-arg><value>text/xml</value></constructor-arg>
                <constructor-arg><value>text/fo</value></constructor-arg>
            </bean>
         </list>
      </property>
   </bean>

   <bean    id="transformer.DITA-OT.fo2pdf"
         class="org.alfresco.repo.content.transform.RuntimeExecutableContentTransformer"
        parent="baseContentTransformer">
      <property name="transformCommand">
         <bean class="org.alfresco.util.exec.RuntimeExec">
            <property name="commandMap">
                <map>
                    <entry key="Windows.*">
         <value>c:\ant\bin\workday_publish -f workday_build.xml -DAlfresco.input.filename='${source}' -DAlfresco.output.filename='${target}' dita.Alfresco.fo2pdf</value>
                    </entry>
                </map>
            </property>
            <property name="errorCodes">
               <value>2</value>
            </property>
         </bean>
      </property>
      <property name="explicitTransformations">
         <list>
            <bean class="org.alfresco.repo.content.transform.ContentTransformerRegistry$TransformationKey" >
                <constructor-arg><value>text/fo</value></constructor-arg>
                <constructor-arg><value>application/pdf</value></constructor-arg>
            </bean>
         </list>
      </property>
   </bean>

   <bean     id="transformer.complex.DITA-XML.PDF"
          class="org.alfresco.repo.content.transform.ComplexContentTransformer"
         parent="baseContentTransformer" >
      <property name="transformers">
         <list>
            <ref bean="transformer.DITA-OT.xml2fo" />
            <ref bean="transformer.DITA-OT.fo2pdf" />
         </list>
      </property>
      <property name="intermediateMimetypes">
         <list>
            <value>text/fo</value>
         </list>
      </property>
   </bean>


BTW, I've added text/fo to mimetype-map.xml.

I've turned on debugging for org.alfresco.repo.action, and here's what I see:

09:57:14,281 DEBUG [org.alfresco.repo.action.executer.TransformActionExecuter] No transformer found to execute rule:
   reader: ContentAccessor[ contentUrl=store://2006/3/14/9/f628d6a4-b383-11da-932f-69d192a6ffa4.bin, mimetype=text/xml, size=2595, encoding=UTF-8]
   writer: ContentAccessor[ contentUrl=store://2006/3/14/9/f7eddf66-b383-11da-932f-69d192a6ffa4.bin, mimetype=application/pdf, size=0, encoding=UTF-8]
   action: ParameterizedItem[ title='transform.title', description='transform.description']

So I guess there's something wrong with my bean definitions? Why isn't my transformer found by the system?


Thanks in advance for any help.
6 REPLIES 6

derek
Star Contributor
Star Contributor
Hi,

I presume that you are running against the V1.2 distribution.  There were some bugs with that RuntimeExecutableContentTransformer, causing the transformer to not register properly.  This has been fixed on the HEAD as well as the V1.2.0 branch, which will eventually be released as V1.2.1.

If you don't want to wait, then checkout the source:

   > svn co svn://www.alfresco.org/alfresco/BRANCHES/V1.2.0/root alfresco-1.2.0-branch
   > cd alfresco-1.2.0-branch
   > set TOMCAT_HOME=wherever
   > ant -f common\build.xml build-tomcat
Now, when you start Tomcat, you should have more luck.  All your config looks fine, so sorry for the bugs.

You can turn on logging for org.alfresco.repo.content.transform.ContentTransformerRegistry to see which transformers are being registered, etc.

One point to note, is that you can extend the mimetypes, rather than modifying the files coming out of the war: http://wiki.alfresco.com/wiki/Adding_a_Mime_Type
Make sure that all your config is in the appropriate shared location of the server and you should be fine.

Regards

dafletcha
Champ in-the-making
Champ in-the-making
Thanks, Derek. I did the rebuild but am still getting the same error: No transformer found to execute rule

I know I've got the new code, because when I first started up, it found a problem with the Tidy conversion bean that I had been using in my transformers-context.xml file as a template. (It never choked on that code before.) When I commented out the Tidy bean, startup was fine and I saw messages saying that my transformers were being registered.

So I'm guessing that my problem is in the implementation of the transformers?  Here's what I'm doing to test:

I've created a rule: Inbound, condition=XML mimetype, action=Transform and copy content, format=PDF.
I Add Content and select an xml file to import.
The file is imported, but not transformed, and the error occurs.

Is it a problem trying to use your prebuilt "copy and transform" action? If so, how do I add my transform to the menu, or override the default behavior?

Thanks very much!

derek
Star Contributor
Star Contributor
Hi,

There have not been any issues with the action.

Stick on debug for org.alfresco.util.exec.RuntimeExec.

Regards

dafletcha
Champ in-the-making
Champ in-the-making
I really appreciate the help, Derek. I found and fixed a problem in my bean definition. I was mucking around too much yesterday trying to debug 🙂  Also, after rebuilding, I hadn't readded "text/fo" to the mimetypes file.

Now I'm getting very close. Now my command is actually firing, but it's throwing an error:

java.io.IOException: CreateProcess: workday_publish -f workday_build.xml -DAlfresco.input.filename="C:\alfresco\tomcat\temp\Alfresco\RuntimeExecutableContentTransformer_source_7164.xml" -DAlfresco.output.filename="C:\alfresco\tomcat\temp\Alfresco\RuntimeExecutableContentTransformer_target_7165.fo" Alfresco.xml2fo error=2

I'm able to run this very same command from the cmd window (minus the trailing "error=2"), and from any directory.  I thought perhaps the double quotes were causing a problem in java, so I tried escaping them with a backslash, but that didn't help. I also tried using single quotes instead of double, but then the command fails at the cmd window.

Any ideas?

dafletcha
Champ in-the-making
Champ in-the-making
OK, the stupid problem with my command syntax was that I didn't include ".bat" with the batch file name. After that, the commands ran.

Thanks again for your help, Derek!

If anyone reading this is also trying to hook up the DITA Toolkit, here's some advice:

Don't try and do a 2-step conversion as shown above. It's probably impossible to do so without a lot of work. I was using the two antcalls found in topic2pdf (conductor.xml) as my two distinct explicit transforms: dita.topic.fo for xml->fo and dita.fo2pdf for fo->pdf. However, that second antcall relies on finding the original xml file to generate its output. In Alfresco, the source and target filenames are incremented during each step in the transform, so you don't know what your original xml filename was when you call the second step.

However, you can't just call dita2pdf either, because that spits out a pdf file with the same nameroot as the xml source–while Alfresco is expecting a target file with a different nameroot than the source. So…. do something like this:

1) Create a copy of dita2pdf and its two sub-targets, topic2pdf and map2pdf, (all found in conductor.xml) and give them unique names.

2) Modify the two dita.fo2pdf antcalls to pass Alfresco's target filename as the "output" parameter.

3) Create a master target that will call your personalized dita2pdf.

4) Add a dirname property that derives the path from Alfresco's target file.

5) Have the master target call your custom dita2pdf, passing Alfresco's source file as "args.input" and the new dirname property as "output.dir".

Here's my Ant code:

<!– This is the target that the Alfresco transform points to –>
      <target name="Alfresco.DITA-XML2PDF">
      <!– Get the path of Alfresco's target file –>
      <dirname property="Alfresco.target.path" file="${Alfresco.target.filename}"/>
      <!– Call your custom dita2pdf target –>
      <antcall target="my.dita2pdf">
         <param name="args.input" value="${Alfresco.source.filename}"></param>
         <param name="output.dir" value="${Alfresco.target.path}"></param>
      </antcall>           
        </target>

      <!– This is just a renamed copy of dita2pdf. Remember to rename the pointers to map2pdf and topic2pdf too. –>
     <target name="my.dita2pdf" depends="dita-preprocess, my.map2pdf, my.topic2pdf"></target>  
 
   <!– A renamed copy of topic2pdf, with just one change to dita.fo2pdf… –>
     <target name="my.topic2pdf" if="noMap" depends="dita-preprocess">
          <antcall target="dita.topic.fo">
            <param name="input" value="${dita.temp.dir}${file.separator}${user.input.file}"></param>
            <param name="output" value="${dita.map.output.dir}${file.separator}${dita.topic.filename.root}.fo"></param>
          </antcall>
      <antcall target="dita.fo2pdf">
            <param name="input" value="${dita.map.output.dir}${file.separator}${dita.topic.filename.root}.fo"></param>
         <!– Change the original param value to Alfresco's target filename –>
            <param name="output" value="${Alfresco.target.filename}"></param>
          </antcall>
     </target>
 
   <!– Same changes as above –>
      <target name="my.map2pdf" unless="noMap" depends="dita-preprocess">
          <antcall target="dita.map.fo">
            <param name="input" value="${dita.temp.dir}${file.separator}${user.input.file}"></param>
            <param name="output" value="${dita.map.output.dir}${file.separator}${dita.map.filename.root}.fo"></param>
          </antcall>
          <antcall target="dita.fo2pdf">
            <param name="input" value="${dita.map.output.dir}${file.separator}${dita.map.filename.root}.fo"></param>
            <param name="output" value="${Alfresco.target.filename}"></param>
          </antcall>
     </target>


And here's my Alfresco transform bean:

<bean id="transformer.DITA-XML.PDF"
         class="org.alfresco.repo.content.transform.RuntimeExecutableContentTransformer"
        parent="baseContentTransformer">
      <property name="transformCommand">
         <bean class="org.alfresco.util.exec.RuntimeExec">
            <property name="commandMap">
                <map>
                    <entry key="Windows.*">
         <value>ant.bat -f my_build.xml -DAlfresco.source.filename="${source}" -DAlfresco.target.filename="${target}" Alfresco.DITA-XML2PDF</value>
                    </entry>
                </map>
            </property>
            <property name="errorCodes">
               <value>2</value>
            </property>
         </bean>
      </property>
      <property name="explicitTransformations">
         <list>
            <bean class="org.alfresco.repo.content.transform.ContentTransformerRegistry$TransformationKey" >
                <constructor-arg><value>text/xml</value></constructor-arg>
                <constructor-arg><value>application/pdf</value></constructor-arg>
            </bean>
         </list>
      </property>
   </bean>

derek
Star Contributor
Star Contributor
Hi,

Nice work.  Did you manage to externalize the mimetype configuration?  If you have suggestions on how the parameterization of the compound transformer and exec classes might interact, then feel free to raise a feature request/enhancement on JIRA.

Just for others reading, the exception java.io.IOException: CreateProcess will arise when the command cannot be executed.  A more descriptive exception is shown with the error code and the captured  stderr and stdout when the command executes but fails.

Regards