Freitag, 13. Februar 2015

Dokumente löschen mit ELOas in ELO Enterprise

Zu meinen Aufgaben gehört die administrative Betreuung eines ELO Enterprise Dokumenten Management Systems.
In diesem System ist eine Workflow Vorlage für den Durchlauf von speziellen Dokumenten konfiguriert.

Der Workflow macht was er soll allerdings tritt hin und wieder das Problem auf, dass ein Dokument gelöscht und der entsprechende Workflow beendet werden soll.
Nach einiger Überlegung lag der Schluss nahe, dieses Szenario in den Workflow einzuarbeiten.

Dabei gibt es nun folgendes Problem: Die Nutzer, die am Workflow beteiligt sind, haben im DMS keine Löschrechte und sollen diese auch nicht erhalten. Damit kann das Löschen des Dokuments nicht direkt in einem Workflow-Knoten erfolgen.

Eine mögliche Lösung ist die Verwendung von ELOas (AS=Automation Service). ELOas ist ein Serverdienst, mit dem zeitgesteuert Aufgaben mit höheren Privilegien ausgeführt werden können.

  1. Der Workflow wird an den entsprechenden Stellen mit weiteren Endknoten ausgestattet, die das zu löschende Dokument in einen dafür vorgesehenen Ordner im Archiv verschieben.
  2. Der Workflow beendet sich
  3. Ein ELOas Ruleset schaut 1 Mal pro Minute in den Löschordner und entfernt dort aufgelaufene Dokumente
Der Weg zum Ziel war etwas steinig.

Um einen ELOas Ruleset zu erstellen verwendet man am Besten den ELO Java Client. Nach der Anmeldung als Administrator navigiert man im Archivbaum zu:

Administration/ELOas base/Rules

In diesem Verzeichnis befindet sich für jede Rule (Aufgabe) eine Textdatei (XML). Über die Postbox und Archivablage kann der Adminstrator einfach eine neue Ruleset dort ablegen (Maske Freie Eingabe).
Für die Löschaufgabe sieht die XML-Datei relativ einfach aus:


<ruleset>
  <base>
    <name>Loeschen</name>
    <search>
      <name>"TREEWALK"</name>
      <value>1742</value>
      <mask>105</mask>
      <max>1</max>
    </search>
    <interval>1M</interval>
  </base>
<rule>
  <name>Loeschen</name>
  <script> 
log.info("############### ObjId: " + EM_ACT_SORD.getId());

if ((EM_TREE_STATE == 1)) {
   ixConnect.ix().deleteSord(1742, EM_ACT_SORD.getId(), LockC.NO, null);
}
</script>
</rule>
<rule>
  <name>Global Error Rule</name>
  <condition>OnError</condition>
  <script></script>
</rule>
</ruleset>



Listing: XML-Datei Ruleset Löschen

Im <base> Teil wird definiert, welche Dokumente das Ruleset verarbeiten soll. Mit der Methode TREEWALK kann ein Archiv-Zweig verarbeitet werden. 1742 ist im Beispiel die ELOID des Ordners, der die zu löschenden Dokument enthält.
Mit <mask> muss eine Verschlagwortungsmaske angegeben werden. Nur Dokumente mit dieser Maske werden behandelt.
Das <interval>1M bedeutet minütliche Ausführung.

Die <rule> gibt an was mit den gefundenen Dokumenten passieren soll. Im Beispiel wird ein <script> eingerichtet welches mit einem Indexserver Aufruf das gefundene Dokument löscht.
Da beim TREEWALK jedes Dokument 2 Mal bearbeitet wird, wird mit 

if ((EM_TREE_STATE == 1))

geprüft ob der letzte Durchlauf erreicht ist.

Nachdem die Ruleset XML-Datei unter

Administration/ELOas base/Rules

im Archiv abgelegt wurde, muss man zum Bearbeiten Auschecken und wieder Einchecken.
Nach dem Einchecken muss ausserdem ein Relaod der Rulesets im ELOas durchgeführt werden. Anderenfalls werden Änderungen am Skript nicht wirksam.
Der Relaod erfolgt über die Webconsole des ELOas. Host und Port entsprechen der Indexserver URL.

http://server:8080/as

Wenn man mit mehreren Mandanten arbeitet muss anstelle von as entsprechend as-Mandant stehen.
Falls der Tomcat nach einem Login fragen sollte findet man diesen im Tomcat Install-Verzeichnis unter conf/tomcat-users.xml.

Wenn die ELOas Console erscheint, sieht man dort eine Liste mit den geladenen Rulesets. Über den Link "Relaod" kann neu geladen werden.

Logfile

Zur Diagnose der ausgeführten Rulesets steht der as-Log im Log Verzeichnis der ELO-Installation zur Verfügung.
Im Skript kann man mit

log.info("Blablub");

Daten in das Log schreiben. log.debug("") hat bei mir keine Ausgabe erzeugt. Vermutlich muss dazu ein Debugschalter aktiviert werden.


Dokumentation

ELO stellt im SupportWeb detaillierte technische Dokumentationen zur Verfügung. Zum ELOas gibt es dort ein Handbuch.



Debugging

In der Dokumentation wird auch die Möglichkeit eines echten Debuggings beschrieben.
Bei komplexeren Aufgaben sollte man davon in jedem Fall Gebrauch machen. Für diese erste Aufgabe habe ich es nicht genutzt.


Mittwoch, 11. Februar 2015

Apache PDFBox - Probleme mit PDPageContentStream

Zur Bearbeitung von PDF-Dokumenten in einem Java-Projekt nutze ich Apache PDFBox. Das klappt recht gut, allerdings stößt man immer wieder auf Probleme, die aus der Verschiedenheit der PDF-Quellen resultieren.

Eine große Verbesserung brachte der Wechsel zur Version 2.0. Diese ist noch in Entwicklung aber hat zumindest für mich einige Probleme des 1.8er Releases gelöst.

Zwei Dinge blieben aber:

  1. Einfügen von Bildern in eine vorhandene Seite (PDImageXObject): Bei wenigen PDF-Dateien waren die Bilder einfach nicht sichtbar. Keine Fehlermeldung. Mit einem Texteditor konnte ich nachvollziehen, dass die Bilder in das PDF-Dokument eingefügt wurden.
  2. Eingefügter Text wurde teilweise in verschiedenen Breiten dargestellt drawString() bzw. showText(). Eine Prüfung mit Adobe Acrobat brachte ans Licht, dass die Textobjekte einen Faktor für die horizontale Verzerrung eingestellt hatten. Dieser war häufig entweder <1 (gestaucht) oder > 1 (gestreckt).

Durch Zufall bin ich dann auf einen wenig genannten Konstruktor der Klasse PDPageContentStream gestossen.

PDPageContentStream(PDDocument document, PDPage sourcePage,
     boolean appendContent, boolean compress,
     boolean resetContext)


Entscheidend ist der letzte Parameter resetContext. Dieser wird von den anderen Konstruktoren mit false belegt.

Durch Setzen des Parameters auf true konnte ich beide genannten Probleme lösen.

Modeless (non modal) SWT Dialog


Für ein Projekt nutze ich einen SWT TitleAreaDialog. Der Nutzer kann darin die Verschlagwortung eines Dokuments vornehmen.

Standardmäßig ist der Dialog MODAL, d.h. das öffnende Anwendungsfenster kann nicht mehr bedient werden. Im konkreten Fall ist dies ungünstig, da die Möglichkeit bestehen soll, in der Dokumentansicht zu scrollen während der Dialog ausgefüllt wird.

Damit das klappt muss der Dialog das Style Bit SWT.MODELESS erhalten und darf gleichzeitig nicht die Bits SWT.APPLICATION_MODAL, SWT.SYSTEM_MODAL oder SWT.PRIMARY_MODAL haben.

Eine Erklärung zu diesen Bits gibt es hier:
http://help.eclipse.org/juno/...%2Feclipse%2Fswt%2Fwidgets%2FShell.html

Da der Dialog irgendwo in der Vererbungshierarchie eines der MODAL-Bits erhält habe ich im Konstruktor meiner Dialog Implementierung die Bits entsprechend angepasst:

 public IndexingDialog(Shell parentShell) {  
   super(parentShell);  
   setShellStyle( (getShellStyle() | SWT.RESIZE | SWT.MODELESS) & 
      (~SWT.APPLICATION_MODAL | SWT.SYSTEM_MODAL | SWT.PRIMARY_MODAL) );   
 }  


getShellStyle() liefert die aktuell gesetzten Bits. Diese werden durch den OR Operator um RESIZE und MODELESS ergänzt. RESIZE erlaubt dem Nutzer, die Größe der Dialog Shell zu verändern.

Um dann die ggf. gesetzten MODAL Bits los zu werden wird das ganze bitweise AND mit der Negation aus dem OR aller MODAL Bits verknüpft.
Der Satz ist nicht wirklich gelungen aber das Prinzip sollte klar sein ;)