April 3, 2007

Verbesserter Spamschutz über Captcha Code

Seit einiger Zeit erhalte ich wieder vermehrt Spam Einträge über Benutzerformulare. Zwar benutzte ich den von mir entwickelten Captcha Bestätigungscode, jedoch scheint dieser mittlerweile zu einfach für die Spambots zu sein.

Deshalb habe ich mich noch einmal hingesetzt und den Captcha Code verbessert, um es den Bots schwerer zu machen, den Code zu erkennen.

Die Veränderungen sind:

  • im Hintergrund des Captcha Codes wird ein zufälliges Polygon gezeichnet (kann auch deaktiviert werden)

  • alternierende Textfarbe

  • zufällige Drehung der Zeichen


Hier noch eine kleine Feature Liste des Captcha Skripts:

  • Auswahl welche Zeichentypen zur Generierung einer zufälligen Zeichenfolge benutzt werden sollen (Zahlen, Klein-, Großbuchstaben)

  • beliebige Länge an Zeichen

  • Abmessungen des Captcha Bildes

  • Farben frei definierbar


Das Skript läuft mit PHP4 und GDLib .

March 23, 2007

Trac Eclipse Plugin

Nachdem ich mich gestern mit einem Kommilitonen über unsere bevorstehenden Diplomarbeiten austauschte, kamen wir auf das Thema Projektmanagement. Beide setzen wir das Tool Trac ein, da wir es schon im Softwareprojekt erfolgreich eingesetzt haben.

Eine kurze Liste der Features von Trac:

  • sehr gute Integration von Subversion

    • Subversion Changesets (Timeline)



    • Repository Inhalt über Webbrowser abrufbar



  • Ticketsystem (Bugtracker)

  • Wiki

  • Milestones


Daraufhin kam bei mir der Wunsch nach einem Eclipse Plugin auf, so dass ich die Tickets auch dort sehen kann. Und ein solches Plugin gibt es auch.

So setzte ich mich sofort hin und wollte das Plugin installieren.

Nach der Anleitung müssen erst zwei Trac-Plugins installiert werden. Das funktioniert auch ohne Probleme. Dann das Eclipse-Plugin per Update Manager installieren. Doch leider (mal wieder) Abhängigkeitsprobleme: Es fehlt org.atl.eclipse.adt.debug. An sich sollte ich dieses Plugin installiert haben, weil die Xtext Komponente von openarchitectureware ATL ebenfalls benötigt. Heruntergeladen habe ich es bereits, anscheinend aber vergessen in den Eclipse Plugin Ordner zu kopieren ;).

Na egal, ATL dort rein und Eclipse neu starten. Und? Mist immer noch nicht. Auch org.eclipse.gmf.runtime.diagram.ui fehlt. Kann dieser Update Manager nicht gleich alle Abhängigkeiten anzeigen?! Dieses Prozedere geht mir jedes mal auf die Nerven und vor allem kostet es Zeit :(

Also auch noch GMT installieren. Eclipse Neustart. Und? Nee, schon wieder fehlendes org.atl.eclipse.adt.debug. Hm, vielleicht ist meine Eclipse Installation kaputt? Einfach mal das Trac Plugin so herunterladen und installieren - ohne Update Manager. Neustart. Und? Läuft ohne Probleme!

Nun noch einen neuen Trac Server anlegen. "Verbindung kann nicht hergestellt werden." Hä, warum das denn nicht?! Nach etwas stöbern in der XmlRpcPlugin Dokumentation kommt heraus, dass das Plugin nur mit dem BASIC-AUTH Authentifizierungsverfahren funktioniert. Ich benutze aber Digest. Das auch noch umstellen:

tracd.py -p8000 --basic-auth=*,C:...users.htbasic,trac C:... rac hesis


Beim Neustart des Daemon erscheint die Meldung, dass das crypt Modul zum entschlüsseln des Passworts nicht gefunden werden kann. Dieses Modul gibt es unter Windows nicht.

Daraufhin habe ich den Versuch Trac über das Eclipse Plugin zu bedienen ersteinmal eingestellt (hat schließlich schon 90 Minuten gekostet) :(

March 14, 2007

Alfresco in JBoss 4.0.5 integrieren

Seit Kurzem ist das Document Manangement System Alfresco in der Community Edition in Version 2.0 verfügbar. Leider gibt es einige Schwierigkeiten das neue Release mit JBoss AS in der Version 4.0.5 lauffähig zu bekommen.

Zwar erscheint Alfresco, man kann es aber nicht benutzen, da die Links JavaScript Fehler produzieren. So etwas zum Beispiel:

Error: document.forms.dashboard['dashboard:act'] has no properties


Grund dafür scheint eine fehlerhafte MyFaces Bibliothek zu sein.

Um Alfresco doch unter JBoss 4.0.5 zum Laufen zu bekommen, muss man unter $JBOSS_HOME/server/default/deploy/jbossweb-tomcat55.sar/jsf-libs/ die MyFaces Jars (in Version 1.1.4) gegen eine ältere Version (1.1.1) austauschen. Mit dieser Version von MyFaces kann Alfresco auch unter JBoss AS 4.0.5 benutzt werden. Unter 4.0.4 ist ein Austausch nicht notwendig, da dort MyFaces eh in Version 1.1.1 vorliegt.

Soweit so gut. Möchte man Alfresco 2.0 auch noch in einem Portlet unter JBoss Portal 2.4.1 benutzen, wird es komplizierter. Doch es gibt eine Lösung, die hier beschrieben wird.

February 25, 2007

Vortrag: openarchitectureware

Bereits am 12.12.07 hielt ich einen Vortrag im Rahmen der Special Interest Group "Model Driven Software-Engineering" (SIG-MDSE) über openarchitectureware.

Mit dem Generator Framework konnte ich mich während meines Praktikums bei Form4 intensiv aueinandersetzen. Das Ziel des Vortrags war eine praktische Einführung in die Benutzung von openarchitectureware zur modellgetriebenen Softwareentwicklung zu geben.

Die Präsentation, sowie der "live" entwickelte Generator steht auf den Seiten der SIG-MDSE zum herunterladen bereit.

January 28, 2007

Windows LaTeX Editor

Da ich mich langsam auf meine Diplomarbeit vorbereite, stellt sich mir die Frage, mit welchem Schreibwerkzeug ich die Arbeit anfertigen werde. Zur Auswahl steht OpenOffice und LaTeX.

Sicher hat OpenOffice den Vorteil eines WYSIWYG Editors, wo man gleich sieht, wie das Geschriebene aussieht. LaTeX mit seiner Syntax ist da schon kryptischer. Bisher habe ich noch keinen vernünftigen Editor für LaTeX unter Windows gefunden, der diesen Nachteil gegenüber Office Programmen ausgleichen konnte.

Jedoch bin ich vor einiger Zeit auf den Editor LEd gestoßen. LEd verfügt über eine integrierte DVI Vorschau. Zwar muss noch kompiliert werden, bevor das Dokument angezeigt wird, aber die paar Sekunden kann ich warten.

January 22, 2007

Web Service mit Java 6

Im neuen Java Release (Mustang) besteht die Möglichkeit ohne weitere Zusatzmittel mit Web Services zu arbeiten. Es ist sehr einfach einen solchen Service lokal zu testen. Lediglich die Klasse, die Services (Methoden/Funktionalität) bereitstellen soll, wird mit einigen Annotations versehen.

Um eine Klasse als Web Service zu kennzeichnen wird sie mit der Annotation javax.jws.WebService und Service Methoden mit javax.jws.WebMethod markiert. Außerdem muss der Web Service veröffentlicht werden. Hier hilft die Klasse javax.xml.ws.Endpoint, die eine statische Methode publish(String address, Object implementor) zur Verfügung stellt.

package webservicetest;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.xml.ws.Endpoint;

@WebService
public class CalculatorService{

@WebMethod
public int duplicate(int value){
return value * 2;
}

public static void main(String[] args) {
Endpoint.publish("http://localhost:8080/Calculator", new CalculatorService());
}
}


Startet man die main Methode dieser Klasse, ist der Web Service unter der URL http://localhost:8080/Calculator so lange verfügbar bis das Programm terminiert. Als Test kann die URL http://localhost:8080/Calculator/rate?WSDL aufgerufen werden. Im Browser erscheint daraufhin eine Beschreibung des Services im WSDL Format.

Mehr Informationen und weitere Möglichkeiten finden sich in der Java 6 API.

January 7, 2007

[FeedCreator] RSS-Feed mit PHP

Wie kann ich meinen Besuchern Inhalte per RSS-Feed zugänglich machen?

Diese Frage stellte ich mir vor Kurzem auch. Nach etwas googeln, habe ich relativ schnell eine Antwort gefunden.

Deshalb möchte ich die Implementierung des RSS 2.0 Feeds nicht im Einzelnen beschreiben, sondern das PHP Skript hier zum herunterladen bereitstellen.
Aufbau

RSS verlangt eine bestimmte XML Struktur (siehe RSS 2.0). Die PHP Klasse setzt diese Struktur um.
Benutzung

Als Erstes muss ein neues Objekt mit den grundlegenden Informationen (Titel, URL, Beschreibung, Sprache) erstellt werden.


$feed = new FeedCreator("Feed Titel", "http://link/zum/feed", "Beschreibung des Feeds", "de-de");

Zusätzlich können noch weitere Feedinformationen hinzugefügt werden. Mehr in der API (ethalten im zip Archiv - Ordner doc).

Als nächstes werden dem Feed Artikel (Items) hinzugefügt. Das geht einfach über

$feed->addItem("Artikel Titel", "Text des Artikels", "Link zum vollständigem Artikel");

Die Länge des Textes wird standardmäßig nicht beschränkt. Die maximale Anzahl von Wörtern kann über $feed->setSize(100); angepasst werden (bevor sie addItem() benutzen).

Nun muss nur noch der RSS-Feed als XML-Datei ausgegeben werden. Das geht mit Hilfe der Funktion $feed->getXML();.
Wichtig: Vor dem Aufruf dieser Methode darf noch nichts an den Browser gesendet worden sein. D. h. keine print oder echo Ausgaben vorher.
Erweiterungen

Den einzelnen Artikeln können noch mehr Informationen beigefügt werden.
Veröffentlichungsdatum

Nützlich für den Abonnementen für die Sortierung im Feedreader. Das Format richtet sich nach RFC 2822. Nützlich erweist sich die date("r") Funktion von PHP.

addItem("Titel", "Text", "URL", "Thu, 21 Dec 2000 16:01:07 +0200");
Autor

Der Autor des Artikels.

addItem("Titel", "Text", "URL", "Thu, 21 Dec 2000 16:01:07 +0200", "autor@mail.de (Autor Name)");
Kategorie

Um dem Artikel eine Kategorie zuzuordnen, muss ein Hilfsobjekt (Category) erstellt werden. Diesem Objekt werden die Kategorien getrennt durch einen / und ein optionaler Namespace angegeben.

$categorie = new Category("Technik/PC", "http://meinedomain.de");
addItem("Titel", "Text", "URL", "", "", $category);
Anhang

Für einen Anhang gibt es auch eine Hilfsklasse (Enclosure). Diesem Objekt muss die URL des Anhangs, die Größe in Bytes und der MIME-Typ mitgeteilt werden.

$enclosure = new Enclosure("http://image.png", 1536, "image/png");
addItem("Titel", "Text", "URL", "", "", null, $enclosure);
Download

FeedCreator_0.3.zip

January 5, 2007

Persistenz für Desktop Anwendungen mit JPA und JavaDB

Im neuen Java 6 Release wird eine Datenbank (Java DB) gleich mitgeliefert, daher liegt es nahe diese für Desktop Anwendungen zu benutzen. Außerdem wurde innerhalb des JSR 220 die sogenannte Java Persistence API (JPA) spezifiziert. Die Persistierung von Objekten wird dadurch transparenter und ist nicht mehr vom Persistenz Framework (z.B. Hibernate) abhängig. Zudem ist das objektrelationale Mapping deutlich einfacher, da es anhand von Annotations gesteuert wird.
Voraussetzungen

In dieser Beschreibung benutze ich die Eclipse Entwicklungsumgebung und Hibernate als Implementierung der JPA. Es werden folgende Hibernate Komponenten benötigt: Hibernate Core, Hibernate Annotations und Hibernate EntityManager. Außerdem ist ein installiertes Java 6 erforderlich.

Aus den verschiedenen Hibernate Komponenten werden folgende Bibliotheken benötigt, die am besten in den Ordner lib kopiert werden.

- lib
+ antlr-2.7.6.jar
+ asm-attrs.jar
+ asm.jar
+ c3p0-0.9.0.jar
+ cglib-2.1.3.jar
+ commons-collections-2.1.1.jar
+ commons-logging-1.0.4.jar
+ dom4j-1.6.1.jar
+ ejb3-persistence.jar
+ hibernate-annotations.jar
+ hibernate-entitymanager.jar
+ hibernate3.jar
+ javassist.jar
+ jboss-archive-browsing.jar
+ jta.jar
+ log4j-1.2.11.jar

Diese Bibliotheken müssen im Klassenpfad eingetragen sein. Außerdem ist es notwendig, die derby.jar ($JAVA_HOME/db/lib/) ebenfalls in den Klassenpfad aufzunehmen.

Konfiguration

Trotz Verwendung von Annotations für das objektrelationale Mapping ist eine Konfiguration mittels XML Datei erforderlich. Für JPA wird dazu im Verzeichnis etc/META-INF/ die Datei persistence.xml angelegt. Darin wird angegeben, welche JPA Implementierung genutzt wird. Außerdem werden Persistenz Framework spezifische Einstellungen vorgenommen. Da diese Datei, ebenso wie die Jar-Dateien, im Klassenpfad verfügbar sein muss, wird das etc Verzeichnis zu den Quellverzeichnissen (Source Folder) hinzugefügt.

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<persistence-unit name="hibernate">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="hibernate.connection.url" value="jdbc:derby:TestDatabase;create=true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect" />
</properties>
</persistence-unit>
</persistence>

Jeder persistence-unit muss ein provider zugeordnet werden. Außerdem können weitere Providerspezifische Eigenschaften definiert werden.
Für das Beispiel mit Hibernate müssen Eigenschaften der Verbindung eingetragen werden. So z.B. der verwendete JDBC Treiber (hibernate.connection.driver_class) und die URL zur Datenbank (hibernate.connection.url). Die mitgelieferte JavaDB kann über jdbc:derby:$database erreicht werden. Beispielsweise wird durch die URL jdbc:derby:TestDatabase;create=true die Datenbank TestDatabase benutzt. Sollte diese nicht existieren, wird sie angelegt. Das Hibernate auch mit der JavaDB arbeiten kann, muss zudem der zu verwendende Dialekt eingestellt werden.

Diese drei Einstellungen sind notwendig, um mit der Hibernate auf JavaDB zu arbeiten. Es können aber noch viel mehr Einstellungen für Hibernate vorgenommen werden (siehe Hibernate Konfiguration).

Verwendung

Nach der Erstellung der Konfiguration können nun Objekte dauerhaft gespeichert und wieder gelesen werden. Dazu müssen die zu persistierenden Beans (bzw. POJOs) mit Annotations versehen werden. Alle Klassen, die persistiert werden sollen, erhalten die Annotation javax.persistence.Entity.

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Person {

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "PERSON_ID")
private long id;

@Column(name="DNAME")
private String name;

private String firstName;

public String getFirstName() {
return this.firtsName;
}

public void setFirstName(final String firstName) {
this.firstName = firstName;
}

public long getId() {
return this.id;
}

public void setId(final long id) {
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(final String name) {
this.name = name;
}
}


Daneben ist es notwendig, dass die Bean ein Attribut besitzt, über die das Objekt eindeutig identifiziert werden kann. Im Normalfall ist dieses Attribut vom Typ long. Dieser Identifier muss mit einer entsprechenden Annotation markiert werden (javax.persistence.Id). Weiterhin kann die Generierungsstrategie einer neuen Id festgelegt werden. Dazu wird die Annotation javax.persistence.GeneratedValue benutzt.
Neben der Deklaration der Id kann jeder Spalte der entsprechende Spaltenname in der Datenbank zugeordnet werden. Das geht über javax.persistence.Colum. Diese Annotation ist optional. Ist ein Attribut nicht damit versehen, wird einfach der Attributname als Spaltenname benutzt.
Dies sind nur ein paar wenige Einstellungen für eine JavaBean. Für weiterführende Informationen kann die API zu Rate gezogen werden.
Objekt speichern

Die zentrale Klasse zum speichern und laden von Objekten ist javax.persistence.EntityManager. Eine Instanz kann über javax.persistence.EntityManagerFactory erstellt werden.

final EntityManagerFactory emf = Persistence.createEntityManagerFactory("hibernate");
final EntityManager em = emf.createEntityManager();

Nachdem der EntityManager verfügbar ist, wird eine javax.persistence.EntityTransaction benötigt. Diese Klasse ist zur Steuerung der Transaktionen verantwortlich. Will man ein Objekt in die Datenbank schreiben, braucht es eine offene Transaktion.

final EntityTransaction tx = em.getTransaction();
tx.begin();

Innerhalb dieser Transaktion kann nun ein Objekt persistiert werden.

final Person person = new Person();
person.setName("mrotzek");
person.setFirstName("michael");
em.persist(person);

Letztendlich muss die Transaktion noch geschlossen werden, um Änderungen wirklich in die Datenbank zu schreiben.

tx.commit();
em.close();
emf.close();

Objekt lesen

final EntityManagerFactory emf = Persistence.createEntityManagerFactory("hibernate");
final EntityManager em = emf.createEntityManager();
final EntityTransaction tx = em.getTransaction();
tx.begin();
final List persons = em.createQuery("select p from Person p").getResultList();
System.out.println(persons.size() + " person(s) found");
for (final Object p : persons) {
final Person lPerson = (Person) p;
System.out.println(lPerson .getName()+", "+lPerson .getFirstName()+" : "+lPerson .getId());
}
tx.commit();
em.close();
emf.close();

Referenzen

Java DB
Using Java DB in Desktop Applications
Working with Derby and Hibernate
Java Persistence with Hibernate
The Java Persistence API
Standardizing Java Persistence with the EJB3 Java Persistence API

December 18, 2006

Eclipse Plugin patchen

Bei der Arbeit mit dem openarchitectureware Framework entdeckte ich einen Bug im Plugin. Dieser Fehler war für mein Projekt so schwerwiegend, dass ich den Fehler sofort beheben musste - ich konnte nicht aufs nächste Update in ein paar Monaten warten. Also musste ich ersteinmal herausfinden, wie man ein Eclipse Plugin patcht.

Zuerst beschafft man sich den Quellcode per CVS. Zwar ist die CVS Struktur von Eclipse Projekten im ersten Augenblick gewöhnungsbedürftig, aber dann doch recht schlüssig. Mehr Information zum Checkout gibt es hier. Nachdem die Quellcodes heruntergeladen sind, kann der Fehler gefunden und beseitigt werden. Soweit so gut. Aber wie seine Eclipse Installation aktualisieren?

Für Eclipse Plugin Projekte gibt es immer eine plugin.xml im Stammverzeichnis. Nach dem öffnen dieser startet man im Reiter Overview unter Exporting den Export Wizard. Im Wizard können die benötigten Fragmente, die exportiert werden sollen, ausgewählt werden. Nach dem Export liegen die Fragmente als JAR Datei vor. Diese werden dann in den Eclipse Plugin Ordner (eclipse/plugins) kopiert (ggf. noch alte Versionen des Plugins löschen). Zu guter Letzt Eclipse neu starten, fertig ist der Patch des Plugins.

December 15, 2006

Neue Funktionen von Java 6

Anfang Dezember hat Sun Java 6 (Codename Mustang) veröffentlicht. Im Gegensatz zum Sprung von Java 1.4.2 auf Java 5 (Tiger) sind die Veränderungen zwischen Tiger und Mustang nicht so tiefgreifend. Trotzdem bietet das Mustang Release einige sinvolle Neuerungen.

Dazu gehört die intergrierte Web Service API, die die Erstellung eines solchen so einfach wie nie zuvor macht. Außerdem wurden einige Verbesserungen im Bereich Datenbankenzugriff vorgenommen. So wird JDBC 4.0 unterstützt. Daneben kommt Java 6 jetzt auch mit einer eigenen Datenbank (Java DB). Hier handelt es sich im wesentlichen um Apache Derby. Der Vorteil liegt darin, dass in einer Desktop Anwendung diese benutzt werden kann - es muss keine weitere Software eingebunden werden, um Daten persistent abzulegen.

Weiterhin soll die Performance bei Desktop Anwendungen verbessert worden sein, da einige Prüfungen nicht mehr zur Laufzeit sondern bereits beim Kompilieren durchgeführt werden. Auch das Look & Feel der Benutzeroberfläche (GUI) passt sich nun besser dem Betriebssystem an.

Ein sehr guter Überblick hier