letzter Stand

Nachdem ich nun meine JRA jar habe und auch die restlet jar habe (Ich denke mir einfach mal, dass die vorausgesetzt wird).
Habe ich mir nun eine einfache Klasse geschrieben (okay sie ist geklaut, aber ich will ja erstmal testen, wie was geht ^^):

package de.hausswolff.cotodo.test;
import java.util.List;
import org.codehaus.jra.*;
@HttpResource(location="/customers")
public class Customers {
    private List registry;

    public Customers(){
        this.registry.add(new Customer("bob"));
        this.registry.add(new Customer("alice"));
        this.registry.add(new Customer("carol"));
        this.registry.add(new Customer("dave"));
    }
   
    @Get
    List get(){
        return registry;
    }

    @Post
    void add(Customer customer){
    }
}

Okay… die Klasse wird anstandslos kompiliert und auch Eclipse kennt alle Annotation (dient wahrscheinlich nur zu meiner Beruhigung, sagt es mir doch, dass die jar richtig eingebunden ist 😀 ).
Was ich mich jetzt allerdings frage ist, wie ich das schöne Teil nun einbinde.
Da es ja von Aufbau her nicht wirkliche eine Bean ist.
Ich habe versuchsweise in der web.xml folgendes eingefügt:

<servlet>
    <servlet-name>JRACustomers</servlet-name>
    <servlet-class>de.hausswolff.cotodo.test.Customers</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>JRACustomers</servlet-name>
    <url-pattern>/customers*</url-pattern>
</servlet-mapping>

Allerdings half das auch nicht. Unter /customers ist nix :-(. Ich werde mich damit morgen in aller Ruhe noch mal befassen.
Als weiter Möglichkeit, dachte ich mir, dass ich die Class per jsp useBean Tag einbinden kann, aber ist ja auch keine wirkliche Bean. Ich hoffe, dass ich da morgen weiter mit komme. Im Netz fand sich bisher auch nix. Und auf der JRA Page wird nur nach paranamer verwiesen. Was das nun schon wieder ist, werd ich mir morgen/gleich mal anlesen.

hands-on: Maven(2)

Bevor ich dann endlich mal wieder etwas über meine eigentliche Arbeit poste, noch mal ein kleiner Abstecher zu dem Thema “Dinge die man nebenher sich aneignet”.
Ich habe mich mal, nach dem Kommentar von Stefan bezüglich JRA umgesehen.
Leider fand ich zuerst nur eine Source Version vom JRA Code, sodass ich mir erstmal die Fähigkeit aneignen musste, das ganze zu kompilieren.
Als Build Tool kommt hier übrigens Maven 2 zum Einsatz.
Das ganze ist vom Apache Projekt und soll wohl irgendwann einmal die Nachfolge von Ant antreten. Wenn man sich so die Feature PlugIns Liste ansieht, ist das auch durchaus wahrscheinlich.
Der riesen Vorteil von Maven 2 – soweit ich das bisher verstanden habe – ist, dass man die Tools, welche man zum Erstellen/Installieren/Testen/Deployen benutzen will, nicht vorher installieren muss, sondern dass Maven 2 von der Versionierung der Sourcen bis hin zum letztendlichen Kopieren auf das Zielsystem alles übernimmt.
Um es kurz zu machen: Ich erhielt dann nach viel Installation und Tutorials lesen endlich meine jra-1.0-alpha-5-SNAPSHOT.jar 🙂 .

Nachdem ich dann noch mal auf der JRA Homepage gesucht habe, habe ich allerdings gesehen, dass es eine alpha 4 auch zum Download gibt. Nunja bin ich zumindest ein wenig aktueller. Jetzt will ich mal schaun, dass ich die Jar einbinden und mit meinem bisherigen Projekt zum Laufen kriege.

erster Eintrag erstellt!

Mittlerweile konnte ich jetzt auch schon den ersten Eintrag erstellen. Das ganze schaut noch recht umständlich aus, weil noch so gar keine Frontends existieren:

public String addEntry(){
    User recipient = (User)em.find(User.class, 3);
    Entry important = new Entry();
    Calendar cal = Calendar.getInstance();
    cal.set(2007, 12, 15);
    Date end = (Date) cal.getTime();
    important.setSender(user);
    important.setRecipient(recipient);
    important.setPriority(1);
    important.setStatus(10);
    important.setTitle("start with ADAM&EVA");
    important.setDeadLine(end);
    important.setSendDate(new Date());
    important.setContent("no text");
    em.getTransaction().begin();
    em.persist(important);
    em.getTransaction().commit();
    em.close();
    return important.toString();
}

Es gibt – natürlich – den Benutzer mit ID 3 (als Empfänger) schon und auch user ist als Attribut der Klasse schon gesetzt.
Letztendlich wird der Eintrag auch abgespeichert – wenn man so will die erste wirklich sinnvolle Funktion :-).
Mittlerweile habe ich mich dazu entschlossen gemäß MVC alle POJOs für JPA im Package de.hausswolff.diplom.M zu speichern und im Package de.hausswolff.diplom.C die Controller (in dem Buch hießen diese Serviceklassen, also für Klasse User aus dem M Package wäre es dann halt UserService. Die Ausgabe in Form von normalen Servletts werde ich dann komplett in einem V Package bündeln.
Was mich noch ein wenig beschäftigt ist, dass ich ja gerne nach dem REST Prinzip vorgehen möchte und also unter /user/3/inbox/5 den Eintrag von Benutzer mit der ID 3, den er erhalten hat (inbox) mit der ID 5 erhalten möchte. Ich nehme mal sehr stark an, dass es dafür eine Java Lib gibt. Habe aber auch noch nicht großartig gesucht. Ich werde – sobald ich die 3-Tabellen Lösung zum Laufen bekomme (siehe letzter Eintrag – war leider ein wenig spät/früh gestern/heute ^^) – mal anfangen die neue Package Struktur als UML zu erstellen.

JPA YEEHA!

Besser später als nie, hier also dann mal – nach laaaanger Zeit mal wieder – mein aktueller Status.
Mittlerweile bin ich ein ganzes Stück weiter und so fange ich sogar an, dem ganzen System von Persistence etwas abgewinnen zu können. Einzig die Frage bleibt, wieso JPA per default partout alle Feldnamen als groß schreibt. Naja das wird sich sicherlich auch noch klären. Aber zuersteinmal der Reihe nach:
Das – anfängliche Problem, dass ich ja einen Integer Primary Key brauche, aber auch zum Beispiel auch ein User Objekt anhand eines Namens (der ja nach meiner Definition auch eindeutig sein soll) erstellen will, ergab sich die Zwickmühle, dass es ein System geben muss, welche einem quasi einfache SQL Searches erlaubt… gibt es auch.
Anhand einer Präsentation, von Phillip fand sich dann auch eine recht kurze (und demnach schmerzlose) Lösung:

@Entity
@Table(name = "Users")
@NamedQuery(name = "findWithName", 
    query = "SELECT u FROM User u WHERE u.name = :Name")
public class User {
    ...
}

Das sagt der Klasse, dass sie, wenn ich eine Query namens (“findWithName”) ausführe, das nachfolgende SQL Statement benutzen soll und demnach auch den Parameter ‘Name’
Der Aufruf schaut dann so aus:

User user = (User) em.createNamedQuery("findWithName")
            .setParameter("Name", "TestUser").getSingleResult();

Nunja ein schöner, langer Aufruf. Aber immerhin wird mir ein User Objekt erstellt, wenn ein User mit Namen ‘TestUser’ existiert!
Kommen wir zum nächsten Punkt – mein Lieblingspunkt an diesem Morgen, weil das mich ziemlich viel Zeit und Schweizß gekostet hat (obwohls doch eigentlich so einfach ist) – die Kardinalitäten – ODER AUCH -” wie papern, wer n Eintrag an’nen User?”
Ich bin in mich gegangen und kam mit der Entscheidung aus mir (sagt man das so?), dass ich für jeden Eintrag, der von User A nach User B geschickt wird, ein Eintrag in der Datenbank erstellt wird. Also selbst, wenn User A an B und C die gleiche Aufgabe verteilen würde, würden zwei Einträge erstellt. Ich weiß, dass es dann recht unmöglich ist, zum Beispiel zwei User für eine Aufgabe vorzusehen und diese Aufgabe dann bei User B erledigt ist und bei User C noch offen – letztendlich ging es mir auch ersteinmal darum, die Abhängigkeiten hin zu bekommen.
Also erstmal die Veriante mit Stützrädern (zwei Tabellen) und dann hinterher (so morgen) schau ich mal, ob ich das auch freihändig schaffe (so drei Tabellen).
Letztendlich schaut das mit JPA ähnlich aus wie bei Willem und seinen RoR (gabs da nich mal n Lied mit RoR, RoR, RoR the Boat? aber ich glaube das war Row… egal).
Also vielleicht zuerst einmal die beiden Klassen und wie diese zusammenhängen:

Ja die Attribute laden quasi dazu ein, auf eine 3. Tabelle auszulagern ;-).
Es gibt also zwischen User und Entry exact zwei 1-zu-N Beziehungen:
1. Hat ein User genau eine Inbox mit N erhaltenen Entries
2. Hat ein User genau eine Outbox mit N versandten Entries
Da Willem nich Ruhe geben wollte, habe ich die Tabellen gleich mal Pluralisiert (okay ist auch sonst ne ganz gute Idee) und die IDs _id getauft.
Für JPA geht man nun wie folgt vor:

...
public class User {
    ...
    @OneToMany(mappedBy = "recipient")
    private Collection inbox;
    @OneToMany(mappedBy = "sender")
    private Collection outbox;
    ...
}
...

sagt einem, dass jeweils die Attribute (eigentlich die Items aus den Collections) inbox und outbox an das Attribut (und hierbei geht es wohl wirklich um das Objekt ansich) “recipient”/ “sender” gemapped werden.
In der Klasse Entry muss dann natürlich quasi “das Kind konfiguriert werden” (das klingt jetzt seltsam aber im Moment fällt mir nix gescheiteres ein):

...
public class Entry {
    ...
    @ManyToOne()
    @JoinColumn(name="recipient_id")
    private User recipient;
    @ManyToOne()
    @JoinColumn(name="sender_id")
    private User sender;
        ...
    }
...

Na gemerkt? ManyToOne anstatt OneToMany….ach war klar? Na,… okay :-).
Nun werden halt nur noch schnell die Feldnamen aus der DB Table angegeben und besagte Objekte erstellt ( recipient/ sender ). Geht ja eigentlich ganz schnell…
Das Setten/Getten probiere ich dann mal morgen und dann auch gerne mit 1+1+1 = 3 Tabellen. Gibt einem ja dann doch ein wenig mehr Möglichkeiten.
Das EJB3 Buch ist übrigens gut. Man liest, schreibt, sucht dann noch nen anderes Beispiel und dann versteht man es erst ;-). Nach und nachen rücken aber erster und letzter Schritt immer näher zusammen.
Ich wünsche allen eine erfolgreiche Woche.

Was bisher so geschieht…

Moin…
Ich wollte mal wieder ein wenig Feedback geben, woran ich bisher so sitze…
Letztendlich bin ich endlich mit einer schönen Datenbankklasse ausgestattet, die mir auch die Dinge bietet, auf die ich angewiesen sein werde – ob da jetzt noch etwas dazu kommt, wird sich zeigen, aber erstmal reicht mir das, was bisher vorhanden ist. Zudem bin ich auf ein paar Besonderheiten von JSP/Java und MySQL gestossen, die in meinen Augen recht unlogisch sind, aber nunja, vielleicht gibt sich das noch.
Mein bisheriger Plan ist es, jetzt erstmal die Grundfunktionen des Servers mit einer einfachen HTML Oberfläche zu erstellen, um dann den Client mit Hilfe von YUI dynamischer zu gestallten.
Aber jetzt erstmall ein Überblick über die Klassen:

Die statische Config Klasse ist erst später hinzugekommen, sodass ich die Attribute aus der Datenbankklasse, welche den Zugriff betreffen wohl dann entferne und die Benutzerdaten zentral in der Config Klasse speichere.
Ich habe jetzt auch schon erste Tests mit einer Session hinter mir, aber das Klassendesign ist noch sehr gewöhnungsbedürftig ^^.

Die Klasse TOOLS soll einfach zur Sammlung verschiedener Funktionen dienen.
Die md5 Methode dient einfach dazu, einen gegeben String als md5 Summe zurückzugeben. Dies brauche ich u.a. für die Passwörter.
Sobald ich die erste HTML Oberfläche habe (die dann einfaches Anmelden, Erstellen und Auflisten von Einträgen beherrschen wird, werd ich erste Funktionstests machen.
Das Schöne, was ich an Eclipse gefunden habe ist, dass man per Vorgabe einfache TextKlassen für Klassen erstellen kann. Dort werden alle Methoden einmal aufgerufen.
Ob das für ein Unit Testing ausreicht muss ich dann noch mal sehen.

Achja… Java und MySQL: Die erhaltenen Einträge aus der Datenbank speichert Java in einem sog. Resultset. Mit der methode next() kann man die verschiedenen Einträge durchblättern. Das komische ist nur, dass wenn – nachweislich – nur ein Eintrag vorhanden ist, muss man dennoch einmal die next() methode aufrufen.
Also muss man von 0. Eintrag auf den 1. blättern? O_o. Meiner Meinung nach irgendwie unnlogisch. Dementsprechend hat mich das auch ein wenig aufgehalten.
Betroffen war u.a. diese Methode aus der Klasse User:

public void load(){
    this.DB.Query("SELECT `ID`, `password` " + 
                   "FROM `users` WHERE `name` = '"+this.name+"' ");
    try {
        ResultSet res = this.DB.getLastResult();
        System.out.println(res.toString());
        res.next();
        this.ID = res.getInt("ID");
        this.password = res.getString("password");
    }catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Ob ich jetzt das “erste Blättern” in der getLastResult() unterbringe habe ich mir noch nicht überlegt.
Wünsche allen frohes Schaffen und ein schönes Rest-Wochenende!

simple iPhoto Gallery Script

Some time ago, i searched for a very simple possibility for publishing some photos online.
As a Mac User i am recently using iPhoto for collecting and organizing my photos.

I reused some old PHP code and create a simple Script, that searches through some iPhoto Web Exports to build a nice index page with folder previews:

phpGallery Screen1

The folder structure should be as the following:
phpGallery Screen2

As i do not have other language Versions of iPhoto, i do not know, if the scripts works also with other Versions of iPhoto.

Here you can download the very first version of the script:

PHP_Gallery_Script_for_iPhoto06_german

FINALLY: Comments are working again

A friend of mine told me some minutes ago that the Comments function on this blog still produces some errors, when trying to post a comment. So i decided to stay with the spam and to disable the filter function until i have the time and the infos about the wordpress system to code my own plugin.

I found another project i worked on in the past years. I updated it a little bit and can now present some screen impressions:

First of all what is it?
So i have the big problem of to many files on to big disk space. As a result there is first the problem of finding files and second the high probability to save identical files on several places. Not only small files like the typical 1×1 spacer.png, but also some sound files, hi-res images or movie files. Just in case of the backup of a backup.

So i decided that i need a system, that organizes my files in that way, that i can have a quick view, i may search through all the files and that there is the safety, that a file is just saved onced and all the copies of it should be just links to the original ones.

I end up with a system design that scans a particular folder for new files and copy them into a special ordered file structure. The unique property of a file is its md5 sum. The original file/folder structure is mapped into a DB table.
The system is no at exactly this point. I created a easy low level plugin interface for examining the different file types.
Lateron i will create a class, that make sys links equivalent to the original folder structure and offer them e.g. as a samba share. Even the possibility of a file history is imaginable. At this point the main task is the imense low performance (due a big use of DB queries and redundant method calls) and the definition of a usefull interface.

Here are some screens of the current system:
File-Vault storage Folder
System File Storage

File-Vault picture Viewer
Picture Viewer

File-Vault mysql Viewer
SQL (Text) Viewer with Import Function

File-Vault PHP Viewer
PHP Viewer

File-Vault MP3 Viewer
MP3 Player

mbff

Vor einiger Zeit habe ich mit der Entwicklung eines Browser Games angefangen.
Zu finden ist eine der ersten Versionen hier:
http://mbff.hausswolff.de

Da mir momentan die Zeit fehlt, es weiter zu entwickeln, und ich eh vorhatte den Server von PHP auf JSP umzustellen, habe ich alle alten Scripte gesammeln und stelle diese hier zum Download bereit.
Der Code ist recht spärlich kommentiert, falls Fragen sind, einfach hier stellen und ich schaue ob ich diese beantworten kann.

mbff-dump-v.0.0.1.0

mbff-planet

mbff-system

mbff-galaxy

Update des Counters

Guten Abend/Guten Morgen :-).

Ich habe mir ein wenig die Nacht um die Ohren geschlagen, um meinem Counterscript ein Update zu verpassen:

z.B.: Die Statistik dieses Blogs:

Es werden nun auch die globalen Informationen der IP Adressen ausgewertet. Dummerweise ist die Datenbank, in der die Zuordnung IP <=> Land vermerkt ist, ein wenig unkorrekt (okay…das meiste ist falsch ^^). Ich habe aber schon eine bessere finden können, muss ich nur ein wenig umkonvertieren.
Die – neuen – blauen Balken zeigen an, wieviele Benutzer an einem Tag die Seite besucht haben – im Gegensatz zu der sonstigen Aufsumierung.