Montag, 18. Mai 2009

UTF8 in Eclipse - OpenSource trotz Windows

Sollte der eine oder andere Leser planen, demnächst ein neues Projekt zu starten und dies eventuell sogar online zu stellen, habe ich hier einen kleinen Tipp. Wichtig ist es auch für Unternehmen, in denen Windows und Linux als Betriebssysteme für Entwicklungsrechner gemischt eingesetzt werden. Denn sollte man einmal eine eingecheckte Datei eines Kollegen bekommen und sich über Sonderzeichen wundern, wird das wohl an den unterschiedlichen Zeichensätzen liegen.

Um daher nicht nach der Hälfte des Projektes alle eingecheckten Dateien noch einmal anfassen zu müssen, empfiehlt sich in Eclipse folgende Einstellung:

"Windows - Preferences" -> "General - Text File Encoding" - Other: UTF-8.

Somit sollten zumindest alle Java-Dateien in UTF-8 gespeichert sein. Die .properties-Dateien jedoch sind weiterhin in LATIN-1 (ISO 8859-1) gespeichert. Wer darüber mehr lesen will, kann dies hier nachlesen:

http://www.thoughtsabout.net/blog/archives/000044.html

Freitag, 15. Mai 2009

Eclipse - Einblenden versteckter Dateien

Es passiert mir immer mal wieder, daß Eclipse interne Konfigurationsdateien anpasst, die für das Projekt benötigt werden. Da diese mit einem . als Dateinamen anfangen, werden sie jedoch im Package Explorer nicht angezeigt. Löscht man nun ein eingechecktes Projekt beispielsweise und checkt es später wieder aus in SVN oder anderen Versionsverwaltungstools, kann es passieren, daß das Projekt invalid ist oder weitere Konfiguration benötigt, die man bereits vorgenommen hatte und von der man davon ausging, sie wäre eingecheckt.

Um das zu verhindern, kann man im Package Explorer in der oberen rechten Ecke auf ein nach unten zeigendes Dreieck klicken. Dabei öffnet sich ein Kontextmenü, in dem man unter anderem die Filter editieren kann. In diesem Filterdialog muß der Haken bei .* resources. weggenommen werden. Dann sieht man wirklich alles, was man benötigt.

Montag, 11. Mai 2009

Shared persistence

Nachdem ich im Internet viel gesucht und nicht viel gefunden habe, habe ich mich dazu entschlossen, selbst einen kleinen Artikel zu folgendem Thema zu verfassen:

"shared persistence / jboss / jpa"
"multiple ejb3 modules sharing one persistence"

Die Anforderung ist relativ einfach erzählt. Man möchte:

  • eine mehrschichtige Anwendung entwickeln

  • möglichst alle Module einzeln austauschbar gestalten

  • auf einem Application Server deployen (in unserem Fall JBoss)

  • möglichst für alle Module nur einen Persistence Kontext definieren

  • die Java Persistence API (JPA) in Verbindung mit EJB3 verwenden, um keine harten Inserts und Selects mehr selbst pflegen zu müssen


Grundinstallation

Und wie sieht das ganze nun aus? Eine vollständige und funktionierende Installation von JDK wird hier vorausgesetzt. Als Datenbank setze ich hier PostgreSQL ein. Um eine andere Datenbank nutzen zu können, muß allerdings nur die persistence.xml angepasst werden. Dazu ändert man den dort eingestellten Dialect entsprechend ab. Eine funktionierende Installation eines AppServers, hier JBoss, wird ebenfalls benötigt, wobei JBoss in dem Fall ja nur entzippt werden muß. Nach der Installation des JBoss muß im server/default/lib - Verzeichnis eine JDBC-Treiberdatei, z.B. postgresql-8.3-603.jdbc3.jar, abgelegt werden.

Als nächstes legen wir eine Testdatenbank an. Dies passiert in postgreSQL über den pgAdmin III. Der Datenbank wird nun der Produktname gegeben, beispielsweise myproduct. Um nun dem JBoss Application Server zu ermöglichen, auf diese DB zugreifen zu können, muß im server/default/deploy - Verzeichnis eine sogenannte DataSource hinzugefügt werden. Diese verweist auf den gewählten Datenbankdialekt und kann wie folgt aussehen:

myproduct-ds.xml:

<?xml version="1.0" encoding="UTF-8"?>

<datasources>
<local-tx-datasource>
<jndi-name>myproductds</jndi-name>
<connection-url>
jdbc:postgresql://localhost:5432/myproduct
</connection-url>
<driver-class>org.postgresql.Driver</driver-class>
<user-name>postgres</user-name>
<password>postgres</password>

<metadata>
<type-mapping>PostgreSQL</type-mapping>
</metadata>
</local-tx-datasource>

</datasources>


Wird nun der Server gestartet und die erzeugte log-Datei geprüft, sollten keine Exceptions auftreten und man sollte in der Management Console unter http://localhost:8080/jmx-console die erzeugte Datenbankverbindung vorfinden. Alternativ kann man auch prüfen, ob in der Log-Datei ein Eintrag ähnlich diesem erfolgt:

[ConnectionFactoryBindingService] Bound ConnectionManager 'jboss.jca:service=ConnectionFactoryBinding,name=myproductdb' to JNDI name 'java:myproductdb'

Somit ist eine Datenbankverbindung verfügbar. Was man nun braucht, sind die einzelnen...

Projekte
In Eclipse ist es relativ einfach, sich folgende Projekte zu erstellen:


  • Ein Java enterprise archive Projekt (EAR), genannt myproduct

  • Ein oder mehrere EJB Projekte, als Beispiel sei genannt myproductEJB

  • Ein leeres Standard Java Project, genannt myproductPersistence



Man kann diese Projekte natürlich auch per Hand konfigurieren. Wichtig dabei sind die folgenden Punkte.

Das EAR Projekt muß eine META-INF/application.xml beinhalten. Diese solle ähnlich der folgenden aussehen...

application.xml:

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:application="http://java.sun.com/xml/ns/javaee/application_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/application_5.xsd"
id="Application_ID" version="5">
<display-name>myproduct</display-name>
<module>
<ejb>myproductEJB.jar</ejb>
</module>
<module>
<ejb>myproductPersistence.jar</ejb>
</module>
</application>


Der Inhalt des EJB Projektes beschränkt sich in unserem Beispiel auf eine Entity, deren Tabelle erzeugt werden soll. In der Praxis werden aber für die einzelnen, austauschbaren Module jeweils eigene EJB Projekte erzeugt und somit eigene ejbmodule.jar Dateien deployed. Die Testbean sieht wie folgt aus...

Person Entity:

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Person implements Serializable {

private static final long serialVersionUID = -3293858472L;

@Id
private long Id;
private String name;

public long getId() {
return Id;
}

public void setId(long id) {
Id = id;
}

public String getName() {
return name;
}

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

}


Wichtig hierbei sind die verwendeten Annotations @Entity und @Id. Diese sind völlig ausreichend, um die Tabelle durch Hibernate erzeugen zu lassen. Für die Vergabe der IDs sollte man natürlich von long-Variablen absehen und stattdessen besser UUID benutzen, aber das ist ein anderes Thema.

Zu guter Letzt bleibt noch das Standard Java Projekt, welches das wichtigste für dieses Beispiel ist. Dieses Projekt ist nicht zwingend ein JPA Projekt, wie es in Eclipse angeboten wird. Es reicht, darin einen Ordner META-INF mit einer persistence.xml zu erzeugen. Der Rest des Projektes, welches später als myproductPersistence.jar deployed wird und uns den Persistenzkontext liefert, kann leer bleiben. Und hier die...



persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
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">
<persistence-unit name="myproduct"
transaction-type="JTA">
<jta-data-source>
java:/myproductdb
</jta-data-source>
<jar-file>
myproductEJB.jar
</jar-file>
<properties>
<property name="hibernate.dialect"
value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.hbm2ddl.auto"
value="update"/>
</properties>
</persistence-unit>
</persistence>


Damit sind alle nötigen Schritte vollzogen, um die Tabelle erzeugen zu lassen. Für jedes Modul wird ein weiteres EJB Projekt mit eigenen Entity Beans erzeugt. Alle diese Projekte nutzen die gemeinsame Persistenz und werden durch Hibernate automatisch erkannt, solange man die einzelnen EJB Projekte als jar-file Einträge in der persistence.xml aufführt.

Wird nun die EAR Datei erzeugt und in das server/default/deploy - Verzeichnis des JBoss gelegt, sollte eine neue Tabelle namens Person in eurem Besitz sein. Dabei muss darauf geachtet werden, daß die EAR-Datei die Jar-Dateien myproductEJB.jar und myproductPersistence.jar beinhaltet.

Hinweis: Nutzt man JBoss 4.x, muß ein vorhandener Bug noch durch einen Workaround ausgebessert werden, indem man im Tag der persistence.xml als relativen Pfad angibt: ../myproductEJB.jar!

Sollten bei euch Fehler beim Testen auftreten, könnt ihr diese gerne hier loswerden in der Kommentarfunktion.

Viel Spaß beim Probieren!