Webservice Ansprache mit der Ant-Task Bibliothek

Wenn Sie Apache Ant nutzen, …

… dann liegt für Sie vielleicht die Frage nahe: Ließen sich die webPDF Webservices nicht aus einem Ant Target heraus aufrufen? Dies würde Ihnen die Möglichkeit bieten, einen festen Ablauf an aufeinander folgenden Webserviceaufrufen zu definieren, der automatisch für eine große Zahl an Dokumenten wiederholbar wäre. (Picture: https://www.apache.org/)

Die kurze Antwort:

Ja, das geht!

Die „webPDF ant-task“ Bibliothek (kurz „ant-task“) definiert einige einfache Tasks, die Sie nutzen können, um einzelne oder gleich mehrere webPDF Webserviceaufrufe zu starten oder deren Ausführung hintereinander zu schalten. Diese Bibliothek bietet Ihnen somit eine Reihe einfacher Werkzeuge, um komplexe Arbeitsabläufe zur Erzeugung, Manipulation oder Auswertung von PDF-Dokumenten zu realisieren.

(Die Webservice-Aufrufe selbst werden mittels der „webPDF wsclient“-Bibliothek durchgeführt, die Sie vielleicht ebenfalls interessieren könnte.)

ant-task auf GitHub und in Maven Central

Die öffentlich zugängliche und kostenlose ant-task-Bibliothek lässt sich in alle Ant-basierten Bauprozesse einbinden (ab webPDF Server Version 7). Wir stellen Ihnen die Bibliothek als öffentliches Projekt unter GitHub zur Verfügung:

https://github.com/softvision-dev/webpdf-ant

In diesem öffentlichen Projekt wird die Bibliothek von uns gepflegt, weiterentwickelt und an neue Versionen von webPDF angepasst. Ihr Feedback oder Anmerkungen und Ideen zur Weiterentwicklung sind uns jederzeit willkommen. Wenn Sie Probleme finden, melden Sie bitte einen Fehler, nachdem Sie nach Duplikaten gesucht haben, oder erstellen Sie eine Pull-Anfrage.

Zur direkten und einfachen Integration in Ihr Projekt, stellen wir die Bibliothek in der aktuellsten Version auch immer als Maven-Paket über Maven-Central zur Verfügung:

<dependency>
    <groupId>net.webpdf</groupId>
    <artifactId>webpdf-ant</artifactId>
    <version>1.0.0</version>
</dependency>

Mittels Apache IVY lässt sich die Bibliothek folgendermaßen in Ihrer ivy.xml einbinden:

<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="2.0">
  <info organisation="org.apache" module="hello-ivy"/>
  <dependencies>
    <dependency org="net.webpdf" name="webpdf-ant" rev="1.0.0"/>
  </dependencies>
</ivy-module>

webPDF webserviceaufruf aus einem Ant Target

Im Folgenden möchten wir eine Ant build-Datei entwickeln, die in der Lage ist, Dateien aus einem Ordner zu entnehmen, sie über den Converter Webservice in das PDF-Format zu konvertieren und die Ergebnisse in einen Zielordner zu schreiben.

Der Converter Webservice dient hier lediglich als Platzhalter für alle anderen webPDF Webservices. Alle übrigen Webservices können in ähnlicher Form aufgerufen werden.

Definition des Projekts und Vorarbeiten

Wir beginnen unsere Ant build-Datei wie üblich mit der Deklaration des Projekts und definieren die Namespaces ivy (um die webPDF Ant-Task Bibliothek über IVY beziehen zu können) und webpdf (um die Tasks leichter aufrufen zu können.) :

<project name="ant-task" default="executeWebPDFTask" basedir="."
         xmlns:ivy="antlib:org.apache.ivy.ant"
         xmlns:webpdf="http://schema.webpdf.de/1.0/operation">

Wir definieren nun das aufzurufende Target und stellen zunächst sicher, dass sowohl unser Quell-, als auch unser Zielordner bereitstehen:

<target name="executeWebPDFTask">
    <mkdir dir="source-documents"/>
    <mkdir dir="target-documents"/>

Danach beziehen wir die nötigen Bibliotheken mittels ivy und laden die Task Definitionen (antlib.xml) für unseren Webserviceaufruf aus der ant-task-Bibliothek:

<ivy:resolve/>
<ivy:retrieve/>
<taskdef resource="antlib.xml"
    classpath="lib/webpdf-ant-1.0.0.jar"/>

Der „webpdf“ Task

Der webpdf task ist der Einstiegspunkt für die Definition eines webPDF Webserviceaufrufs und definiert grundsätzliche Optionen und Parameter für den Verbindungsaufbau zum webPDF Server und die auszuführenden Webservices.

Der Task wird wie folgt definiert:

<webpdf serverurl="http://localhost:8080/webPDF"
        targetdir="target-documents"
        failonerror="true">

Der Task selbst stellt folgende Attribute zur Verfügung:

  • serverurl Die Adresse (und der Port) des webPDF Servers, auf dem Webservices ausgeführt werden sollen.
  • tempdir (optional) Wird dieser Pfad übergeben, so werden temporäre Dateien an dieser Stelle erzeugt statt im systemweiten, temporären Verzeichnis.
  • targetdir Gibt einen Pfad an, in dem die Ergebnisse der Webservice Aufrufe gespeichert werden.
  • failonerror (optional) wird dieser boolesche Wert auf „true“ gesetzt, wird die Ausführung beim ersten auftretenden Fehler sofort unterbrochen.

Authentifizierung

Falls der webPDF Server einen Nutzernamen und ein Passwort benötigt, so können diese im Element webpdf in einem Element usercredentials angegeben werden:

<usercredentials username="admin" password="admin"/>

Das Element stellt folgende Attribute zur Verfügung:

  • username Der Nutzername.
  • password Das zugehörige Passwort.

Auswahl der Quelldateien

Um dem task eine oder mehrere Quelldokumente zur Verarbeitung zu übergeben, können wir dem webpdf Task entweder ein „file“ oder ein „fileset“ Element übergeben. Beispielsweise würde folgende Definition dazu führen, dass sämtliche PNG Dateien, die wir in unseren Quellordner legen, nacheinander durch den Task verarbeitet würden:

<fileset dir="source-documents">
    <include name="**/*.png"/>
</fileset>

Über ein entsprechendes Mapping kann hier die Namenswahl für die erzeugten Dokumente beeinflusst werden – beispielsweise würde folgendes Mapping dazu führen, dass sämtliche erzeugten Dokumente den gleichen Namen wie ihr Quelldokument erhalten würden, aber mit der Endung „pdf“, statt „png“.

<globmapper from="*.png" to="*.pdf"/>

Der “operation“ Task

Um den gewünschten webPDF Webservice Endpunkt zu wählen und parametrisieren, nutzen wir den operation Task. Dort können wir ein Element hinterlegen, das den angesprochenen Endpunkt wiederspiegelt, sämtliche seiner Parameter über Attribute zur Verfügung stellt und alle Unterstrukturen enthalten darf, wie im Nutzerhandbuch beschrieben. In unserem Fall ist dies also das converter Element, das wir zum Beispiel wie folgt definieren:

<webpdf:operation>
    <webpdf:converter pages="1" jpegQuality="100"/>
</webpdf:operation>

Der “group“ Task

Ein operation Task kann dem webpdf Task nicht direkt hinzugefügt werden und muss immer in einem group Task enthalten sein. Ein group Task bündelt mehrere Webservice Aufrufe und bringt diese in eine feste Ausführungsreihenfolge. Jeder im group Task definierte Webserviceaufruf nutzt hierbei das Ergebnisdokument des vorhergehenden Aufrufs als sein Ausgangsdokument. Standardmäßig werden alle hierbei entstehenden Zwischenergebnisse nur temporär gespeichert und gelöscht, sobald sie nichtmehr benötigt werden.

Wir möchten in diesem Fall zunächst nur den Converter Webservice aufrufen und fassen ihn somit wie folgt in einen group Task:

<group>
    <webpdf:operation>
        <webpdf:converter pages="1" jpegQuality="100"/>
    </webpdf:operation>
</group>

group Tasks werden im webpdf Task definiert. Ausschließlich das Ergebnis der letzten Operation, der letzten Gruppe des webpdf Tasks wird üblicherweise in das Zielverzeichnis geschrieben.

Das Ergebnis

Insgesamt ergibt sich also folgendes Ergebnis:

<?xml version="1.0" encoding="UTF-8"?>
<project name="ant-task" default="executeWebPDFTask" basedir="."
         xmlns:ivy="antlib:org.apache.ivy.ant"
         xmlns:webpdf="http://schema.webpdf.de/1.0/operation">

    <target name="executeWebPDFTask">
        <echo>+++ PREPARE +++</echo>
        <mkdir dir="source-documents"/>
        <mkdir dir="target-documents"/>

        <echo>+++ IVY RESOLVE DEPENDENCIES +++</echo>
        <ivy:resolve/>
        <ivy:retrieve/>
        <taskdef resource="antlib.xml"
        classpath="lib/webpdf-ant-1.0.0.jar"/>

        <echo>+++ EXECUTE WEBPDF-TASK +++</echo>
        <webpdf serverurl="http://localhost:8080/webPDF"
                targetdir="target-documents"
                failonerror="true">
            <!--Authentifizierungsoptionen-->
            <usercredentials username="admin" password="admin"/>
            <!--Wahl der Quelldokumente-->
            <fileset dir="source-documents">
                <include name="**/*.png"/>
            </fileset>
            <globmapper from="*.png" to="*.pdf"/>
            <!--Abfolge der Webseriveaufrufe-->
            <group>
                <webpdf:operation>
                    <webpdf:converter pages="1" jpegQuality="100"/>
                </webpdf:operation>
            </group>
        </webpdf>
        <echo>+++ EXECUTION FINISHED +++</echo>
    </target>
</project>

Die build-Datei und das Target executeWebPDFTask sind hiermit ausführungsbereit. Es wird automatisch die nötigen Bibliotheken beziehen, Quell- und Zielordner vorbereiten und automatisiert sämtliche PNG-Dokumente des Quellordners mittels des webPDF Converter Webservice in PDF Dokumente konvertieren und diese im Zielverzeichnis ablegen.

Verkettung von Operationen und Gruppen

Wie bereits erwähnt kann ein group Task mehrere Operationen hintereinander ausführen, wobei er das Ergebnis einer vorhergehenden Operation als Ausgangsdokument der nachfolgenden Operation nutzt.

Hierfür werden in einer group schlicht mehrere operation Elemente hintereinander definiert:

<group>
    <webpdf:operation>...</webpdf:operation>
    <webpdf:operation>...</webpdf:operation>
</group>

Auch das Verketten mehrerer Gruppen ist auf diese Art möglich, wobei die nachfolgende Gruppe das Ergebnis der vorhergehenden als Ausgangsdokument nutzt:

<webpdf>
    <group>...</group>
    <group>...</group>
</webpdf>

Umleitung von Zwischenergebnissen in eine Variable

Um komplexere Operationen umzusetzen, lässt sich das Ergebnis einer Gruppe in eine Variable umleiten, sodass im weiteren Verlauf darauf zugegriffen werden kann. Hierfür lassen sich die erzeugten Ergebnisse in OUTPUT Variablen zur späteren Nutzung hinterlegen. (Die entsprechende temporäre Datei wird in diesem Fall von der Löschung ausgenommen)

Folgendermaßen ließe sich beispielsweise das Ergebnis einer Gruppe in einer Variablen mit der Bezeichnung out hinterlegen:

<group>
    <var name="out" role="OUTPUT"/>
    <webpdf:operation>…</webpdf:operation>
    <webpdf:operation>…</webpdf:operation>
</group>

Der Pfad zum letzten Ergebnis, das in dieser Gruppe erzeugt wurde, wird in einer Variablen mit Namen out hinterlegt. Im weiteren Verlauf kann auf diese Variable wie üblich über ${out} zugegriffen werden.

Das in out hinterlegte Dokument würde auch dann dem Bearbeitungszustand zu diesem Zeitpunkt entsprechen, wenn weitere Gruppen folgen würden, die dieses Dokument als ihr Ausgangsdokument nutzen.

Setzen der Ausgangsdokuments über eine Variable

Üblicherweise verarbeitet der webpdf Task die Dateien eines Filesets oder einer ähnlichen Auswahl. Er setzt hierfür die gewählten Dokumente nacheinander als Ausgangsdokument der ersten Gruppe. Die Gruppe führt Operationen auf Basis dieses Dokuments aus, erzeugt ein Zwischenergebnis und reicht dieses an eine nachfolgende Gruppe als deren Ausgangsdokument weiter und so fort.

Möchten wir, dass eine nachfolgende Gruppe nicht mit dem Ergebnis der vorhergehenden Gruppe weiterarbeitet, so können wir ihr über eine INPUT Variable den Pfad zu einer Datei hinterlegen, die sie stattdessen als Ausgangsdokument nutzen soll:

<group>
    <var name="in" role="INPUT" value="beliebiger Dateipfad"/>
    <webpdf:operation>…</webpdf:operation>
    <webpdf:operation>…</webpdf:operation>
</group>

Hierdurch wird lediglich das Dokument ersetzt, das von der ersten Operation der Gruppe verarbeitet wird, das daraus resultierende Ergebnis und alle folgenden Zwischenergebnisse werden wie üblich an die Nachfolger weiter gereicht.

Nutzung von Input und Output Variablen

Um den Nutzen von Input und Output Variablen zu veranschaulichen, betrachten wir folgendes Beispiel:

<group>
    <var name="out" role="OUTPUT"/>
    <webpdf:operation>
        <webpdf:converter/>
    </webpdf:operation>
</group>
<group>
    <var name="in" role="INPUT" value="beliebiger Dateipfad"/>
    <var name="out2" role="OUTPUT"/>
    <webpdf:operation>
        <webpdf:converter/>
    </webpdf:operation>
</group>
<group>
    <var name="in2" role="INPUT" value="${out}"/>
    <webpdf:operation>
        <webpdf:merge>
            <webpdf:data source="uri" uri="file:///${out2}"/>
        </webpdf:merge>
    </webpdf:operation>
</group>

Die erste Gruppe konvertiert regulär ein vom webpdf Task ermitteltes Dokument mittels des Converter Webservice und erzeugt ein Zwischenergebnis, der Pfad zu diesem Ergebnis wird in der Variablen out hinterlegt.

Die zweite Gruppe würde nun üblicherweise mit dem erstellten Zwischenergebnis weiterarbeiten, allerdings wird ihr stattdessen über die variable in ein Dokument mittels eines festen Dateipfads übergeben. Sie konvertiert dieses Dokument mittels des Converter Webservice und erzeugt ein Zwischenergebnis, dessen Pfad in der Variablen out2 hinterlegt wird.

Die dritte Gruppe schließlich erhält über die Variable in2 das Ergebnis der ersten Gruppe als Ausgangsdokument, die enthaltene Merge Operation erhält das Ergebnis der zweiten Gruppe als data Parameter. Das zweite erzeugte Zwischenergebnis wird also hinten an das erste erzeugte Zwischenergebnis angehängt.

Das Ergebnis der dritten Gruppe schließlich, stellt also das Gesamtergebnis dieser drei Gruppen dar.