RRZE – Projekte & Prozesse (P&P)

Das Blog der RRZE Stabsstelle "Projekte & Prozesse"

Content

Sortierbare Elemente in Tapestry per jQuery UI

Problembeschreibung

 
English Version
Zur Sortierung von Elementen in einem Webfrontend kann man sich verschiedene Realisierungen vorstellen. Beispielsweise könnte man für jedes Element eine Textbox bereitstellen, in denen der Benutzer den Index innerhalb der Sortierreihenfolge definiert. Das ist zwar sehr barrierefrei, aber auch unhandlich, wenn man sich vorstellt, dass in einer bestehenden Sortierung das letzte Element weit nach oben verschoben werden soll, da dann viele Indizes angepasst werden müssen. Eine andere Realisierung wären Links mit denen die Elemente jeweils eine Position nach oben oder unten verschoben werden können. Das erfordert jedoch häufiges Neuladen der Seite und ist für den Benutzer nicht sonderlich ästhetisch anzusehen.

Daher wurde für eine konkrete Realisierung des Problems in FAU.ORG auf die wunderbare Welt der AJAX/Javascript Komponenten von jQuery zurückgegriffen. Konkret auf die Komponenten von jQuery UI. Diese Komponentensammlung umfasst sowohl Interactions (also Elemente wie Draggable, Droppable, Sortable, etc.) als auch Widgets (Datepicker, Progressbar, etc.). Die Sortable-Komponente entsprach genau den Anforderungen des oben beschriebenen Problems.

Integration von jQuery:Sortable in Tapestry

Zunächst müssen die notwendigen Javascript-Bibliotheken eingebunden werden:
[html]<link type=”text/css” href=”${asset:jqueryui/themes/base/jquery.ui.all.css}” rel=”stylesheet” />
<script type=”text/javascript” src=”${asset:scripts/jquery-1.4.1.js}”></script>
<script type=”text/javascript” src=”${asset:jqueryui/ui/jquery.ui.core.js}”></script>
<script type=”text/javascript” src=”${asset:jqueryui/ui/jquery.ui.widget.js}”></script>
<script type=”text/javascript” src=”${asset:jqueryui/ui/jquery.ui.mouse.js}”></script>
<script type=”text/javascript” src=”${asset:jqueryui/ui/jquery.ui.sortable.js}”></script>[/html]
Optional kann man die sortierbaren Elemente (die als unordered List gerendert werden) als Kästen formatieren:
[html]<style type=”text/css”>
#sortable { list-style-type: none; margin: 0; padding: 0; float: left; margin-right: 10px; }
#sortable li { margin: 0 5px 5px 5px; padding: 5px; font-size: 1.0em; width: 350px; }
</style>[/html]
Danach wird die Liste um Sortierfähigkeit erweitert und ein Handler entwickelt, der die Sortierergebnisse speichert:
[javascript]<script type=”text/javascript”>
$(function() {
$(“#sortable”).sortable();
$(“#sortable”).disableSelection();
});

function storeOrder() {
var result = $(‘#sortable’).sortable(‘toArray’);
var context = “”;
for (var id in result) {
if (context == “”) {
context = result[id];
} else {
context = context + “_” + result[id];
}
}
window.location = “/${pageName}” + “.save/” + context;
}
</script>
[/javascript]
Schließlich wird die Liste selbst noch eingebunden und ein Speichernlink bereitgestellt:
[html]<ul id=”sortable”>
<li t:type=”loop” source=”elements” value=”element” id=”${element.id}”>${element.name}</li>
</ul>
<a href=”#” id=”prepare” onClick=”storeOrder()”>${message:save}</a>
<t:actionlink t:id=”save” context=”literal:dummy”></t:actionlink>[/html]
Die einzelnen Listenelemente werden durch invisible Instrumentation der Loop-Komponente von Tapestry erzeugt. Die erste Funktion im Javascript-Block sorgt für die Verschiebbarkeit per Maus der Elemente innerhalb der Liste und verbietet deren Selektierbarkeit.

Beim Klicken auf den HTML-Link wird lediglich die Javascript-Funktion storeOrder() aufgerufen. Diese erzeugt ein Array der IDs der Elemente in ihrer vor dem Klicken aktuellen Reihenfolge. Da diese Liste per ActivationContext an einen Actionhandler auf Tapestry-Serverseite übergeben werden soll, kommaseparierte Liste in diesem Kontext jedoch nicht zugelassen sind, wird die Liste in einen String umgewandelt, in dem die Element-IDs per Unterstrich voneinander getrennt vorkommen. Dies kann auf Serverseite durch ein simples String.split() wieder zerlegt werden. Man beachte, dass dafür ebenfalls ein Actionhandler auf Serverseite bereitgestellt werden muss. Dafür wurde der pseudo-Actionlink erzeugt. Der Redirect der storeOrder()-Funktion ruft den Actionhandler mit dem vorbereiteten ActivationContext schließlich manuell auf.

Demo

Eine Demo der Sortable-Komponente von jQuery UI ist hier zu finden.

Sortable Elements in Tapestry with jQuery UI

Problem description

There are many ways to realize sorting elements in a web frontend. One could provide a textbox for every element, which holds the index within the sorting order. This is barrier free to the fullest, but also very inconvenient. Imagine a ordered list, where the last element should be moved to the very top. With this technique almost all element indexes must be adopted. Another realization would be two links on every element. One to move itself upwards and one downwards. This requires a lot of page reloading and is not really state of the art.

To solve the concrete problem within the FAU.ORG project the wonderful AJAX/Javascript components of jQuery were used. More specific the components of jQuery UI. This collection of components includes Interactions (elements like Draggable, Droppable, Sortable, etc.) and Widgets (Datepicker, Progressbar, etc.). The sortable component matched exactly the requirements of the above mentioned problem.

Integration of jQuery:Sortable in Tapestry

First of all one has to include the required Javascript-libraries:
[html]<link type=”text/css” href=”${asset:jqueryui/themes/base/jquery.ui.all.css}” rel=”stylesheet” />
<script type=”text/javascript” src=”${asset:scripts/jquery-1.4.1.js}”></script>
<script type=”text/javascript” src=”${asset:jqueryui/ui/jquery.ui.core.js}”></script>
<script type=”text/javascript” src=”${asset:jqueryui/ui/jquery.ui.widget.js}”></script>
<script type=”text/javascript” src=”${asset:jqueryui/ui/jquery.ui.mouse.js}”></script>
<script type=”text/javascript” src=”${asset:jqueryui/ui/jquery.ui.sortable.js}”></script>[/html]
The next step comprises optional formatting of the elements (which are rendered as an unordered list):
[html]<style type=”text/css”>
#sortable { list-style-type: none; margin: 0; padding: 0; float: left; margin-right: 10px; }
#sortable li { margin: 0 5px 5px 5px; padding: 5px; font-size: 1.0em; width: 350px; }
</style>[/html]
Now the list is enriched to support sortability and a handler is developed, which stores the order of elements:
[javascript]<script type=”text/javascript”>
$(function() {
$(“#sortable”).sortable();
$(“#sortable”).disableSelection();
});

function storeOrder() {
var result = $(‘#sortable’).sortable(‘toArray’);
var context = “”;
for (var id in result) {
if (context == “”) {
context = result[id];
} else {
context = context + “_” + result[id];
}
}
window.location = “/${pageName}” + “.save/” + context;
}
</script>[/javascript]
Finally the list itself must be included and a link to store the changes provided:
[html]<ul id=”sortable”>
<li t:type=”loop” source=”elements” value=”element” id=”${element.id}”>${element.name}</li>
</ul>
<a href=”#” id=”prepare” onClick=”storeOrder()”>${message:save}</a>
<t:actionlink t:id=”save” context=”literal:dummy”></t:actionlink>[/html]
Every list element is created with invisible instrumentation of the Loop-component of Tapestry. The first function in the Javascript-block enables moving elements by mouse within the list and disables selections.

When clicking the HTML-link the storeOrder() Javascript-function is called. This function creates an array of the element-IDs in the most recent defined order. As the list will be handled over to an ActionHandler-function by ActivationContext on Tapestry server-side and comma-separated lists are forbidden within this context, the array is converted to a single string, where the IDs are separated by underscore. This string can easily be converted to an array again with the  String.split() Java-function.  Be aware, that therefore an ActionHandler has to be provided on server-side. To accomplish this a pseudo ActionLink is created within the Tapestry-Template. The redirect of the storeOrder()-function calls the ActionHandler with the given context manually.

Demo

A demo of the Sortable-component of jQuery UI can be found here.

Umwandeln von SVG-Grafiken in Visio-Dokumente per VBA

English Version
Die RRZE Icons werden ja bekanntlich im “Scalable Vector Graphics”-Format erstellt. Zur Verwendung der Icons in Visio kann dafür eine Stencil-Palette erstellt werden. Dafür müssen jedoch alle SVG-Grafiken in das Visio-Format umgewandelt werden. Dazu habe ich ein Skript in Visual Basic for Applications (VBA) – der Skriptsprache von Microsofts Office Produkten – erstellt, was diesen Prozess automatisiert für eine ganze Sammlung von Icons ausführt.
[vb]’Alle Variablen muessen vor ihrer Verwendung deklariert werden (sonst sucht man sich nen Wolf bei Fehlern)
Option Explicit

Sub Konvertieren()
Dim FSO
Dim SourceFolder
Dim SubFolder
Dim FileItem
Dim newFileName

Set FSO = CreateObject(“scripting.FileSystemObject”)
‘ Hier einfach den Basis-Ordner anpassen
Set SourceFolder = FSO.GetFolder(“E:\SVN\rrze-icon-set\trunk\visio\”)

For Each SubFolder In SourceFolder.SubFolders
‘ .svn-Ordner ignorieren
If (InStr(SubFolder.Path, “.svn”) = 0) Then
For Each FileItem In SubFolder.Files
‘ nur .svg-Dateien betrachten
If (Right(FileItem.Name, 4) = “.svg”) Then
newFileName = Replace(FileItem.Path, “.svg”, “.vdx”)
‘ keine existierenden vdx-Dateien überschreiben
If (Not FSO.FileExists(newFileName)) Then
‘ Neues Dokument beginnen
Application.Documents.AddEx “”, visMSDefault, 0
‘ Icon importieren
Application.ActiveWindow.Page.Import FileItem.Path
‘ Default-Dokument-Eigenschaften setzen
Application.ActiveDocument.Company = “RRZE”
‘ Datei mit gleichem Namen im vdx-Format abspeichern
Application.ActiveDocument.SaveAsEx newFileName, visSaveAsWS + visSaveAsListInMRU
‘ Dokument schließen
Application.ActiveDocument.Close
End If
End If
Next FileItem
End If
Next SubFolder

End Sub
[/vb]
Die Kommentare im Code erläutern die jeweilige Funktion der Zeile. Das Skript kann man einfach in den VBA-Skripteditor in Visio kopieren, den Wert des Basisverzeichnisses anpassen und ausführen (F5). Fertig.

Man könnte das Skript noch derart erweitern, dass es nach dem Basis-Ordner fragt. Dazu einfach hier oder hier nachlesen.

Batchprocessed conversion of svg-graphics to Visio-documents

The RRZE icons are designed in the “Scalable Vector Graphics”-format. For a convenient usage in Visio they can be collected as a stencil-set. Therefore their format has to be converted into the vdx-format. I wrote a script in Visual Basic for Applications (VBA) – the scripting language of Microsofts’ Office products – to convert a complete set of icons within a base folder.
[vb]’Declare all variables before usage to avoid typo errors
Option Explicit

Sub Convert()
Dim FSO
Dim SourceFolder
Dim SubFolder
Dim FileItem
Dim newFileName

Set FSO = CreateObject(“scripting.FileSystemObject”)
‘ The base folder MUST be defined here
Set SourceFolder = FSO.GetFolder(“E:\SVN\rrze-icon-set\trunk\visio\”)

For Each SubFolder In SourceFolder.SubFolders
‘ ignore .svn-folder
If (InStr(SubFolder.Path, “.svn”) = 0) Then
For Each FileItem In SubFolder.Files
‘ process .svg-files only
If (Right(FileItem.Name, 4) = “.svg”) Then
newFileName = Replace(FileItem.Path, “.svg”, “.vdx”)
‘ don’t overwrite existing vdx-files
If (Not FSO.FileExists(newFileName)) Then
‘ open a new document
Application.Documents.AddEx “”, visMSDefault, 0
‘ import icon into new document
Application.ActiveWindow.Page.Import FileItem.Path
‘ set default document properties
Application.ActiveDocument.Company = “RRZE”
‘ save as a file with same name in vdx-format
Application.ActiveDocument.SaveAsEx newFileName, visSaveAsWS + visSaveAsListInMRU
‘ cleanup
Application.ActiveDocument.Close
End If
End If
Next FileItem
End If
Next SubFolder

End Sub
[/vb]
The comments in the code describe the used functions. The script can simply be copied into the VBA-editor in Visio. Remember to set the base-folder correctly. Run the code within the editor (F5). As simple as that.

The script may be enhanced to use a dialog to ask for the base-folder. Simply read here or here about the usage of a FileDialog-Object.

Erneuerungen am RRZE-Icon-Set

English Version

Seit der letzten Auflage wurden zahlreiche neue oder veränderte Icons hinzugefügt. Beispiele dafür sind weitere Icons für die Dienste “mein Campus” oder FAU.ORG. Weiterhin ist eine neue Unterteilung der Icons nötig geworden, um Icons, die so genannte MIME-Types darstellen, einzugliedern. Eine weitere Erneuerung im RRZE-Icon-Set sind detailärmere Versionen mit denen die Icons in den Größen 16×16 und 22×22 erzeugt werden. Somit können auch aus den kleinen Icons die wesentlichen Informationen gelesen werden.

Icon Inspector

Der eigens für das RRZE-Icon-Set entwickelte Icon Inspector hat neue Funktionen erhalten.

Die Icon Gallerie enthällt nun auch eine hochauflösende Vorschau für jedes Icon mittels des populären Lightbox2 Skripts.
Zudem besteht seit neustem auch die Möglichkeit eine vielseitig konfigurierbare PNG Übersichtsgrafik mit allen Icons erstellen zu lassen. So hat man alle Icons auf einen Blick.

Falls mehrere Icons mit dem selben Namen gibt, was meist durch Kopieren oder Verschieben von Icons innerhalb der Ordnerstruktur passiert, wird nun eine entsprechende Warnung erzeugt.

Zum Schutz der Privatsphäre des Icon Entwicklers werden in Anlehnung an Sebastian Pippings svgstrip Script außerdem automatisch einige Attribute aus den SVG Dateien entfernt, die absolute Pfade des lokalen Systems enthalten können. Namentlich handelt es sich dabei um die Attribute sodipodi:absref, sodipodi:docname, sodipodi:docbase und inkscape:export-filename.

Im Bereich automatisierter Metadatengenerierung kann als erste Funktion das Meta-Title Element der SVGs automatisch aus dem Dateinamen generiert und gesetzt werden.
Geplant sind weitere Funktionen, wie z.B. das automatische Einfügen eines konfigurierbaren Linzenzhinweises.

Momentan wird wie auch bei den früheren Versionen lediglich der Einsatz unter Linux empfohlen. Eine lauffähige Windows Variante ist aber in Arbeit und wird in Kürze verfügbar sein.

Update of the RRZE Icon Set

Since the last edition of the RRZE Icon Set many new or modified icons have been added. Some examples are various icons for projects like “mein Campus” or FAU.ORG. Further on a new subdivision has been added to distinguish Icons that show so called MIME types. Another renewal are the less detailed versions with which the sizes 16×16 and 22×22 can be generated so that the important information can also be read out of the small sized Icons.

Icon Inspector

The especially for the RRZE Icon Set developed Icon Inspector got new features.

The Icon Gallery now also contains a high detailed preview for every icon using the popular Lightbox2 script.
Additonally a highly configurable PNG overview image – containing all icons with their title – can be generated. This way all icons can be easily viewed with one look.

Also multiple icons with the same name are now detected and a warning is issued. This often happens after copying or moving icons around within the folder structure.

To shield the icon developer’s privacy some attributes that contain absolute local paths are now beeing removed from the SVGs. This part was inspired by Sebastian Pippings svgstrip script and removes the attributes sodipodi:absref, sodipodi:docname, sodipodi:docbase and inkscape:export-filename

As the first function in the field of automated metadata generation the SVG title tag can now be automatically generated from the icon’s filename.
Others are planned, e.g. the automatic insertion of a configurable licensing notice in every SVG file.

At the moment the Icon Inspector is only recomended for use under Linux. But a working Windows version is under construction and will be available soon.

Queries über mehrere Datenbanken in PostgreSQL

English Version

Einleitung

Manchmal muss man Daten aus mehreren Datenbanken miteinander vergleichen, importieren oder aktualisieren. Wenn nicht gerade umständlich ein Programm mit mehreren Datenquellen geschrieben werden soll, bleiben einem nur die Tools der Datenbank selbst. Im Fall von PostgreSQL sind das das Kommandozeilen-Interface psql oder die GUI pgAdmin. Beide sind jedoch nicht in der Lage Abfragen über mehrere Datenbanken abzusetzen. Das liegt schlicht daran, dass beim Verbinden zu einer Datenbank dessen spezifischen Systemkataloge geladen werden und Postgres anscheinend nicht in der Lage ist mehrere dieser Art gleichzeitig zu verwalten. Es gibt allerdings einen Ausweg: dblink. Dabei handelt es sich um eine SQL-Bilbiothek, die mit Postgres ausgeliefert wird und per Datenbank installiert werden kann. Mit Hilfe dieser Bibliothek ist es möglich, Daten aus einer anderen Datenbank abzufragen und andere SQL-Statements zu dieser abzusetzen.

Installation

Die Installation von dblink ist einfach: die Bibliothek liegt im contrib-Ordner der PostgreSQL Installation und wird so in eine Datenbank installiert:

psql -U postgres -d -f `pg_config --sharedir`/contrib/dblink.sql

Das Installieren unter dem Benutzer postgres ist empfehlenswert, da hierbei alle Berechtigungen für etwaige zusätzliche Installationen vorhanden sind. Durch `pg_config --sharedir` findet die Shell das Share-Verzeichnis, in dem der contrib-Ordner liegt. Man sollte sich nur immer im Hinterkopf behalten, dass die Bibliotheken des contrib-Ordners per Datenbank installiert werden (und damit auch Teil eines vollständigen dump sind).

Verwendung

Für Abfragen aus anderen Datenbank muss die dblink-Funktion verwendet werden. Diese wird einfach in der FROM-Clause verwendet:

Select * From dblink('dbname=fauorgdb', 'select id, fauorgpath from orgunit') as t1(id bigint, fauorgpath text);
-- Beispiel auf anderer Postgres Instanz:
Select * From dblink('hostaddr=dbsrv42 dbname=fauorgdb user=fauorg password=drowssap', 'select id, fauorgpath from orgunit') as t1(id bigint, fauorgpath text);

Der erste Parameter der dblink-Funktion definiert die Datenbankverbindung (in diesem Fall lediglich den Datenbanknamen), der zweite Parameter enthält die Anfrage. Der Alias-Teil der FROM-Clause t1(id bigint, fauorgpath text) muss leider verwendet werden, weil Postgres das Schema der abgefragten Daten nicht kennt und sonst schimpft. Eine as-Deklaration ist zwar SQL-Standard, jedoch ist die Definition der Feldtypen eine Postgres-Erweiterung. Da die Verwendung von Abfragen auf einer anderen Datenbank jedoch nicht zur alltäglichen Arbeit gehört, empfiehlt sich die Definition von Views:

create or replace view provisionierte_daten as
select * from dblink('dbname=fauorgdb', 'select id from orgunit') as t1(id bigint);

Die View wird einmal definiert und fertig. Damit lassen sich dann Abfragen der folgenden Art definieren:

select * from provisionierte_daten
except
select "FAUORGId" from "IMP_FAUORG";

Das ist sehr nützlich, um zu prüfen, ob zwei Datenbanken den gleichen Datenbestand haben.

Ultraschnieker Anwendungsfall: selektives Replizieren ODER ‘PostgrESB’ (FT)

Die Kombination aus sehr mächtigem Regelsystem und der Fähigkeit auf entfernten Datenbanken DML-Statements abzusetzen, ermöglicht (selektives) Replizieren von Daten. Hierbei geht es darum eine gesamte Datenbank (oder Teile davon) auf eine andere Datenbank zu replizieren. Alles was man dafür tun muss, ist

  1. das gesamte oder partielle Schema der primären Datenbank auf einer sekundären Datenbank zu installieren
  2. für alle Tabllen und DML-Operationen (INSERT, UPDATE, DELETE) eine Regel wie folgt zu erstellen:
    CREATE OR REPLACE RULE replic_insert AS
      ON INSERT TO  DO 
        SELECT dblink_exec(
          'dbname=test', 
          'insert into  (id, name) values (' || quote_literal(new.id) || ',' || quote_literal(new.name) || ');
        );
    

Das Beispiel funktioniert für eine Tabelle mit den Feldern id und name. Leider muss das Statement recht kompliziert aufgebaut werden, da die sekundäre Tabelle mit den Pseudonamen NEW und OLD nichts anfangen kann. Wird die Regel darüberhinaus mit einer WHERE-Bedingung definiert, lässt sich die Replikation selektiv einschränken. Des Weiteren muss das Schema nicht notwendigerweise gleich sein, da auch heterogene Datenbanken mit Daten versorgt werden können – vorausgesetzt man kennt das Schema und kann die Regel dementsprechend definieren. Anders ausgedrückt ist also nicht nur die Replikation einer Datenbank möglich, sondern vielmehr die Provisionierung eines Teils des Datenbestands in eine andere PostgreSQL Instanz (um den Kreis zum Titel dieses Abschnitts abzuschließen).

Probleme

Probleme bei der Verwendung traten bei mir lediglich mit Passwörtern auf. Die ‘Fremddatenbank’ benötigt ja ebenfalls Authentifizierung. In meinen Tests wurden lediglich Datenbanken auf derselben lokalen Postgres-Instanz abgefragt und ich habe den lokalen Zugriff in der pg_hba.conf auf trust gesetzt:

# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD
host    all         all         127.0.0.1/32          trust

Eine andere Möglichkeit besteht in der Verwendung der Passwortdatei.

Links

Querying multiple databases in PostgreSQL

Introduction

It is sometimes necessary to compare, import or update data from several databases. Unless you want to write a cumbersome program with several data sources, you are stuck with the database tools themselves. In PostgreSQL’s case, that is the command line interface psql or the GUI pgAdmin. Both of them are unable to process queries for several databases at once. The reason for this is simply that, upon connection to a database, its specific system catalogues are loaded, and Postgres seems unable to manage several of these at once. There is however, a way around this: dblink. This is an SQL library shipped with Postgres that can be installed via database. With this library, it is possible to query data from other databases and make SQL statements for these.

Installation

Installing dblink is easy: The library can be found in the PostgreSQL installation’s contrib folder. You can install it like this:

psql -U postgres -d -f `pg_config --sharedir`/contrib/dblink.sql

It is advisable to install as user postgres, as that gives you all the permissions necessary for possible additional installations. With `pg_config --sharedir`, the Shell finds the share directory that contains the contrib folder. Just keep in mind that the libraries within the contrib folder are installed via database (and are thus part of a complete dump).

Usage

For queries from other databases, you have to use the dblink function. You can use it with a simple FROM clause:

Select * From dblink('dbname=fauorgdb', 'select id, fauorgpath from orgunit') as t1(id bigint, fauorgpath text);
-- Example from another Postgres Instance:
Select * From dblink('hostaddr=dbsrv42 dbname=fauorgdb user=fauorg password=drowssap', 'select id, fauorgpath from orgunit') as t1(id bigint, fauorgpath text);

The dblink functions’s first parameter defines the database connection (in this case, the database name). The second parameter contains the query. The FROM clause’s alias part t1(id bigint, fauorgpath text) must be used because Postgres doesn’t know the queried data’s schema and starts whining otherwise. Although an as declaration would be SQL standard, definition of field types is part of the Postgres expansion. Since the use of queries in another database is probably not part of your everyday work, it is advisable to define Views:

create or replace view provisionierte_daten as
select * from dblink('dbname=fauorgdb', 'select id from orgunit') as t1(id bigint);

You only have to define the View once, and you are done. With this you can then use queries of the following kind:

select * from provisionierte_daten
except
select "FAUORGId" from "IMP_FAUORG";

This is very useful for checking if two databases have the same dataset.

Application deluxe: selective replicaion OR ‘PostgrESB’ (FT)

The combination of a very powerful set of rules and the possibility to put statements into remote databases, allows the selective replication of data. This means replicating a complete database (or parts thereof) into another database. All you have to do for this is

  1. installing the primary database’s complete or partial schema on the secondary database.
  2. create a rule for all tables and DML operations (INSERT, UPDATE, DELETE) as follows:
    CREATE OR REPLACE RULE replic_insert AS
      ON INSERT TO  DO 
        SELECT dblink_exec(
          'dbname=test', 
          'insert into  (id, name) values (' || quote_literal(new.id) || ',' || quote_literal(new.name) || ');
        );
    

The example works with a table containing the fields id and name. The statement needs to be rather complicated, as the secondary table cannot interprete the pseudo names NEW and OLD. If the rule is futher defined with a WHERE clause, the replication can be made very selective. In addition, the schemata don’t need to be identical, as you can also provide heterogenical databases with data – if you know the schema and can define your rule accordingly. In other words, this allows not only replication of a database, but also provisioning part of your dataset into another PostgreSQL instance.

Problems

The only problems I found were with passwords. The ‘foreign database’ needs authentication as well. In my tests, I only queried local databases within the same Postgres instance, and set the local access in pg_hba.conf to trust:

# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD
host    all         all         127.0.0.1/32          trust

Another possibility is the use of a password file.

Links

Inkscape und Datenschutz jetzt auch mit dem RRZE Icon Inspector

English Version

An den letzten Artikel anknüpfend kann nun auch der RRZE Icon Inspector die etwas zu gesprächigen XML Tags aus den Inkscape SVGs entfernen.

Nach Vorlage von Sebastian Pippings svgstrip werden bei jedem Lauf die Attribute ‘sodipodi:absref’, ‘sodipodi:docbase’, ‘sodipodi:docname’ im SVG-Tag, sowie das Attribut ‘inkscape:export-filename’ aus allen Tags entfernt.

Datenschutz wieder hergestellt 😉

Inkscape and Data security with the RRZE Icon Inspector

Picking up where the last article left off, the RRZE Icon Inspector is now able to remove the rather “talkative” XML Tags from Inkscape’s SVG files.

Using Sebastian Pippings svgstrip template, attributes ‘sodipodi:absref’, ‘sodipodi:docbase’, ‘sodipodi:docname’ are removed from the SVG-Tag, and attribute ‘inkscape:export-filename’ is removed from all tags..

Welcome back, Data security! 😉

Isoliertes Classloading auf dem JBOSS AS

English Version

Durch Verwendung von Technologien wie Enterprise Java Beans (EJB) und Enterprise Service Bus (ESB) ist es heute ohne Weiteres möglich, lose gekoppelte und feingranular modulare Dienste zu entwerfen, die in Kollaboration eine verteilte Anwendung ausmachen. Einheiten des Entwurfs sind nicht mehr ganze Anwendungen, sondern klar abgegrenzte Dienste, die lokal oder entfernt benutzt werden können. Diese Dienste werden auf ein oder mehreren Applikationsservern (AS) deployed und können dort benutzt werden. Wenn die Dienste selbst auf Funktionen aus Bibliotheken zugreifen müssen, so kann es passieren, dass zwei unterschiedliche Dienste dieselbe Bibliothek in unterschiedlichen Versionen verwenden (müssen). Da beim Standard-Deployment allerdings alles von einem Classloader geladen und instanziert wird, tritt das Problem auf, dass nicht genau vorherzusagen ist, welche der beiden Versionen ein und derselben Bibliothek zuerst geladen wird. Darüberhinaus ist es ja gerade notwendig beide Versionen vorzuhalten, da sie in unterschiedlichen Contexten verwendet werden. Dies ist ohne weiteres Zutun nicht möglich. Daher bietet der JBOSS AS die Möglichkeit, Einheiten des Deployments (EJBs oder ESBs) so zu konfigurieren, dass sie von einem isolierten Classloader geladen werden. Damit ist es möglich die gleiche Bibliothek mehrfach zu laden (insbesondere mit unterschiedlichen Versionen), wenn dies gewünscht wird.

Eine Beispielkonfiguration für ESBs ist im Folgenden dargestellt:

[deployment.xml]
<jbossesb-deployment>
	<loader-repository>
		fauorg.esb.loader:loader=simple-scoped
		<loader-repository-config>java2ParentDelegaton=false</loader-repository-config>
	</loader-repository>
</jbossesb-deployment>

Die Datei sollte deployment.xml heißen und unter src/main/resources/META-INF abgelegt werden. Sie sorgt dafür, dass Klassen in folgender Reihenfolge geladen werden:

  1. /lib/ (aus dem verpackten ESBs)
  2. server/default/lib/

Dabei werden also lediglich Klassen aus dem server/default/lib/ Verzeichnis geladen, die nicht mit verpackt wurden. Der Name des JMX Classloader Objekts ist im Beispiel fauorg.esb.loader und sollte vom Entwickler festgelegt werden. Damit lassen sich auch mehrere Einheiten des Deployments in einem Classloader zusammenfassen.

Nähere Informationen hierzu finden sich hier. Eine Zusammenstellung von UseCases zum Thema isoliertes Classloading auf dem JBOSS AS gibts hier. Zum Aktivieren eines Loggers für den Classloader verfolgt man am besten diese Anleitung.

Isolated loading of classes on JBOSS AS

Using techology like Enterprise Java Beans (EJB) and Enterprise Service Bus (ESB), it is easily possible to design granular, losely connected modular services. In collaboration, these create distributed applications. Design units are no longer complete applications, but clearly separated services that can be used locally or remotely. These services are deployed on one ore more application servers (AS), and can be used there. If the services themselves need to access libraries, it is possible for two different services to use the same library in different versions. Since in standard deployment, everything is loaded and instanced by a classloader, the problem can occur that it becomes impossible to predict which library will be loaded first. It is furthermore necessary to keep both versions available, since they are used in different contexts. Without additional information, that is not possible. That is why JBOSS AS offers the possibility of configuring deployment units (EJBs or ESBs) in such a way that they are loaded by an isolated classloader. That makes it possible to load the same library multiple times (especially in different versions) if that is necessary.

Here is an exemplary configuration for ESBs:

[deployment.xml]
<jbossesb-deployment>
	<loader-repository>
		fauorg.esb.loader:loader=simple-scoped
		<loader-repository-config>java2ParentDelegaton=false</loader-repository-config>
	</loader-repository>
</jbossesb-deployment>

The file should be named deployment.xml and put in src/main/resources/META-INF. It ensures that classes are loaded in the following order:

  1. /lib/ (from the packaged ESBs)
  2. server/default/lib/

That means that only classes from the directory server/default/lib/ that weren’t packaged are loaded. The name of the JMX Classloader Object can be found in example fauorg.esb.loader and should be defined by the developer. This allows for several deployment units to be combined into one classloader

You can find further information here. A summary of UseCases regarding isolated classloading on the JBOSS AS can be found here. To activate logging for the classloader, follow these instructions.

Hibernate und Case-sensitive Tabellen-/Spaltennamen

English Version

Wenn Hibernate so konfiguriert ist, dass es das relationale Schema der Datenbank selbst erzeugt, werden alle Tabellen- und Spaltennamen derart erzeugt, dass sie lediglich aus Kleinbuchstaben bestehen. Das ist meines Erachtens auch sinnvoll, weil durch die Verwendung von Hibernate das zugrundeliegende Datenbankmanagementsystem einfach ausgetauscht werden kann. Einige Datenbanksysteme sind jedoch case-sensitiv und würden bei Verwendung einer ‘beliebigen’ Schreibweise Fehler erzeugen. Verfolgt man daher die Konvention alles klein zu schreiben, entstehen diese Probleme gar nicht. Des Weiteren ist es nicht empfehlenswert Tabellen- oder Spaltennamen zu vergeben, die sich einzig durch ihre Verwendung von Groß- und Kleinbuchstaben unterscheiden. Über die bessere Lesbarkeit von Tabellen- oder Spaltennamen mit gemischter Schreibweise (beispielsweise durch Verwendung von Binnenmajuskeln) lässt sich ohnehin streiten.

Hat sich ein Datenbankadministrator dennoch dafür entschieden Großbuchstaben in Bezeichnern eines relationalen Schemas zu verwenden, oder liegt das Datenbankschema schlicht bereits vor, wenn Klassen auf Relationen gemappt werden, kommt man nicht umher den Namen des Feldes oder der Tabelle explizit zu definieren. Ohne diese Definition würde Hibernate die Namen der Membervariablen und Klassen vollständig klein geschrieben verwenden und Datenbanksysteme, die Groß- und Kleinschreibung unterscheiden, würden Fehler erzeugen. Um den Namen des Bezeichners für die Datenbank zu definieren muss man lediglich den name-Parameter der Annotationen @Table und @Column (beide aus javax.persistence) verwenden und den vergebenen Namen in Backticks (`) setzen:

@Entity
@Table(name="`MyEntity`")
public class MyEntity {

  @Column(name="`StartDatum`")
  protected Date startDatum;

  ...
}

Das Mapping verwendet also eine Tabelle namens MyEntity, in der sich ein Feld namens StartDatum befindet.

Dank gilt Frank Tröger, der diesen Trick gefunden hat. Sollte man bei der Verwendung von Bezeichnern, die gleichzeitig Schlüsselwörter der Sprache SQL sind, Probleme haben, könnte die Verwendung von eckigen Klammern helfen.

Hibernate and case sensitive table and column names

If Hibernate is configured to create the relational database schema itself, all table and column names created will be lower case. I think this is reasonable in most cases, as you can simply switch the underlying database management system when using Hibernate. Several database systems are case sensitive, however, and would generate errors when using an ‘arbitrary’ notation. If you keep to the standard of writing everything lowercase, these problems won’t turn up. It is also not advisable to chose table or column names that only differ in their use of lower or uppercase letters. Whether or not table and column names with mixed notation (e.g. when using Camel Case) are better to read is open to discussion, anyway.

If the database admin decided to use upper case characters in relational schema names, or when the database schema is already existent when classes are mapped to relations, you won’t get around an explicit definition of fields or tables. Without this definition, Hibernate will use lower case for all member variables and classes, causing database system that differentiate between lower and uppercase to generate errors. To create a definition for a designator, simply use the name parameter of annotations @Table and @Column (both from javax.persistence) and put the name in backticks (`):

@Entity
@Table(name="`MyEntity`")
public class MyEntity {

  @Column(name="`StartDatum`")
  protected Date startDatum;

  ...
}

Mapping thus uses a table called MyEntity, with a field called StartDatum.

Thanks go to Frank Tröger, who found this trick. If you have problems using designators that are SQL key words, the use of square brackets might help.

Release 2.1 – Feinschliff

English Version
Nachdem im Januar endlich der Startschuss für das zentrale webbasierte Organisationsmanagement FAU.ORG gefallen ist, waren Änderungen bzw. Ergänzungen notwendig. Diese ergaben sich aus der Nutzung und umfassen vor allem Verbesserungen der Bedienbarkeit der Oberfläche:

  • Relevanzschalter
    Mittels der Relevanzschalter ist es nun möglich zu unterscheiden, ob eine OE Personalstelle oder Kostenstelle ist und ob diese im Gebäudemanagement Raumzuweisungen erhalten darf.
  • Sprung zu OE in Baum
    Da die OE-Struktur der FAU “doch ein paar mehr” Einträge hat, ist es nun möglich direkt zu einer OE-Nummer im Baum zu springen.
  • Wechseln aus OE zurück in Ausgangsposition im Baum
    Bisher musste man sich nach den Anschauen oder Bearbeiten einer OE immer durch den Baum zum Ausgangspunkt hangeln. Nun ist es möglich aus der Anzeige der OE direkt zu deren Eintrag im Baum zu springen.
  • Filtern nach Gültigkeit im Baum
    Der Baum zeigte bisher auch abgelaufene OE. Nun ist es möglich diese explizit auszuschließen bzw. OE, die erst in der Zukunft gültig werden, einzublenden.
  • Änderungshistorie
    Es ist jetzt möglich nachzuvollziehen, was in einem wählbaren Zeitraum im gesamten System, einem Teilbaum oder an einer einzelnen Organisationseinheit verändert wurden.
  • sowie ein paar kleine “Überraschungen” für die geneigten AnwenderInnen

Außerdem wurde die Systemanbindung überarbeitet, so dass nun:

  • die Personalverwaltung
  • das Gebäudemanagement
  • die Finanzverwaltung
  • das Identity Management (IdM) sowie
  • mein campus

mit aktuellen Daten zur Organisationsstruktur laufend versorgt werden.

Die neue Version ist ab sofort online und nutzbar.

Release 2.1 – Time for fine-tuning

After the central webbased organisation management service FAU.ORG finally started in january, changes respectively additions were needed. These developed from the usage and cover especially improvements of the usability of the user interface:

  • a switch for relevance
    with this switch it is possible to distinguiunterscheidensh between an OE as a personnel position or as a financial position and if these positions have rights in assigning rooms in the funterscheidenacility management.
  • A jump to the OE tree
    Because the FAU’s structure has got „some more“ entries it is now possible to jump directly to one specific OE number in the tree.
  • Change from the OE back to the starting position in the tree
    Until now you had to go back the whole tree after reading or changing an OE. Now it is possible to jump directly from the display of the OE back to the its entry in the tree.
  • Filter the tree for validation
    Until now the tree also showed expired OEs. Now it is possible to explicitely exclude the expired OEs or respectively show OEs which become valid in the future.
  • History of changes
    It is now possible to reconstruct what happened in a selectable space of time in the whole system, a branch or a single organisational unit.
  • And also some smaller „surprises“ for the willing users.

Furthermore the system application has been revised so that:

  • the personnel management
  • facility management
  • financial management
  • identity management (IdM)
  • my campus

can be fed continuously with current data from the organisational structure.
The new version is now online and available for use.

JBoss And JBoss ESB Color-coded Logging

Farbcodiertes Logging für JBoss und JBoss ESB

English Version

Sowohl während der Entwicklung als auch in einer Produktivumgebung können nach Prioritäten farbcodierte Logs sehr nützlich sein. Die folgenden Logging Konfiguration werden auf den von PP genutzten JBoss und JBoss ESB Systemen verwendet.

  1. Die Konfiguration des JBoss Loggings ist in der Datei $JBOSS_HOME/server/default/conf/jboss-log4j.xml definiert. Der Standard ConsoleAppender kann durch den ANSIConsoleAppender ersetzt werden. Die Declaration sieht folgendermaßen aus:
  2.    <!--<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">-->
       <appender name="CONSOLE" class="de.rrze.ppsa.log.ANSIConsoleAppender">
          <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
          <param name="Target" value="System.out"/>
          <param name="Threshold" value="INFO"/>
     
          <layout class="org.apache.log4j.PatternLayout">
             <!-- The default pattern: Date Priority [Category] Message\n -->
             <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
          </layout>
       </appender>

    Um ähnliche Farbcodierungen für den server.log zu erhalten, der ein anderes Farbschema benutzt, müssen die folgenden Änderungen vorgenommen werden:

       <!-- A time/date based rolling appender -->
       <appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender">
          <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
          <param name="File" value="${jboss.server.log.dir}/server.log"/>
          <param name="Append" value="false"/>
     
          <!-- Rollover at midnight each day -->
          <param name="DatePattern" value="'.'yyyy-MM-dd"/>
     
          <!-- Rollover at the top of each hour
          <param name="DatePattern" value="'.'yyyy-MM-dd-HH"/>
          -->
     
          <layout class="org.osuosl.logging.ANSIColorLayout">
             <!-- The default pattern: Date Priority [Category] Message\n -->
             <param name="ConversionPattern" value="%d %-5p [%c{1}] %m%n"/>
     
             <!-- The full pattern: Date MS Priority [Category] (Thread:NDC) Message\n
             <param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
              -->
          </layout>
       </appender>
  3. Zuletzt muss ppsa-log4j-color-0.0.1.jar zum JBoss classpath hinzugefügt werden. Dies wird dadurch erreicht, dass man es in die $JBOSS_HOME/server/default/lib kopiert. Die Jar-Datei enthält sowohl den ANSIConsoleAppender als auch die ANSIColorLayout Klassen.
  4. Nicht vergessen, den Server danach neu zu starten.

Die vorgeschlagene Lösung basiert auf dem ANSIColorAppender, geschrieben von Dan Dyer und dem ANSIColorLayout von Peter Krenesky.

During development cycle or in a productive environment color-coded log messages based on their priority can prove pretty useful. The following logging configurations are deployed on the JBoss and JBoss ESB systems used by PP:

  1. The JBoss loggin configuration is defined in the $JBOSS_HOME/server/default/conf/jboss-log4j.xml file. The standard ConsoleAppender can be exchanged with the ANSIConsoleAppender. Declaration change looks like that:
  2.    <!--<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">-->
       <appender name="CONSOLE" class="de.rrze.ppsa.log.ANSIConsoleAppender">
          <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
          <param name="Target" value="System.out"/>
          <param name="Threshold" value="INFO"/>
     
          <layout class="org.apache.log4j.PatternLayout">
             <!-- The default pattern: Date Priority [Category] Message\n -->
             <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
          </layout>
       </appender>

    in order to get similar color-coding(this one uses different color scheme) for the server.log the following changes have to applied:

       <!-- A time/date based rolling appender -->
       <appender name="FILE" class="org.jboss.logging.appender.DailyRollingFileAppender">
          <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
          <param name="File" value="${jboss.server.log.dir}/server.log"/>
          <param name="Append" value="false"/>
     
          <!-- Rollover at midnight each day -->
          <param name="DatePattern" value="'.'yyyy-MM-dd"/>
     
          <!-- Rollover at the top of each hour
          <param name="DatePattern" value="'.'yyyy-MM-dd-HH"/>
          -->
     
          <layout class="org.osuosl.logging.ANSIColorLayout">
             <!-- The default pattern: Date Priority [Category] Message\n -->
             <param name="ConversionPattern" value="%d %-5p [%c{1}] %m%n"/>
     
             <!-- The full pattern: Date MS Priority [Category] (Thread:NDC) Message\n
             <param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
              -->
          </layout>
       </appender>
  3. At last the ppsa-log4j-color-0.0.1.jar has to be added to the JBoss classpath. This can be achieved by copying it in the$JBOSS_HOME/server/default/lib. This jar file contains the ANSIConsoleAppender and the ANSIColorLayout classes.
  4. Do not forget to restart the server.

The proposed solution is based on the ANSIColorAppender written by Dan Dyer and the ANSIColorLayout provided by Peter Krenesky.

Inkscape und Datenschutz

English Version

Dank David Wessel (infeurope S.A.) wurden wir darauf hingewiesen, dass die svg-Dateien durchaus private Informationen enthalten.

Mir ist aufgefallen, dass in den jeweiligen SVG-Versionen der Dateien noch einige Pfadangaben enthalten sind, welche teilweise Rückschlüsse auf den Inhalt ihrer Dateiablage geben können.

Das sieht dann z.B. so aus:

inkscape:export-filename="C:\Users\dieDesignerin\RRZE\berlios_rrze_icons\tango\720x720\actions\add-participant.png"

Nicht schlimm, aber auch nicht schön.

Etwas Suchen via Google brachte mich auf einen Fehlerreport bei Ubuntu Privacy concern with export-filename and sodipodi:absref. Aha – das Problem ist also nicht nur bekannt, sondern es haben noch mehr! Wirklich spannend wird es dann, denn Sebastian Pipping schreibt in Kommentar 7, dass er das Programm “svgstrip” erstellt, um diese Informationen zu entfernen. Also runtergeladen und angewendet. Das Tool hatte noch ein Problem mit UTF-8 Zeichen in den Metadaten, aber Sebastian hat den Fehler binnen 3 Tagen – und wie bei Open Source Software so oft – unentgeldlich behoben. Vielen Dank dafür. Und nun klappt es auch mit den UTF-8 Zeichen.

Also Datenschutz wieder hergestellt. Version der Grafiken committed.

Dumm nur, dass man dies nach jeden erneuten Speichern mit Inkscape wiederholen muss. Es müsste eine Option geben, Inkscape diese Unart abzukonfigurieren. Aber daran arbeite ich noch. Genau wie an einer Anleitung, wie man die Metadaten unter Windows entfernt. Vielleicht?! 😉

Hier kommt erstmal die Schritt-für-Schritt-Anleitung unter Linux.
Voraussetzung ist, dass git, svn und python installiert sind, aber wer sich auf die Befehlszeile traut, bekommt das auch hin. O:-)

  1. Die aktuellste Version von svgstrip via git holen.
    git clone https://github.com/hartwork/svgstrip git/svgstrip
    (übrigens: ein git pull in dem neuen Verzeichnis hält die Version aktuell.)
  2. In das Verzeichnis mit den Icons wechseln – in meinem Fall das RRZE Icon Set.
    cd svn/rrze-icon-set/trunk
  3. Dann möchte ich alle svg-Dateien suchen und durch svgstrip bearbeiten lassen.
    for i in $(find . -name *.svg); do echo $i; ../../svgstrip/svgstrip --in-place $i; done;
  4. und dann das Ganze zurück ins subversion.
    svn ci

Fertig!

Danke an David Wessel und Sebastian Pipping!

 

*Update – 20.07.2015: URL zum git-Repository von svgstrip angepasst*

 

 

Inkscape and privacy

David Wessel (infeurope S.A.) was kind enough to inform us that svg files can, in fact, contain private information.

I noticed that svg versions of files still contain parts of the files’ paths, which allows inference of the original file system.

It looks like this:

inkscape:export-filename="C:\Users\dieDesignerin\RRZE\berlios_rrze_icons\tango\720x720\actions\add-participant.png"

Not too bad, but not very nice, either.

Some searching with Google led me to an error report for Ubuntu: Privacy concern with export-filename and sodipodi:absref. So not only is the problem already known, others are having it as well. Now it’s getting interesting, as Sebastian Pipping writes in commentary 7 that he wrote the program “svgstrip” to get rid of this information. I downloaded the program and ran it. The tool still had a problem with UTF-8 characters in the Metadata, but Sebastian fixed that bug within 3 days. And, like most of the time with Open Source Software, for free.And now, UTF-8 characters are no longer a problem.

Data security is once again intact. New versions of the graphics were committed.

On the down side, this needs to be repeated every time you save a file with Inkscape. There ought to be an option to configure what is saved in svg files. But I’m still working on that. I’m also working on instructions how to remove the metadata under Windows. Maybe?

For now, I give you a step by step instruction for Linux.
You need svn and python installed, but if you are confident to use the command line, you will manage that, too. O:-)

  1. Get an up to date version of svgstrip with git.
    git clone https://github.com/hartwork/svgstrip git/svgstrip
    (by the way: git pull in the new directory keeps the version up to date.)
  2. Change into your icon directory ? in my case that is the RRZE Icon Set.
    cd svn/rrze-icon-set/trunk
  3. Now I would like to search for all svg files and edit them with svgstrip.
    for i in $(find . -name *.svg); do echo $i; ../../svgstrip/svgstrip --in-place $i; done;
  4. and finally, send it all back into the subversion
    svn ci

Finished!

Thanks to David Wessel and Sebastian Pipping!

 

*Update – 20.07.2015: changed URL to the git repository of svgstrip*