Strict Standards: Declaration of Walker_Page::start_lvl() should be compatible with Walker::start_lvl(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_Page::end_lvl() should be compatible with Walker::end_lvl(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_Page::start_el() should be compatible with Walker::start_el(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_Page::end_el() should be compatible with Walker::end_el(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_PageDropdown::start_el() should be compatible with Walker::start_el(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1244

Strict Standards: Declaration of Walker_Category::start_lvl() should be compatible with Walker::start_lvl(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_Category::end_lvl() should be compatible with Walker::end_lvl(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_Category::start_el() should be compatible with Walker::start_el(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_Category::end_el() should be compatible with Walker::end_el(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_CategoryDropdown::start_el() should be compatible with Walker::start_el(&$output) in /www/htdocs/v167612/wplog/wp-includes/classes.php on line 1442

Strict Standards: Redefining already defined constructor for class wpdb in /www/htdocs/v167612/wplog/wp-includes/wp-db.php on line 306

Strict Standards: Redefining already defined constructor for class WP_Object_Cache in /www/htdocs/v167612/wplog/wp-includes/cache.php on line 433
iFool » IT

Archiv

Archiv für die Kategorie ‘IT’

Jetty unter MAC OS X (10.8.2) als Boot-Daemon einrichten

10. November 2012

Ich habe einen Jetty-Server auf unserem Home-Server (MAC MINI) installiert, um darauf ein paar GRAILS-Anwendungen für den Hausgebrauch zu hosten (Kassenbuch, Dokumenten-Archiv etc.). Fraglich ist nun, wie man einen Daemon so einrichten kann, dass der Jetty-Server bei jedem Start des MAC MINI automatisch (und ohne dass sich ein Benutzer dazu anmelden muss) startet.

Zunächst einmal habe ich ein Start-Script (Filename “Users/Shared/jetty/taustart.sh”) geschrieben, dass ich verwende, um den Jetty-Server einfach mit vorher festgelegten Eingenschaften starten zu können:


cd /Users/Shared/jetty
java -Dtau.config.path=/Users/Shared/jetty/tau-config -DSTOP.PORT=8085 -DSTOP.KEY=stopme -jar start.jar

Wie zu erkennen ist befindet sich das Jetty-Home-Verzeichnis in meinem Fall unter “/Users/Shared/jetty”. Außerdem habe ich dem Server mitgeteilt, dass ich ihn bei Bedarf über den STOP.PORT “8085″ mit den STOP,KEY “stopme” stoppen möchte. Das ist nützlich, wenn ich den Server für Wartungsarbeiten beenden muss. Ab jetzt soll er ja schließlich beim Systemstart automatisch gestartet werden.

Der Clou an der Sache besteht nun darin, dem launch-Daemon (”launchd”) mitzuteilen, dass dieses Start-Script beim booten automatisch ausgeführt werden soll. Dazu erstelle ich eine sogenannte “plist” (Filename “/Library/LaunchDaemons/org.aulich.jetty.plist”) wie folgt:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>org.aulich.jetty</string>
    <key>ProgramArguments</key>
      <array>
        <string>/Users/shared/jetty/taustart.sh</string>
      </array>
    <key>Disabled</key>
    <false/>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
  </dict>
</plist>

Jetzt kommt noch ein wichtiger Schritt, den ich zunächst vergessen hatte und mich wunderte, warum meine plist nicht ausgeführt wird: Der Eigentümer der neuen plist sollte “root” sein. Daher verwendete ich das folgende command um den Eigentümer entsprechend auf dem plist-File zu setzen:


sudo chown root /Library/LaunchDaemons/org.aulich.jetty.plist

So, dass ist eigentlich auch schon alles, was geschehen muss, um einen entsprechenden Boot-Daemon einzurichten. Abschließend sei noch angemerkt, dass ich das folgende Script benutze, wenn ich den Jetty-Server zwischendurch mal beenden muss:


cd /Users/Shared/jetty
java -Dtau.config.path=/Users/Shared/jetty/tau-config -DSTOP.PORT=8085 -DSTOP.KEY=stopme -jar start.jar --stop

Allgemein, IT, Software ,

ECM-System für den Hausgebrauch

18. Januar 2012

ECM (Enterprise-Conten-Management) ist zurzeit einer der am schnellsten wachsenden IT-Bereiche. Klassische Archivierung “meets” Web-Content-Management gepaart mit Neben-Disziplinen wie Social-Network, Workflow-Management und dergleichen mehr.

Die Software-Lösungen für diesen Bereich sind bereits vielfältig und einige Dinge gibt es auch unter GNU-Lizenz.

Das Thema interessiert mich schon eine ganze weile und ich möchte mich an einer Low-Cost-Implementierung für den privaten Anwendungsbereich versuchen. Als ECM-System habe ich mir jetzt Alfresco vorgenommen, ein bereits in der vierten Generation aufgelegtes und in der Community-Version frei verfügbares ECM für verschiedene Betriebssysteme.

Als Hardware habe ich mir den hier noch aus früheren Experimenten vorhandenen Zotac Mag-Mini geschnappt und ein 32-Bit-Ubuntu Linux-System installiert, da der Zotac kein 64-Bit System zulässt. Leider gibt es für 32-Bit keinen All-In-One-Installer von Alfresco. Das bedeutete, ich musste alle “Zutaten” (wie z.B. MySQL, Tomcat, PDFToSwf etc) zu Fuß installieren. Zum Glück gab es für diesen Zweck einen schönen Blog, den ich in großen Teilen so wie hier verlinkt nachvollziehen konnte.

Anschließend noch ein Startscript für Alfresco in “/etc/init.d”. Jetzt kann die praktische Arbeit beginnen …

Die Vision ist primär die bessere Abwicklung der häuslichen Papierflut: Belege, die sich sonst wochenlang bis sich mal wieder jemand erbarmt in Sammelkästen türmen sollen künftig zeitnah eingescannt und in das ECM verschoben werden. Die verhasste Ablage der Originale erfolgt dann nur noch chronologisch in herkömmlichen Aktenordnern. Im ECM werden die Belege kategorisiert und zusätzlich Volltext-Indexiert. Damit sollte dann zukünftig die Recherche entsprechend leichter fallen. Sollte man mal für irgendwelche Zwecke den Original-Beleg benötigen kann man diesen über die rein chronologische Ablage im Aktenordner leicht finden.

Eine entscheidende Rolle in der Bewertung der Praxistauglichkeit der Lösung spielt für mich u.A. ein ergonomischer Scanningprozess mit OCR und PDF-Output. Hier habe ich mich für eine Vor-Vor-Version von ABBY-Finereader (Version 9) entschieden, die für “Nüsse” zu haben war. Zusammen mit einem im Büro verfügbaren PANASONIC-Dokumentenscannersollte die Digitalisierung der Papierbelege auch bei größerem Volumen gut gelingen.

Mal sehen, wie sich die Sache entwickelt…

IT, Software

Reguläre Ausdrücke in Java: Extrem nützlich (Java-Regex)

11. November 2011

Ich hatte neulich in einem Projekt zur automatischen Rechnungserkennung (OCR) die Anforderung, dass Texte (Artikelnummern) in Abhängigkeit vom Lieferanten nach Musterzeichenfolgen durchsucht werden sollten und dann mit den erkannten Mustern verschiedene Dinge passieren sollten: Zeichen(ketten) entfernen, abändern oder hinzufügen. Das ganze sollte über ein Benutzerinterface konfigurierter und maximal variabel sein.

Die einfachste und wirklich sehr elegante Lösung bestand in der Schaffung einer entsprechenden Tabelle mit den Stammdaten:

  • Lieferantennummer
  • Artikelnummer
  • Muster-Zeichenfolge
  • Erstetzungszeichenfolge

Anschließend habe ich dann einen kleinen Eingriff nach der OCR-Erkennung mit den zu verarbeitenden Zeichenketten vorgenommen. Der Programmieraufwand war an dieser Stelle unter Verwendung der Regulären Ausdrücke in Java (Regex) minimal.

Hier dazu ein Codebeispiel:


import java.util.regex.*;
public class RegexTester {
  public static void main(String args[]) {
    String sourceString = "12345X67890A12XB123X12";
    String patternString = "([0-9])([0-9])([0-9])X";
    String replacementString = "$2$3X";
    Matcher matcher = Pattern.compile(patternString).matcher(sourceString);
    StringBuffer targetString = new StringBuffer();
    while (matcher.find())
      matcher.appendReplacement(targetString, replacementString);
    matcher.appendTail(targetString);
    System.out.println(targetString);
  }
}

In diesem kleinen Beispiel wird im Quellstring “12345X67890A12XB123X12″ nach denjenigen Stellen gesucht, in denen ein X auf 3 Ziffern folgt. Dieses Suchmuster wird dabei durch diesen Regulären Ausdruck definiert: “([0-9])([0-9])([0-9])X”. Wenn so eine Stelle gefunden wird soll die erste der 3 Ziffern eliminiert werden. Die beiden Folgeziffern und das X sollen hingegen im Ergebnis erhalten bleiben. Diese Vorschrift wird durch diesen Regulären Ausdruck definiert: “$2$3X”.

Die kleine Routine gibt dann das Ergebnis folgerichtig in Zeile 12 aus: “1245X67890A12XB23X12″

Ich bin begeistert, wie leistungsfähig die Regulären Ausdrücke sind und wie leicht die Implementierung in Java zu machen ist.

Allgemein, IT, Software

Mit Excel und jQuery Mobile ein Fußballteam mit Onlineinformationen unterstützen…

1. Oktober 2011

Die Aufgabenstellung ergab sich aus meiner Tätigkeit als Betreuer einer B-Jugend Fußballmannschaft: Im Laufe der Saison gibt es immer eine Menge Informationen, die zur Koordination von Terminen erforderlich sind: Der Spielplan bestimmt die Spieltage und Spielorte. Fahrten müssen organisiert und abgestimmt werden. Die Spieler verfügen i.d.R. noch nicht über einen eigenen Führerschein und müssen daher Verwandte und Freunde zur Unterstützung mit einbeziehen. Zu allem Überfluss ändern sich dann auch noch Termine oder eingeplante Fahrer fallen kurzfristig aus bzw. Fahrdienste werden getauscht. Das über gedruckte Dokumente aktuell zuhalten bedeutet bei einem 22-Mann-Kader einen hohen Aufwand und ständig geistern Dokumente mit veralteten Informationen herum.

SV20 Webapp der B1-JugendMeine Lösung des Problems besteht hier in der Bereitstellung der Informationen im Internet: Ein paar html-Dateien ergänzt um das JS-Framework jQuery Mobile und relativ wenig individuellen Java-Script-Code bilden den Rahmen einer Webanwendung für mobile Endgeräte. Die Saisondaten werden auf verschiedenen Registern einer Excel-Datei gepflegt. Bei jedem Update wird das Excel-File als XML gespeichert und auf den Webserver geladen.

Innerhalb der Webapp werden die Inhalte mittels AJAX dann aus dem XML-File dynamisch geladen und mit jQuery Mobile aufbereitet. Das geht sehr einfach und sieht auch noch elegant aus.

Eine Einschränkung: Der MS Internetexplorer hat gewisse Schwierigkeiten mit jQuery Mobile (zumindest mit der Art, wie ich es einsetze). Deshalb gilt bei meiner kleinen Webapp: “IE-User müssen leider draußen bleiben ;-)”. Aber wie gesagt: Es ist im Grunde auch eine Wabapp für mobile Devices und deren Browser sollten keine Probleme haben.

Links:

jQuery Mobile, Webapp der B1-Jungend des SV20 Brilon

Allgemein, Software

HSQLDB nicht als “inMemory-DB” nutzen

16. Dezember 2009

Auch bei der Entwicklung einer Anwendung und den damit verbundenen Tests kann es recht lästig sein, immer wieder “zu Fuß” Testdaten eingeben zu müssen. Die von GRAILS automatisch verwendete HSQLDB ist in der Data-Source als inMemory-DB konfiguriert und daher gehen alle erfassten Daten bei jeder Beendigung der Anwendung verloren.

Zwar kann man durch entsprechende Einlassungen im Bootstrap auch Testdaten “beim Hochfahren” generierern, aber das ist für flexible Tests auch nicht so prickelnd, zumal die Erfassung über Programmierung auch Mühen bedeutet.

Eine gute Alternative bietet die Möglichkeit, einfach die HSQLDB-Datasource anzupassen:


 development {
  dataSource {
   dbCreate = "update" // one of 'create', 'create-drop','update'
   url = "jdbc:hsqldb:file:/temp/test/mydb;shutdown=true"
  }
 }

In diesem Beispiel auf einem PC mit Windows 7 wird beim ersten Start ein Verzeichnis C:\temp\test mit folgenden Files erstellt: mydb.lck, mydb.log, mydb.script und mydb.properties.  In den Textdateien mydb.script und mydb.log werden die Tabellendefinitionen und die Daten in lesbarer Form gespeichert. Beim Start der Anwendung wird dann jeweils aus diesen Textdateien wieder eine schnelle “inMemory-DB” aufgebaut. Während die Anwendung läuft werden DB-Änderungen in der *.log-Datei protokolliert, sodass die Daten auch bei einem Crash der Anwendung nicht verloren gehen können.

Die Verwendung von HSQLDB in Verbindung mit Textdeateien zur Speicherung der Daten ist eine bequeme und sofort Verfügbare Alternative für jeden GRAILS-Entwickler. Außerdem kann es auch eine Alternative für den Livebetrieb in Anwendungen mit kleinem Datenbestand sein (bei wenigen Hundert Datensätze etwa).

Allgemein, Groovy & Grails

GRAILS: Cursor beim Seitenaufbau automatisch in ein bestimmtes Feld setzen

9. März 2009

Die Aufgabenstellung ist eigentlich trivial: Im Body-Tag der GSP-Seite kann man das im OnLoad-Event sehr einfach vorsehen:


<body OnLoad="document.myform.startnummer.focus(); document.myform.startnummer.select();">

In diesem Beispiel wird bei einer create.gsp-Seite der Focus auf das Feld “startnummer” im Formular “myform” gesetzt und der Inhalt des Feldes gleichzeitig markiert. Dummerweise funktioniert das aber nicht so ohne weiteres.

Wenn man sich den Sourcecode der fertig gerenderten Seite ansieht erkennt man ein leeres <body>-Tag! Das liegt daran, dass bestimmte Standards durch das Layout der Anwendung vorgegeben werden. Ein OnLoad-Event ist zunächst nicht vorgesehen. Man kann es aber sehr einfach durch die folgende Ergänzung der Seite /views/layouts/main.gsp gewissermaßen “freischalten”:


   <body onload="${pageProperty(name:'body.onload')}">

Groovy & Grails

GRAILS quickstart mit MySQL

24. Februar 2009

mysql_logoIch dachte mir, es sei ganz nützlich immer ein Datenbanksystem auf dem Notebook zu haben und installierte mir deshalb schnell mal MySQL. Das war mit dem MSI-Installer für Windows auch garkein Problem: Einfach die Standardversion (derzeit MySQL Server 5.1) ausgewählt und schon war die Basis fix und fertig eingerichtet.

Jetzt galt es nurnoch, eine Datenbank mit gültigem User einzurichten und ein paar Handgriffe im Setup der GRAILS-Anwendung zu unternehmen, die mit MySQL zusammenarbeiten sollte.

Den Job mit der Datenbankeinrichtung hat mir ein kleines Script abgenommen (Dateiname C:\temp\create_rc.sql):


DROP DATABASE RC;
CREATE DATABASE RC;
USE RC;
DROP USER 'rcuser'@'localhost';
CREATE USER 'rcuser'@'localhost';
GRANT ALL PRIVILEGES ON RC.* TO 'rcuser'@'localhost';

Mehr…

Groovy & Grails ,

Mobiler Mailaccount - Komfortabel und sicher

27. Januar 2009

thunderbirdNachdem der Heim-PC im letzten Sommer aus dem Wohnzimmer verschwand und sich die PS3 mit einem Yellow-Dog Linux als doch eher ungeeignet zur Verwaltung eines Emailaccounts herausstellte habe ich meine Post einfach auf dem Server des Hosters belassen und mich eines Webmail-Zugangs bedient.

Das ist auf die Dauer ein bischen unbequem und unsicher. Hier nur einige der vielen Gründe, die oft gegen einen Webmail-Account sprechen: Spartanische Funktionen, fehlende Rechtschreibprüfung, kein Offlinezugriff, keine bzw. schlechte Textformatierung, kein Schutz vor Verlust und Spam…

Einen “privaten” Mailclient fest auf dem Notebook meiner Frau bzw. auf dem von mir beruflich genutzten Notebook zu installieren kam nicht in Frage. Mehr…

Software

Wie werde ich die ID-Spalten los? Arbeiten mit Templates

15. Januar 2009

GRAILS macht eigentlich automatisch schon sehr schöne Listen aber “per default” werden dabei leider alle Attribute berücksichtigt. Das führt dann dazu, dass man die unwichtigen ID-Felder zur scheinbar wichtigsten Spalte werden: Sie stehen an erster Stelle und werden dann auch noch mit der “show”-Aktion der zugehörigen Domänenklasse verlinkt.

listwithoutid_fieldSo wie links im Bild sieht es schon besser aus: Das ID Feld wird unterdrückt und statt dessen das erste (kennzeichnende) Feld gesetzt und verlinkt.

Jetzt könnte man das für jede Domainklasse nach der Generierung der Ansichten (gsp-Views) anpassen, aber das macht keinen richtigen Spaß, denn

    1. Wäre das eine relativ stupide Arbeit, die man für jede einzelne Domainklasse durchführen müsste
    2. Würde das ganze nach dem nächsten Generieren wiederholt werden müssen

Die Bessere Alternative ist hier die Arbeit mit den Templates, um das GRAILS-Verhalten nachhaltig zu ändern

Mehr…

Groovy & Grails, IT

Validierung der Benutzereingaben innerhalb der Domainklasse

14. Januar 2009

validierung_messagesDomainklassen bestimmen hauptsächlich die Eigenschaften der Businessobjekte und die Beziehungen dieser Objekte untereinander. Zu den Eigenschaften gehört die Anzahl, Art und Ausprägung der einzelnen Attribute.

Die Art und Anzahl der Attribute wird durch Deklaration einzelner Objekte und einfacher Datentypen im Kopf der Klasse vorgenommen. Wie kann der Entwickler dann Einfluss auf die gültigkeit der Benutzereingaben nehmen? Hier geht es um Validierung…

In der Abbildung wird ein “Create-Dialog” für eine Domainklasse “Archiv” gezeigt, die 2 Attribute enthält: Name des Archivs und Beschreibung.  Der Benutzer hat mit seinen Eingaben gegen 2 Validierungsregeln verstoßen und ich möchte kurz einmal zeigen, wie soetwas funktioniert.

Mehr…

Allgemein, Groovy & Grails