PDFBox 0.7.3

23. August 2007 von Ralph Bergmann in Allgemein
Schlagwörter:

Nicht wenige IT-Systeme bieten als Schnittstelle einen PDF-Export an. Ein Problem hat man aber dann, wenn man die Informationen in diesen Dokumenten wieder in eine andere Datenbank überführen will. Eine Lösung dafür ist die PDFBox, welche aktuell auf Sourceforge gehostet wird.

Die PDFBox beinhaltet in der aktuellen Version 0.7.3:

  • PDF to Text
  • PDF to Image
  • Text to PDF
  • Image to PDF
  • Encrypt / decrypt PDF
  • Alle Funktionen zusätzlich als Kommandozeilen-Werkzeuge

  • Kommentare deaktiviert

Ort des nächsten Java-User-Group-Treffens

23. August 2007 von Jan Lolling in Treffen
Schlagwörter: , ,

jug-logo.png Das nächste Treffen findet am 31.08.2007 um 18:00 statt. Als Ort nehmen wir das Restaurant ZOE in der Mitte Berlins (Rochstrasse 1) mit WLAN-Zugang.
Es ist ein Tisch reserviert auf den Namen Lolling.

Oracle sagt: “t2cGetCharSet”

23. August 2007 von Ralph Bergmann in Java

otn_logo_small.gifOracle-Fehlermeldungen (ORA-XXXX) waren schon immer etwas eigenwillig. Neu für mich war aber die Fehlermeldung “t2cGetCharSet”. Was will mir Oracle damit sagen? Nun ganz einfach, ich habe eine veraltete Version des JDBC-Treibers im Einsatz. Nach einem Upgrade von 10g Release 1 auf 10g Release 2 müssen die ojdbc14.jar, ojdbc14_g.jar und ojdbc14dms.jar ausgetauscht werden. Hm … ein wenig erinnert mich das schon die MS-DLL-Hölle. :|

Java-Anwendung erstellen für Mac OS X

22. August 2007 von Jan Lolling in Java, Java Code Beispiele
Schlagwörter: , , ,

Wer eine Mac hat will natürlich seine Java-Anwendung auch mal echt im Dock sehen oder eine sinnvolle Dateiverknüpfung nutzen usw.
Das alles ist sehr einfach machbar.
Also was habe ich hier nun vor:
Ich werde euch an hand einer realen Anwendung zeigen wie man die Apple-Application-Events auswertet und wie man eine echte Mac-Anwendung zusammenbaut mit ant.
Meine Anwendung ist ein SQL-Client der speziell für die Entwicklung von Java-Anwendungen in Verbindung mit SQL entwicklelt wurde und darüberhinaus sehr viel Komfort bei der Handhabung der Datenbank und deren Daten mit sich bringt. Ich habe diese SQLRunner genannt und sie ist in meiner Firma mittlerweile sehr verbreitet via Java web Start.

Hier soll es aber nicht um Java Web Start gehen. JWS ist wirklich gut dokumentiert, dass muss ich hier nicht nachholen.

1. Wie kommuniziert Mac OS X mit einer Java Anwendung:
Mac OS sendet an die Anwendung Events:
a) zum Öffnen einer Datei
b) zum Öffnen des “Einstellungen…” Dialoges
c) zum Drucken einer Datei
d) zum Öffnen des About-Dialoges
e) zum Schliessen der Anwendung
Klingt erstmal etwas merkwürdig – jedenfalls für mich.
Wenn man sich Mac OS X Anwendungen ansieht so fällt auf, dass das Menü, egal was man selbst programmiert hat um einen ganz links stehenden Menüpunkt erweitert wurde der nach der Anwendung benannt ist und typischerweise aus immer den gleichen Einträgen besteht: “About”, “Preferences…”, Services (hat keinen Bezug zur Anwendung), “Exit ”

Apple stellt in seiner Java-Implementierung nun eine API zur Verfügung die einem diese Kommunikation bereitstellt. Die dafür notwendigen Klassen sind in:

/System/Library/Frameworks/JavaVM.framework/Classes/ui.jar

Man sollte aber darauf achten welche JRE-Version in der Anwendung unterstützt werden soll und sich besser die Datei aus der passenden version holen.
Das folgende Codesnippet zeigt die Registrierung des notwendigen EventListeners:
Ein paar Vorbemerkungen:
Bei mir hat der Code zum Öffnen einer Datei anfangs nicht funktioniert. Meine Anwendung wurde zwar gestartet aber es kam kein Event zum Öffnen der Datei. Das Problem lag schlicht daran, dass die nachfolgend beschriebene Registrierung zu einem Zeitpunkt erfolgte an dem Mac OS den Event bereits vorher gesendet hat. Meine Applikation hatte schlicht zu spät zugehört. Deshalb unbedingt die Registrierung soweit wie möglich nach vorn verlegen.
Dann hatte ich aber das Problem, dass es zu diesem Zeitpunkt noch kein Fenster oder Editor gab der sich für die übergebenen Inhalte interessiert hätte. Das muss man so lösen, dass man z.B. den Dateinamen erstmal merkt und beim Initialisierungsprozess des Fensters nachfragt ob solche Informationen vorliegen und die dann auch gleich berücksichtigt. Der SQLRunner z.B. initialisiert sich recht langwierig, da diverse Konfigurationen eingelesen werden müssen und dieser Vorgang wird in der boolean initalizationFinished mit true dokumentiert.

public static void main(String[] args) {
    commandLineArguments = args;
    System.getProperties().put("apple.laf.useScreenMenuBar", "true"); // damit Menüs oben in der Leiste landen !
    BasicConfigurator.configure(); // log4j minimal konfigurieren, wird später verbessert
    logger.info("SQLRunner Application Version " + VERSION);
     // unbedingt soweit zum Beginn als möglich den Listener registerieren !!
    String osname = System.getProperty("os.name");
    // laufen wir gerade auf Mac OS X ?
    if (osname != null && osname.toLowerCase().indexOf("mac") != -1) {
        // diese Methode zeitlich so nah wie möglich zum Start der Anwendung ausführen !!
        setupMacOSXApplicationListener(); // registrieren des Listeners
    }
... die Anwendung weiter initialisieren, z.B. Konfigdateien lesen und GUI erstellen usw.
}
    private static void setupMacOSXApplicationListener() {
        if (logger.isDebugEnabled()) {
            logger.debug("setupMacOSXApplicationListener()");
        }
        try {
            final com.apple.eawt.Application application = com.apple.eawt.Application.getApplication();
            application.setEnabledAboutMenu(true); // damit ein "Über " Menü erscheint
            application.addPreferencesMenuItem(); // "Einstellen..." Dialog
            application.setEnabledPreferencesMenu(true); // diesen Dialog auch freischalten
            application.addApplicationListener(new com.apple.eawt.ApplicationListener() {
                // jemand hat auf Über... geklickt
 
                public void handleAbout(com.apple.eawt.ApplicationEvent ae) {
                    if (initializationFinished) { // nur was tun wenn Anwendung bereit ist
// .... hier den eigenen Info-Dialog zeigen oder was auch immer !
                        ae.setHandled(true); // habe fertig...
                    }
                }
 
                // kommt z.B. wenn eine Datei aus dem Kontextmenü heraus geöffnet wird
                // Mac OS startet ganz normal die Anwendung und versendet diesen Event
                public void handleOpenApplication(com.apple.eawt.ApplicationEvent ae) {
                    if (ae.getFilename() != null) {
                        if (initializationFinished) {
                            // die Anwendung ist bereit und alles initialisiert
                            // ... alles notwendige tun um eine Datei zu laden
                        } else {
                            // die Anwendung fährt gerade hoch
                            // noch kein Fenster da.
                            // ich merke mir die zu ladene Datei und muss später das laden nachholen
                            fileToLoad = ae.getFilename(); // fileToLoad ist eine static String variable
                        }
                    }
                }
 
                public void handlePreferences(com.apple.eawt.ApplicationEvent ae) {
                    if (initalizationFinished) {
                        // ... zeige meinen eigenen Einstellen-Dialog
                        ae.setHandled(true); // habe fertig
                    }
                }
 
                public void handlePrintFile(com.apple.eawt.ApplicationEvent ae) {
                    // meine Anwendung kann nicht drucken und will es auch nicht
                }
 
                public void handleQuit(com.apple.eawt.ApplicationEvent ae) {
                    // ... Die Anwendung geordnet beenden
                    // Fragen nach ggf notwendigen Speichern, Streams schliessen usw.
                    ae.setHandled(true); // bin mir nicht ganz sicher ob ich hier noch hinkomme ;-)
                }
 
                // meine Anwendung läuft bereits und jemand klickt unten auf mein Dock-Icon
                public void handleReOpenApplication(com.apple.eawt.ApplicationEvent ae) {
                    // ich würde hier ein weiteres Fenster aufmachen ...
                }
 
                // kommt z.B. wenn eine Datei aus dem Kontextmenü heraus geöffnet wird
                // Die Anwwendung ist aber schon vorher gestartet worden
                public void handleOpenFile(com.apple.eawt.ApplicationEvent ae) {
                    if (initializationFinished) { // sicher ist sicher
                        // Datei öffnen
                    } else {
                        // Datei merken und ggf später öffnen
                        fileToLoad = ae.getFilename();
                    }
                }
            });
        } catch (Throwable e) {
            logger.warn("setupMacOSXApplicationListener failed: " + e.getMessage(), e);
        }
    }

Soweit nun fast alles was man braucht um den eigenen Code zu erweitern

Wir brauchen nun ein schickes Icon für unsere Anwendung.
Dazu malt man sich in der Grösse 128×128 Bit mit 256 Bit Farbtiefe ein hübsche Bildchen im PNG oder JPG-Format.
Dieses Bild muss nun ind das sogenannte Icon-Format überführt werden. bei Mac OS X heissen diese Dateien .icns.
Der angedeutete Plural ist nicht ohne Grund. In der Datei stecken mehrere Bilder mit gleichem Inhalt aber unterschiedlicher Auflösung und Bildgrösse um die Skalierung zu ermöglichen wenn im Doc das Bild grösser wird oder wenn im Finder grössere Icons eingestellt werden. Damit Mac OS X da was zum interpolieren hat sind mehrere unterschiedliche Grössen in einer Datei enthalten.
Ein nettes (billiges aber kostenpflichtiges) Photoshop-Plugin Icon Export hilft hier weiter. Mit Photoshop kann man simpel ein nettes Bild bastel und es dann sogleich mit diesem Plugin in das icns-Format exportieren. Das Plugin funktioniert auch bei dem sehr preiswerten Photoshop Elements (momentan version 4.0) was jeder zweiten Digitalkamera kostenlos beiliegt oder im Laden 90 Euro kostet. Ich hatte es mir gekauft und es nie bereut !

Nun sind alle Zutaten zusammen: Wir haben eine nette Anwendung und auch ein hübsches Icon.

Nun müssen wir noch eine echte Mac-App bauen.
Ich bevorzuge dazu ant. Aktuell ist gerade die Version 1.7.0 – kann ich nur dringend empfehlen !

Hier ein Teil meines ant-scripts.
Ich kenne nur einen wirklich sinnvollen Weg: der jarbundler. Das Teil ist sehr gut dokumentiert !

Hier ein Beispiel für ein ant-task:

<target name="macapp"
        depends="jar"
        description="build Mac OS X application bundle">
    <delete failonerror="false"
            includeemptydirs="true"
            dir="${macappdir}" />
    <mkdir dir="${macappdir}" />
    <taskdef name="jarbundler"
             classname="net.sourceforge.jarbundler.JarBundler" />
    <jarbundler dir="${macappdir}"
                name="SQLRunner"
                shortname="SQLRunner"
                infostring="Version ${version} Copyright Jan Lolling"
                icon="${src}/sqlrunner.icns"
                version="${version}"
                mainclass="sqlrunner.Main"
                jvmversion="1.5+"
                vmoptions="-Xmx512m -Dcom.sun.management.jmxremote=true -Dapple.awt.graphics.UseQuartz=true">
        <jarfileset dir="${lib}">
            <include name="*.jar" />
        </jarfileset>
        <jarfileset dir="${distrib}">
            <include name="sqlrunner2.jar" />
        </jarfileset>
        <documenttype name="SQL script" extensions="sql" role="Editor" />
        <documenttype name="SQLRunner CSV Import Configuration" extensions="importconfig" role="Editor" />
    </jarbundler>
    <mkdir dir="${macappdir}/SQLRunner.app/Contents/Resources/German.lproj"/>
    <mkdir dir="${macappdir}/SQLRunner.app/Contents/Resources/English.lproj"/>
    <delete file="${macappdir}/SQLRunner.app/Contents/MacOS/JavaApplicationStub" />
    <echo>copy JavaApplicationStub</echo>
    <exec executable="cp">
        <arg line="/System/Library/Frameworks/JavaVM.framework/Resources/MacOS/JavaApplicationStub" />
        <arg value="${macappdir}/SQLRunner.app/Contents/MacOS/JavaApplicationStub" />
    </exec>
</target>

Java-Anwendungen werden wenn sie wie normale Mac Anwendungen gestartet werden sollen mit einem JavaStub gestartet. Dieser kann direkt in das eigene Projekt kopiert werden oder er wird verlinkt (wie im Beispiel). das direkte Kopieren hat den Nachteil das man damit die JRE-version festlegt ist aber krisenfest wenn Apple mal die Verzeichnis-Struktur von Java ändern sollte. Der symbolische Link hat den Vorteil, dass man immer mit der aktuellsten Version arbeitet und den Nachteil dass Verzeichnisänderungen der JRE ein echtes Problem darstellen würden. Seite der ersten Version von Mac OS X ist dieser Pfad aber stabil geblieben, weshalb ich das skizzierte Risiko als gering einschätze.

Viel Freude mit Java auf dem Mac wünscht Jan

iPhone Aktivierung mit Java

22. August 2007 von Jan Lolling in Java
Schlagwörter: ,

Die Aktivierung des iPhone (Rufnummervergabe und Vertragserstellung beim Provider – also der gesamte Provisioning-Prozeß) wird sich komplett von dem unterscheiden was bisher üblich war. Bisher ist man in den Laden gegangen und hat das Mobilfunktelefon samt SIM-Karte mit eingetragener Riufnummer gleich mitnehmen können. Meist war noch eine Wartezeit (ca. 1-2 Stunden) notwendig bis der Bereitstellungsprozeß in den IT-Systemen des Providers komplett durchgelaufen war und im Laden musste man auch noch eine Weile warten. Alles in allem war man nicht in der Lage komplett Online zu einem Mobilfunk-Telefon zukommen.
Das wird sich mit Apples iPhone nun ändern.
Die Aktivierung (sogar mit Providerwechsel!) wird in iTunes abgewickelt und iTunes spricht seinerseits über Webservices einen für das jeweilige Land zentralen Provisioning-Server an auf dem alle Prozesse abgebildet sind. Die Serversoftware ist komplett in Java geschrieben und läuft auf einem BEA-Applicationserver und nutzt eine Oracle 10g Datenbank.
iTunes benutzt auf der Clientseite ebenfalls Java um die Kommunikation durchzuführen und für die interne Workflowsteuerung.
Bei Mac OS X ist das kein Problem da dort Java zur Standardausstattung gehört, bei Windows müsste dann vermutlich Java installiert werden oder iTunes bringt eine kleine JVM mit – mir noch nicht bekannt. Der ganze provisioning Prozeß wird typischerweise in ca. 8-10 Minuten durchlaufen. Auf der amerikanischen Apple-Seite kann man sich ein Video ansehen in dem der Prozeß komplett durchlaufen wird. Die dahinter stehende Software wird gerade für die europäschen Verhältnisse angepasst.
Wenn man mal den bisherigen Prozeß der Aktivierung vergleicht mit dem was Apple mitbringt ist das ein Quantensprung! Ein typischer Bereitstellungsprozeß kostet bei der Deutschen Telekom ca. 50-60 Euro. Der iPhone-Prozeß verursacht ausschliesslich IT-Kosten und keine Personalkosten (mal übliche Supportdienstleistungen nicht mit betrachtet).

  • Kommentare deaktiviert

« vorherige Beiträge nächste Beiträge »