Bean-Bean Mapping mit Dozer

Dozer ist eine kleine Open-Source Bibliothek (Apache-Lizenz) zum Mappen von JavaBeans auf JavaBeans. Motivationen gibt es genug — die Webseite zählt gleich einige Argumente auf:

  • A mapping framework is useful in a layered architecture where you are creating layers of abstraction by encapsulating changes to particular data objects vs. propagating these objects to other layers (i.e. external service data objects, domain objects, data transfer objects, internal service data objects). A mapping framework is ideal for using within Assembler type classes that are responsible for mapping from one data object to another.
  • For SOA/ESB systems, a side effect is the passing of domain objects between different systems. Typically, you won’t want internal domain objects exposed externally and won’t allow for external domain objects to bleed into your system.
  • Mapping between data objects has been traditionally addressed by hand coding value object assemblers (or converters) that copy data between the objects. Most programmers will develop some sort of custom mapping framework and spend countless hours and thousands of lines of code mapping to and from their many transfer objects.
  • A generic mapping framework solves these problems. Dozer is an open source mapping framework that is robust, generic, flexible, reusable, and configurable.
  • Data object mapping is an important part of layered service oriented architectures. Pick and choose the layers you use mapping carefully. Do not go overboard as there is maintenance and performance costs associated with mapping data objects between layers.

Basis des Mappings sind XML-Dokumente; im einfachsten Fall:

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://dozer.sourceforge.net http://dozer.sourceforge.net/schema/beanmapping.xsd">
  <mapping>
<class-a>d.e.i.n.p.a.k.e.t.TestObject</class-a>
<class-b>d.e.i.n.p.a.k.e.t.TestObjectPrime</class-b>
<field> <A>yourSourceFieldName</A> <B>yourDestinationFieldName</B> </field>
</mapping>
</mappings>

Angestoßen wird er über ein Mapping-Objekt, welches auch leicht von Spring injiziert werden kann:

Mapper mapper = new DozerBeanMapper();

DestinationObject destObject = mapper.map(sourceObject, DestinationObject.class);

oder

DestinationObject destObject = new DestinationObject();
mapper.map(sourceObject, destObject);

Interessant finde ich die JMX-Integration. Der Mapper gibt Statistik-Informationen etwa über die Anzahl gemappter Objekte.

Ähnliche Beiträge

3 Gedanken zu “Bean-Bean Mapping mit Dozer

  1. Hallo Christian,

    habe früher auch häufig Dozer eingesetzt, arbeite inzwischen aber an/mit einem alternativen Ansatz, der typsicheren Mapping-Code zur Compilezeit generiert. Dabei definiert man ein Interface mit Methoden mit den gewünschten Quell- und Zieltypen:


    @Mapper
    public interface MyMapper {

    @Mapping(source="yourSourceFieldName", target="yourDestinationFieldName")
    TestObjectPrime testObjectToTestObjectPrime(TestObject testObject);
    }

    MapStruct (so heißt der Code-Generator) erzeugt dann eine Implementierung dieses Interfaces, die mit einfachen Setter/Getter-Aufrufen das Mapping vornimmt.

    Vorteile sind in meinen Augen die Typsicherheit zur Compile-Zeit (wenn Attribute nicht gemappt werden können, gibt es einen Fehler zur Build- und nicht erst zur Laufzeit), Effizienz (keine Reflection etc.) und dass man keinerlei Bibliotheken zur Laufzeit benötigt. Dadurch dass man den generierten Code anschauen kann, sind die Mappings auch sehr einfach nachzuvollziehen, zu debuggen etc.

    Was hältst Du von diesem generierungsbasierten Ansatz?

    Viele Grüße,

    –Gunnar

  2. Ich bin auch kein Freund von XML und was typsicheres finde ich immer besser, auch zum Refactoring, das war ja lange bei Spring ein Problem. Code zu generieren ist auch Ok, aber zur Laufzeit finde ich das besser, nicht statisch vorher, das ist immer blöd im Build-Prozess, und man sieht ja auch bei Java, dass so was RMIC gar nicht mehr nötig ist.
    Perfekt wäre hier so was wie in Mapping-Builder, den könnte man noch relativ leicht in Dozer einbringen und könnte auch Basis für einen statischen Mapper sein. Ein bisschen so wie Google Guice.

    map(Klass1.class).to(Klass2.class).
    withAttribute(„longname“).to(„name“).
    withAttribute(„alter“).modifyValue( ageFromYearsToDateObject ).to(„age“).
    done();

    Allerdings sind die Namen hier doch wieder Strings, hier könnten Annotationen an einer speziellen Mapping-Klasse elegant helfen.

    Die Domain-Klassen selbst zu annotieren würde mir nicht gefallen, das gehört da nicht rein.

  3. <cite aber zur Laufzeit finde ich das besser, nicht statisch vorher, das ist immer blöd im Build-Prozess

    Hmm, hatte bis jetzt noch keine Schwierigkeiten mit diversen Generatoren (Antlr, JPA-Metamodell etc.). Wie Du schon sagst, verlierst Du mit Generierung zur Laufzeit einige der Vorteile eines Buildzeit-Generators:

    * Typsicherheit/Validierung: Du weißt zur Buildzeit ob die Mappings funktionieren oder nicht (Attributnamen, Typkonvertierungen)
    * Plain Java-Code, keine weiteren Bibliotheken zur Laufzeit benötigt
    * Einfach zu analysieren/debuggen: Wenn mal was nicht funktioniert wie erwartet, kannst Du den generierten Code einfach nachvollziehen und im Notfall auch von Hand nachbearbeiten

    Perfekt wäre hier so was wie in Mapping-Builder, den könnte man noch relativ leicht in Dozer einbringen

    Es gibt ein API dieser Art in Dozer, aber halt ohne compile-time Typsicherheit.

    Die Domain-Klassen selbst zu annotieren würde mir nicht gefallen, das gehört da nicht rein.

    Sehe ich auch so 🙂

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert