Archive for the 'FRF' category

FRF #02 – Morphia und MongoDB

Nov 07 2011 Published by under Development, eclipse, FRF, Java

Mit etwas Verspätung kommt nun der 2. Teil des FRF indem ich mich mit Morphia und MongoDB auseinander gesetzt habe. Die Einarbeitung in beide Themen hat doch mehr Zeit in Anspruch genommen als vermutet. Zudem hatte ich zu Beginn ein Paar Probleme, bis mein Maven und die MongoDB liefen (OSX spezifischer Natur).

Ziel

Das Ergebnis dieses Parts wird es sein, dass CRUD Prinzip mit Hilfe von Morphia in der MongoDB abzubilden. Dazu verwenden wir DAOs und POJOs, welche mit Morphia Annotationen versehen werden.

Das Wichtigste vorweg, MongoDB sollte gestartet sein. Dazu einfach den MongoDB Daemon starten (mongod).

Vorraussetzungen

Maven2 oder Maven3 installiert und konfiguriert. Des Weiteren sollte das m2eclipse Plugin installiert sein. Man sollte wissen wie man Maven einsetzt. Ich werde auf bestimmte Aspekte im Zusammenhang mit diesem Tutorial eingehen, aber es wird keine Einführung in Maven sein.

Ready, Steady, Go

Create & Configuring our Maven Project (Ready)

Zu Beginn sollte ein neues Maven Projekt erstellt werden. Als Archtype sollte maven-archtype-sample gewählt werden. Danach nur noch bei Artifact Id den Namen des Projektes eintragen und Projekt erstellen. Unter Umständen kann es sein, dass es als Java 1.5 Projekt angelegt wird, falls dies so sein sollte, einfach folgenden Absatz in die POM kopieren

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>

und dann Rechtsklick auf das Projekt -> Maven -> Update Project Configuration… Nun sollten etwaige Fehlermeldungen verschwinden. Wenn wir uns schon in der POM aufhalten, dann passen wir gleich die JUnit Version an und zwar nehmen wir die Aktuellste – 4.10. Ansonsten benötigen wir nur noch die Dependencies für Morphia und den MongoDB Java Driver.

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.morphia</groupId>
<artifactId>morphia</artifactId>
<version>0.99</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.6.5</version>
</dependency>
<dependency>
<groupId>com.google.code.morphia</groupId>
<artifactId>morphia-validation</artifactId>
<version>0.99</version>
</dependency>
</dependencies>

Damit Maven die Morphia Dependencies findet muss noch das Morphia Repository hinzugefügt werden.

<repositories>
<repository>
<id>morphia</id>
<url>http://morphia.googlecode.com/svn/mavenrepo/</url>
</repository>
</repositories>

POJOs & DAOs (Steady)

Da das grundlegende Maven-Setup nun steht kann es endlich losgehen. Wir benötigen 2 POJOs, POJO A referenziert POJO B, eine Singelton für den DB Zugriff, entsprechende DAOs.

The Singelton

Das Singelton-Pattern sollte jedem geläufig sein. Es bietet sich gerade dazu an für den Zugriff auf die MongoDB. Hierfür erstellen wir eine neue Klasse mit einem privaten Konstruktor in dem der Verbindungsaufbau zur DB abläuft. Ich nenne die Klasse MongoConnectionManager.java.

public class MongoConnectionManager {

private static final MongoConnectionManager INSTANCE = new MongoConnectionManager();
private final Datastore db;
public static final String DB_NAME = "personDB";
private MongoConnectionManager() {
try {
Mongo m = new Mongo("localhost", 27017);
db = new Morphia().map(Person.class).map(Company.class).createDatastore(m, DB_NAME);
db.ensureIndexes();
} catch (Exception e) {
throw new RuntimeException("Error initializing mongo db", e);
}
}

public static MongoConnectionManager getInstance() {
return INSTANCE;
}

public Datastore getDb() {
return db;
}
}

Was passiert hier? Wir stellen eine Verbindung auf die MongoDB mit Hilfe des MongoDB Java Drivers her. Als Parameter wird der Host und der entsprechende Port mitgeben.

Mongo m = new Mongo("localhost", 27017);

Die folgende Zeilen sind Morphia Spezifisch. Es werden unsere Entities (POJOs) registriert und die Tabelle (hier Datastore) in unserer Datenbank erstellt. Die Methode ensureIndexes(); erstellt synchron die Indexes und die gekapselten Collections für unsere Entities.

db = new Morphia().map(Person.class).map(Company.class).createDatastore(m, DB_NAME);
db.ensureIndexes();

The POJOs

In diesem Beispiel verwende ich 2 POJO Klassen, Person und Company. Jeder Person ist eine Company zugeordnet.

@Entity(value="persons", noClassnameStored=true)
public class Person {
@Id
private ObjectId id;
private String name;
private String surename;
private String Email;

@Reference
private Company company;

//Gettter/Setter
...
  • @Entity wird benötigt um mitzuteilen, dass diese Klasse als Entität verwendet werden soll. Morphia persistiert diese Klasse dann dementsprechend.
  • @Id wird im Zusammenhang mit der Klasse ObjectId verwendet. @Id sagt aus, dass dieses Attribut vom Typ ObjectId, bei fehlerfreien persistieren die entsprechende Id von der MongoDB zugewiesen bekommt.
  • @Reference stellt die Verbindung/Verknüpfung mit der Klasse Company dar.

Die wichtigsten Annotationen sind @Entity und @Id, die vorhanden sein müssen.


@Entity(value="companies", noClassnameStored=true)
public class Company {

@Id
private ObjectId id;
private String name;
private Long noEmployees;

//Getter/Setter
...

Die Klasse Company benötigt keine weiteren Morphia Annotationen außer @Enity und @Id.

The DAOs

Data Access Objekt was ist das? Hier lesen!

Use a Data Access Object (DAO) to abstract and encapsulate all access to the data source. The DAO manages the connection with the data source to obtain and store data.

Ich baue meine DAOs immer wie folgt auf, einmal das Interface EntityDAO und die Implementierung dazu EntityDAOImpl. In das Interface kommen die gewünschten Methoden zum Suchen, Erstellen, Löschen, … von Datensätzen.

public interface PersonDAO {
public Key<Person> save(Person person);
public Person findPerson(ObjectId personId);
public List<Person> findAllPersons();
public List<Person> findPersonsByCompany(Company company);
}

Nun erben wir u.a. von unseren oben erstellten Interface und programmieren unsere Methoden aus.

public class PersonDAOImpl extends BasicDAO<Person, ObjectId> implements PersonDAO {
public PersonDAOImpl(){
super(Person.class, MongoConnectionManager.getInstance().getDb());
}

@Override
public Person findPerson(ObjectId personId) {
return get(personId);
}

@Override
public List<Person> findAllPersons() {
return find().asList();
}

@Override
public List<Person> findPersonsByCompany(Company company) {
return createQuery().field("company").equal(company).asList();
}
}

Das war schon die ganze Zauberei. Nun sind wir soweit um unsere Anwendung zu testen.

Creating & Running JUnit Tests (Go)

Wir verwenden JUnit Tests um unsere Anwendung auf Funktionalität zu testen. Ist besser, sauberer und vor allem professioneller als eine Main Klasse zuschreiben und mit System.out.println(); zu arbeiten.

Dafür legen wir im Ordner src/test/java unterhalb des Packages eine neue JUnit Klasse an. Ich hab meine PersonDAOTest.java genannt.

Ich habe 2 Tests geschrieben, einen der prüft ob ein Datensatz persistiert wurde, der Andere versucht einen Datensatz zu finden.

Wichtig ist, dass die Companies bereits existieren (persistiert sind) wenn sie den Personen zugeordnet werden. Falls dies nicht der Fall ist, bricht der Test mit einer MappingException ab! Siehe Kommentar im Quellcode.


public class PersonDAOTest {

private PersonDAO personDAO;
private BasicDAO<Company, ObjectId> companyDAO;

private final Company ibm = new Company().withName("IBM").withNumberOfEmployees(Long.valueOf(426751));
private final Company samsung = new Company().withName("Samsung").withNumberOfEmployees(Long.valueOf(290000));

@Before
public void before() {
Util.drop();

personDAO = new PersonDAOImpl();
companyDAO = new BasicDAO<Company, ObjectId>(Company.class, MongoConnectionManager.getInstance().getDb());

/**
* "Pre" store the company, so that they will haven an objectId, otherwise it will throw new Mapping Exception
* see here for more information: http://code.google.com/p/morphia/issues/detail?id=315
*/

ArrayList<Company> arrList = new ArrayList<Company>();
arrList.add(ibm);
arrList.add(samsung);

for (Company c : arrList) {
companyDAO.save(c);
}
}

private Person createPerson(){
Person person = new Person();
person.setSurename("Sue");
person.setName("Walker");
person.setEmail("sue.walker@ibm.com");
person.withCompany(ibm);
personDAO.save(person);
return person;
}

@Test
public void testPersistance() {
Person person = createPerson();

assertNotNull("Saved Person Id", person.getId());
person = personDAO.findPerson(person.getId());
assertNotNull("Person retrieved", person);
}

@Test
public void query() {
createPerson();
List<Person> persons = personDAO.findPersonsByCompany(ibm);
assertTrue("Returned one Person" , persons.size() == 1);
persons = personDAO.findPersonsByCompany(samsung);
assertTrue("Nothing should returned" , persons.size() == 0);
}
}

Sobald die JUnit Klasse fertig gestellt wurde kann man mit

mvn test

die Tests ausführen.

Ich denke die Klasse ist recht selbsterklärend, falls doch Erklärungsbedarf  bestehen sollte, schreibts in die Kommentare ich werde es mit in den Artikel einfließen lassen.

Mit einem Administrationstool wie z.B. MongoHub (OSX) kann mit Hilfe einer grafischen Oberfläche nachgeschaut werden ob etwas persistiert wurde.

Comming Next …

Im nächsten Part versuche ich dem ganzen eine Oberfläche zu verpassen. Das Framework wird Vaadin sein. Es soll dann möglich sein neue Einträge hinzuzufügen, zu modifizieren und zu löschen mit Hilfe einer UI. Dort kommt dann der Tomcat noch mit ins Spiel.

Last But Not Least …

… habe ich noch ein paar Interessante Ressourcen zum Thema MongoDB und Morphia gefunden. Diese Links dienten als Quellen und Anhaltspunkte für diesen Artikel:
http://www.mongodb.org/display/DOCS/Quickstart
http://www.mongodb.org/display/DOCS/Admin+UIs
http://www.mongodb.org/display/DOCS/SQL+to+Mongo+Mapping+Chart
http://code.google.com/p/morphia/wiki/QuickStart
http://sleeplessinslc.blogspot.com/2010/10/mongodb-with-morphia-example.html
http://mongohub.todayclose.com/download

Das Projekt kann gezippt heruntergeladen werden. GitHub folgt!

Projekt Download

Version 0.2

2 responses so far

FRF #01 – Getting Started

Okt 05 2011 Published by under Development, eclipse, FRF, Java

So nun ist es soweit der erste FRF geht an den Start.

Einleitung

Ziel ist es eine Web 2.0-fähige Applikation zu bauen, die den Einsatz der genannten Technologien exemplarisch darstellen. Hierfür wird Vaadin für die UI-Bibliotheken, Mongo für die Datenbank(schicht) und Morphia für die Persistenz(schicht) verwendet.

Warum genau diese Technologien?

Ich interessiere mich seit längerem für die NoSQL Datenbanken und habe das ganze leicht verfolgt, aber nie wirklich ausgetestet. Durch diesen Artikel auf IT-Republik bin ich auf Vaadin gestoßen. Habe mir dann mal die Website des Projektes angeschaut, etwas gestöbert und hatte das verlangen es einmal auszuprobieren. Morphia kam dann durch die Suche nach einer JPA-like-Lib für MongoDB hinzu. Um die Zusammenarbeit der einzelnen Tools aufzuzeigen wird nun dieser Prototyp entwickelt.

Bestandsaufnahme

Als erstes muss eine Bestandsaufnahme der benötigten Tools & Libraries durchgeführt werden.

Es wird benötigt:

Nachdem alles runtergeladen und (je nachdem) installiert/entpackt wurde geht es an die Einrichtung der Tools.

Einrichtung der Tools

Für den Tomcat7 habe ich ein recht aktuelle und ausführliche Anleitung gefunden, mit Hilfe der ich ihn eingerichtet habe.

Vaadin besitzt auch ein eclipse PlugIn, in welchem man direkt die aktuellesten Vaadin Libs herunterladen kann.

Bei MongoDB wird es ein wenig interessanter, es existier ein PlugIn zur Verwaltung in eclipse und auf der MongoDB Seite sind die Java Treiber vorhanden. Im Moment bin ich noch ein wenig unschlüssig, ob ich auf DataNucleus oder Morphia setzen werde. Aktuell tendier ich eher zu Morphia.

Ein guter Getting Started Artikel zu MongoDB findet ihr auf der MongoDB Seite.

What’s next?

Im nächsten Artikel geht es dann um etwas an das Eingemachte, es wird via Morphia auf die MongoDB zugegriffen und Daten persistiert.

Ich möchte das Tutorium langsam von unten aufbauen, sprich von der DB Schicht hoch zum UI. Slow but steady.

Hier lang zu FRF #02 – Morphia und MongoDB.

Version: 0.4

4 responses so far

FRF #00 – Was ist den FRF?

Sep 28 2011 Published by under Development, FRF, Web Development

Ich möchte nun hier auf meinem Blog ein neues Projekt beginnen. Während meiner Zeit als Praktikant habe ich oftmals den Freitag genutzt mich mit neuen Themen, die mich interessieren zu beschäftigen. Dies wurde spaßiger Weise Freaky Research Friday, kurz FRF genannt, da ich zum damaligen Zeitpunkt in Researchbereich einer Firma tätig war.

Nun möchte ich versuchen dies weiterzuführen. Meine Idee ist es kleine Prototypen mit den entsprechenden Technologien zu bauen und das ganze als Tutorial aufzuziehen und eine Schritt für Schritt Anleitung zu erstellen und versuche jeden Freitag ein Post hierzu im Blog zu verfassen.

Habe eine Seite in der Navigation erstellt, in welcher Ihr einen Überblick über die vorhandenen Serien bzw. Artikel habt.

Themen werden sich größtenteils im Bereich der Softwareentwicklung bewegen, aber ab und zu einen Blick abseits zu riskieren kann nie schaden. :D

In diesem Sinne FRF!

One response so far