Vortrag downloaden

Werbung
WER ERZÄHLT DIE NÄCHSTEN 55+ MINUTEN
ETWAS?
Gerrit Brehmer, Karlsruhe
Auf der Arbeit: Software-Entwickler/Architekt ( / Projektleiter) bei der
inovex GmbH
In der Freizeit: Smart Home
BEAN-MAPPING: EINSATZ
Wann müssen Beans gemappt werden?
Entities zu DTOs
interne zu generierten Klassen (JAXB etc.)
zur Einbindung externer Dienste
standardisierten Schnittstellen
eigenen REST/SOAP Schnittstellen
Allgemein Austauschformate zwischen Schichten und Applikationen
BEAN MAPPING: UMSETZUNG
Was benutzen wir dafür bisher?
von Hand geschriebener Mapping-Code
typsicher, schnell
fehleranfällig, aufwendig
Dozer
wenig Aufwand, Rekursives Auto-Mapping
Reflection & XML: langsam
Apache Commons BeanUtils
wenig Aufwand
Reflection, nur nicht komplexe Properties, langsam
GEHT ES BESSER?
Wunschliste
schnell
typsicher
wenig Aufwand
automatisches Mapping
Null-Prüfungen
Konvertierungen von "ähnlichen" Typen
Fehlendes Mapping schnell erkennen
nachvollziehbar
MAPSTRUCT
mapstruct.org / github.com/mapstruct
OpenSource (Lizenz: Apache 2.0)
Initator & Maintainer: Gunnar Morling (RedHat,
Hibernate Team)
Aktuelle Version: 1.0.0.CR2 (Final Release in Kürze)
Weiterentwicklung/Support
mehrere Stamm-Entwickler
schnelles Feedback
kontinuierliche Weiterentwicklung
WIE FUNKTIONIERT MAPSTRUCT
Annotation Processor
Verarbeitet Annotations am eigenen Quellcode
siehe andere bekannte Libs: JPA MetaModel, Lombok, QueryDSL
z.B. mit Hilfe maven-processor-plugin
Generiert Java Quellcode
Zusammenspiel verschiedener FreeMarker Templates
DEMO
INTEGRATION IN ECLIPSE #1
MapStruct eclipse Plugin
noch work-in-progress
Hauptsächlich noch fehlende Features, keine Bugs
Code Completion: JAXB Listen, Nested Properties
Quick Fix: Collection Mappings
INTEGRATION IN ECLIPSE #2
m2e APT Plugin
Aktivierung nicht
vergessen!
Inkompatibilitäten mit
Eclipse Compiler pre Mars
(ab 1.0.0.CR2)
Manchmal 'Clean Project'
notwendig
Maven: build-helpermaven-plugin
automatische Build-Path
Anpassung
GENERIERTE ABHÄNGIGKEITEN
Zu mappende Klassen sind ebenfalls generiert (z.B. JAXB per Schema)
Resultat: Compiler Fehler bei Generierung MapStruct Mapper
Lösung:
Weiteres Maven Modul/Artefakt für abhängige Klassen
Maven Plugins in unterschiedliche Phasen verlegen
AUTOMAPPING #1
Primitive & Wrapper-Typen
Datums-Typen
Joda / Java 8 DateTime API Klassen
Date
Calendar
dest.setLocalDateTime(java.time.LocalDateTime.ofInstant(
src.getDate().toInstant(),
java.time.ZoneId.systemDefault())
);
AUTOMAPPING #2
Collection- & Array-Typen
Mapping nicht nur per Setter
Adder (ohne Null Prüfung!)
Getter (ohne Null Prüfung!)
Setter
Mapping-Methoden zwischen Collection/Array Typen müssen nicht
definiert werden
Maps
JAXB
JAXBElement
XMLGregorianCalendar
VERSCHACHTELTE MAPPINGS
@Mapping(source = "source.nested.param" target = "param")
public Target toTarget(Source source);
inkl. Null-Prüfungen
Bisher nur für Quell-Parameter
Feature Request für Ziel-Parameter vorhanden
MAPPING VON ENUM-TYPEN
@Mapping(source = "FINAL", target = "LAST")
TargetEnum map(SourceEnum enum);
String-Match oder explizites Mapping
fehlende Mappings zu Zielwerten werden signalisiert
MAPPING DEFAULTS UND KONSTANTEN
@Mapping(source = "src", target = "dest", defaultValue = "-1")
Default-Werte als Ersatz bei null-Werten in QuellInstanzen
@Mapping(constant = "CONST", target = "dest")
String-Konstanten, auf die bei Bedarf StandardConverter oder andere Mapping Methoden
angewendet werden
QUALIFIER
Unterscheidung bei identischem Quell- und Zieltyp
Ohne Qualifier Zuordnung nicht eindeutig = Compiler Fehler
spezielle Mappings für ansonsten automatisch generierten MappingCode
@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Marker {
}
@Marker
public String specialStringMapping(String source) {
...
}
@Mapping(source = "src", target = "dest", qualifiedBy = Marker.class)
public Target map(Source source);
BEAN-FACTORIES
Als Ersatz für Standard-Konstruktor
Selbst geschriebene Factory-Methoden (leere Parameterliste,
Rückgabetyp = Zieltyp)
Generische Factories möglich
Verwendung bereits vorhandener (z.B. ObjectFactory von JAXB)
@Mapper(uses = CustomFactory.class)
public interface Mapper {
...
}
public class CustomFactory {
public TargetDto createTargetDto() {
....
}
public <T extends AbstractEntity> T createEntity(@TargetType Class<T> entityClass) {
...
}
}
MAPPING PER EXPRESSION
@Mapping(
expression = "java(java.util.UUID.randomUUID().toString())",
target = "uniqueId")
TargetDto mapTo(SourceEntity source);
Aktuell nur Unterstützung für Java Code
echte Skriptsprachen für zukünftige Versionen geplant
Notwendige Imports können am @Mapper konfiguriert werden
UNTERSCHIEDLICHE QUELLEN
@Mappings({
@Mapping(source = "param1.src", target = "dest1"),
@Mapping(source = "param2.src", target = "dest2")
})
Target map(SourceOne param1, SourceTwo param2);
Aber: Sind nur im Custom-Code / Expressions wiedervendbar
MAPPING ALS UPDATE
@Mapper
public interface Mapper {
Target update(Source src, @MappingTarget Target target);
}
mehrere Quellen möglich
Return Type: voidoder identisch mit Ziel-Typ
BIDIREKTIONALES MAPPING
@Mapper
public interface Mapper {
@Mapping(source = "special", target = "destParam")
Dto map(Entity source);
@InheritInverseConfiguration
Entity map(Dto source);
}
Ausnahmen
geschachtelte Quell-Property
Konstanten
Expressions
CUSTOM MAPPER #1
@Mapper(uses = CustomMapper.class)
public interface Mapper {
...
}
public class CustomMapper {
public TargetDto toTarget(Source source) {
....
}
}
Mapper Klassen
notwendig, wenn automatische Mapping-Methoden nicht
generiert werden können
Einzelnes Element gemappt auf Liste
Liste mit Inhalten aus verschiedenen Quellen
Liste komplexer Elemente gemappt auf Liste primitiver
Werte
CUSTOM MAPPER #2
@Mapper(uses = CustomMapper.class)
public interface Mapper {
...
}
@Mapper
public abstract class CustomMapper {
public TargetDto toTarget(Source source) {
....
}
@Mappings(...)
public abstract NestingTargetDto toNestingTarget(NestingSource source);
}
Abstrakte Klassen
Ähnlich wie Mapper per Interface
abstrakte Methoden werden generiert
public Methoden enthalten den nicht generierbaren Mapper-Code
KOMPONENTENMODELLE
Konfiguration pro Mapper
Mehrere werden bereits unterstützt
Spring (@Component, @Autowired)
CDI (@ApplicationScoped, @Inject)
JSR 330 (@Named, @Inject)
Alle miteinander verbundenen Mapper müssen dasselbe
Komponentenmodell verwenden
Keine Abhängigkeit zu MapStruct zur Laufzeit
@Mapper(componentModel = "spring")
public interface Mapper {
...
}
@Component
public class MapperImpl {
...
}
KONFIGURATION
@MapperConfig(componentModel = ..., uses = ..., ...)
public interface DefaultMapperConfig {
...
}
@Mapper(config = "DefaultMapperConfig")
public interface Mapper {
...
}
MAPPING ASPEKTE #1
Decorator
angepasster Code für ausgewählte Methoden
Aber: greift nur, wenn Methode vom eigenen Code oder anderen
Mapper-Klassen aufgerufen wird
@Mapper
@DecoratedWith(MapperDecorator.class)
public interface Mapper {
...
}
public abstract class MapperDecorator implements Mapper {
private final Mapper delegate;
public MapperDecorator(Mapper delegate) {
this.delegate = delegate;
}
@Override
public Target toTarget(Source source) {
Target target = delegate.toTarget(source);
// ... custom mapping
...
}
MAPPING ASPEKTE #2
@BeforeMappingund @AfterMapping
Matching auf Mapping-Methoden anhand Quell- und Zieltypen
@Mapper
public abstract class Mapper {
@BeforeMapping
void flushEntity(AbstractEntity entity) {
// flush entity to init all fields
}
@AfterMapping
void manuelUpdateMissing(Source src, @MappingTarget Target target) {
// e.g. as alternative for expressions / custom mapper
}
}
EXCEPTIONHANDLING
Checked Exceptions
nur wenn an Mapping Methode deklariert
ansonsten gewrapped in RuntimeException
RuntimeExceptions ohne Anpassung
FAZIT & AUSBLICK
MapStruct ist ready-to-use
umfangreiche Dokumentation
lebendige Community
keine Bugs, die den Einsatz verhndern
Große Funktionsauswahl: Viele Wege führen zum Ziel!
So viel wie möglich automatisch mappen
Damit verbundene Checks durch MapStruct minimieren Mapping
Fehler
Das Feature-Set ist noch nicht komplett: Weitere nützliche Features
werden sicher folgen!
VIELEN DANK FÜR EURE AUFMERKSAMKEIT!
Herunterladen