= Dozer Component
:doctitle: Dozer
:shortname: dozer
:artifactid: camel-dozer
:description: Map between Java beans using the Dozer mapping library.
:since: 2.15
:supportlevel: Stable
:component-header: Only producer is supported
//Manually maintained attributes
:camel-spring-boot-name: dozer

*Since Camel {since}*

*{component-header}*

The Dozer component provides the ability to map between Java beans
using the http://camel.apache.org/dozer-type-conversion.html[Dozer]
mapping framework.  Camel also supports the ability
to trigger Dozer mappings
http://camel.apache.org/dozer-type-conversion.html[as a type converter].
 The primary differences between using a Dozer endpoint and a Dozer
converter are:

* The ability to manage Dozer mapping configuration on a per-endpoint
basis vs. global configuration via the converter registry.
* A Dozer endpoint can be configured to marshal/unmarshal input and
output data using Camel data formats to support a single, any-to-any
transformation endpoint
* The Dozer component allows for fine-grained integration and extension
of Dozer to support additional functionality (e.g. mapping literal
values, using expressions for mappings, etc.).

In order to use the Dozer component, Maven users will need to add the
following dependency to their `pom.xml`:

[source,xml]
------------------------------------------------------------
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-dozer</artifactId>
    <version>x.x.x</version>
    <!-- use the same version as your Camel core version -->
</dependency>
------------------------------------------------------------

== URI format

The Dozer component only supports producer endpoints.

--------------------------
dozer:endpointId[?options]
--------------------------

Where *endpointId* is a name used to uniquely identify the Dozer
endpoint configuration. 

An example Dozer endpoint URI:

[source,java]
---------------------------------------------------------------------------------------
from("direct:orderInput").
  to("dozer:transformOrder?mappingFile=orderMapping.xml&targetModel=example.XYZOrder").
  to("direct:orderOutput");
---------------------------------------------------------------------------------------

== Options

// component-configure options: START

// component-configure options: END

// component options: START
include::partial$component-configure-options.adoc[]
include::partial$component-endpoint-options.adoc[]
// component options: END

// endpoint options: START

// endpoint options: END


== Using Data Formats with Dozer

Dozer does not support non-Java sources and targets for mappings, so it
cannot, for example, map an XML document to a Java object on its own.
 Luckily, Camel has extensive support for marshalling between Java and a
wide variety of formats using
http://camel.apache.org/data-format.html[data formats].  The Dozer
component takes advantage of this support by allowing you to specify
that input and output data should be passed through a data format prior
to processing via Dozer.  You can always do this on your own outside the
call to Dozer, but supporting it directly in the Dozer component allows
you to use a single endpoints to configure any-to-any transformation
within Camel.

As an example, let's say you wanted to map between an XML data structure
and a JSON data structure using the Dozer component.  If you had the
following data formats defined in a Camel Context:

[source,xml]
-----------------------------------------------
<dataFormats>
  <json library="Jackson" id="myjson"/>
  <jaxb contextPath="org.example" id="myjaxb"/>
</dataFormats>
-----------------------------------------------

You could then configure a Dozer endpoint to unmarshal the input XML
using a JAXB data format and marshal the mapping output using Jackson.

[source,xml]
----------------------------------------------------------------------------------------------------------
<endpoint uri="dozer:xml2json?marshalId=myjson&amp;unmarshalId=myjaxb&amp;targetModel=org.example.Order"/>
----------------------------------------------------------------------------------------------------------

== Configuring Dozer

All Dozer endpoints require a Dozer mapping configuration file which
defines mappings between source and target objects.  The component will
default to a location of META-INF/dozerBeanMapping.xml if the
mappingFile or mappingConfiguration options are not specified on an
endpoint.  If you need to supply multiple mapping configuration files
for a single endpoint or specify additional configuration options (e.g.
event listeners, custom converters, etc.), then you can use an instance
of `org.apache.camel.converter.dozer.DozerBeanMapperConfiguration`.

[source,xml]
------------------------------------------------------------------------------------------
<bean id="mapper" class="org.apache.camel.converter.dozer.DozerBeanMapperConfiguration">  
  <property name="mappingFiles">
    <list>
      <value>mapping1.xml</value>
      <value>mapping2.xml</value>
    </list>
  </property>
</bean>
------------------------------------------------------------------------------------------

== Mapping Extensions

The Dozer component implements a number of extensions to the Dozer
mapping framework as custom converters.  These converters implement
mapping functions that are not supported directly by Dozer itself.

=== Variable Mappings

Variable mappings allow you to map the value of a variable definition
within a Dozer configuration into a target field instead of using the
value of a source field.  This is equivalent to constant mapping in
other mapping frameworks, where can you assign a literal value to a
target field.  To use a variable mapping, simply define a variable
within your mapping configuration and then map from the VariableMapper
class into your target field of choice:

[source,xml]
--------------------------------------------------------------------------------------------------------
<mappings xmlns="http://dozermapper.github.io/schema/bean-mapping"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping http://dozermapper.github.io/schema/bean-mapping.xsd">
  <configuration>
    <variables>
      <variable name="CUST_ID">ACME-SALES</variable>
    </variables>
  </configuration>
  <mapping>
    <class-a>org.apache.camel.component.dozer.VariableMapper</class-a>
    <class-b>org.example.Order</class-b>
    <field custom-converter-id="_variableMapping" custom-converter-param="${CUST_ID}">
      <a>literal</a>
      <b>custId</b>
    </field>
  </mapping>
</mappings>
--------------------------------------------------------------------------------------------------------

=== Custom Mappings

Custom mappings allow you to define your own logic for how a source
field is mapped to a target field.  They are similar in function to
Dozer customer converters, with two notable differences:

* You can have multiple converter methods in a single class with custom
mappings.
* There is no requirement to implement a Dozer-specific interface with
custom mappings.

A custom mapping is declared by using the built-in '_customMapping'
converter in your mapping configuration.  The parameter to this
converter has the following syntax:

--------------------------
[class-name][,method-name]
--------------------------

Method name is optional - the Dozer component will search for a method
that matches the input and output types required for a mapping.  An
example custom mapping and configuration are provided below.

[source,java]
--------------------------------------------------
public class CustomMapper {
    // All customer ids must be wrapped in "[ ]"
    public Object mapCustomer(String customerId) {
        return "[" + customerId + "]";
    }
} 
--------------------------------------------------

[source,xml]
--------------------------------------------------------------------------------------------------------
<mappings xmlns="http://dozermapper.github.io/schema/bean-mapping"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping http://dozermapper.github.io/schema/bean-mapping.xsd">
  <mapping>
    <class-a>org.example.A</class-a>
    <class-b>org.example.B</class-b>
    <field custom-converter-id="_customMapping" 
        custom-converter-param="org.example.CustomMapper,mapCustomer">
      <a>header.customerNum</a>
      <b>custId</b>
    </field>
  </mapping>
</mappings>
--------------------------------------------------------------------------------------------------------

=== Expression Mappings

Expression mappings allow you to use the powerful
http://camel.apache.org/languages.html[language] capabilities of Camel
to evaluate an expression and assign the result to a target field in a
mapping.  Any language that Camel supports can be used in an expression
mapping.  Basic examples of expressions include the ability to map a
Camel message header or exchange property to a target field or to
concatenate multiple source fields into a target field.  The syntax of a
mapping expression is:

[source,shell]
----------------------- 
[language]:[expression]
-----------------------

An example of mapping a message header into a target field:

[source,xml]
--------------------------------------------------------------------------------------------------------------
<mappings xmlns="http://dozermapper.github.io/schema/bean-mapping"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping http://dozermapper.github.io/schema/bean-mapping.xsd">
  <mapping>
    <class-a>org.apache.camel.component.dozer.ExpressionMapper</class-a>
    <class-b>org.example.B</class-b>
    <field custom-converter-id="_expressionMapping" custom-converter-param="simple:${header.customerNumber}">
      <a>expression</a>
      <b>custId</b>
    </field>
  </mapping>
</mappings>
--------------------------------------------------------------------------------------------------------------

Note that any properties within your expression must be escaped with "\"
to prevent an error when Dozer attempts to resolve variable values
defined using the EL.

== Dozer Type Conversion

WARNING: The dozer type conversion is deprecated. Do not use.

https://github.com/DozerMapper/dozer/blob/master/docs/asciidoc/about/about.adoc[Dozer] is a fast
and flexible framework for mapping back and forth between Java Beans.
Coupled with Camel's automatic type conversion, it's a formidable tool
for dealing object to object mapping headaches that crop up in
enterprise integration projects.

To explain how Dozer can be used within Camel we'll use the following
example of a simple Customer Support Service. The initial version of the
Service defined a 'Customer' object used with a very flat structure.

*Legacy Customer Service Class*

[source,java]
-----------------------------------------------------------------------------------
public class Customer {
    private String firstName;
    private String lastName;
    private String street;
    private String zip;

    public Customer() {}

    public Customer(String firstName, String lastName, String zip, String street) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.zip = zip;
        this.street = street;
    }

    public String getFirstName() {
        return firstName;
    }

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

    ... getters and setters for each field
-----------------------------------------------------------------------------------

In the next version it was decided to structure the data better in the
model by moving the address data into its own type, with the resulting
domain object ending up looking like the below.

*Next Gen Customer object*

[source,java]
-------------------------------------------------------------------------
public class Customer {
    private String firstName;
    private String lastName;
    private Address address;

    public Customer() {}

    public Customer(String firstName, String lastName, Address address) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.address = address;
    }
    ....


public class Address {
    private String zipCode;
    private String streetName;

    public Address() {}

    public Address(String zipCode, String streetName) {
        this.zipCode = zipCode;
        this.streetName = streetName;
    }
-------------------------------------------------------------------------

Much nicer! But as often occurs, the previous version of the service,
with the old flat 'Customer' object, was in production with a client and
the project must support the legacy interface. To support both versions,
we must add a mechanism to convert between the old Customer service type
and the new Customer domain type and back again. It would be a simple
matter to write a custom converter class to map between them, but this
may not be the only service/domain inconsistency and these tedious and
error prone custom mappings could quickly start to add up, and bugs with
them.

To a large extent the two objects share an identical structure, with only
the address representation being different. It would be very helpful if
there were a practical way to automate this kind of mapping, such
that the similar properties could get mapped automatically and only the
inconsistencies requiring custom mapping.

This is where Dozer comes in; it uses reflection to map data between two
bean types using a set of simple mapping rules. Where no rule is
specified, Dozer will attempt to map between them by using matching
properties of two beans. In this way, focus can be given to the
inconsistencies between the beans i.e. the address properties, knowing
that Dozer will automatically match and convert the others.

=== Configuring Dozer Type Converter

Dozer's configuration is extremely flexible and many mapping scenarios
are covered https://github.com/DozerMapper/dozer/blob/master/docs/asciidoc/documentation/mappings.adoc[here].
For our simple example, the configuration looks like the following.

*mapping.xml*

[source,xml]
---------------------------------------------------------------------------------------------------------
<mappings xmlns="http://dozermapper.github.io/schema/bean-mapping"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping http://dozermapper.github.io/schema/bean-mapping.xsd">
  <mapping>
    <class-a>org.apache.camel.converter.dozer.service.Customer</class-a>
    <class-b>org.apache.camel.converter.dozer.model.Customer</class-b>
    <field>
      <a>street</a>
      <b>address.streetName</b>
    </field>
    <field>
      <a>zip</a>
      <b>address.zipCode</b>
    </field>
  </mapping>
</mappings>
---------------------------------------------------------------------------------------------------------

=== Support for Dozer in Camel Type Converter

Camel provides a simple mechanism to integrate Dozer Mappers with it's
own powerful xref:manual::type-converter.adoc[Type Conversion] framework.
Its configured by creating an instance of `DozerTypeConverterLoader`
providing it the camel context and an optional Dozer mapper.

If no mapper is supplied, Camel's registry will
be searched for suitable instances. The loader will query the Dozer
Mapper for the types it converts and register them with Camel's
type conversion framework to be handled by the mapper.

[NOTE]
====
*Limitation*

The Camel Dozer type converter does not support having the same type
conversion pairs in different mapping ids (eg map-id) in Dozer.
====

In Java it can be configured as follows:

[source,java]
-----------------------------------------------------------------------------------------
Mapper mapper = DozerBeanMapperBuilder.create()
                .withMappingFiles("mapping.xml")
                .build();

new DozerTypeConverterLoader(camelContext, mapper);
-----------------------------------------------------------------------------------------

Or in Spring XML:

[source,xml]
--------------------------------------------------------------------------------------------------
<bean id="dozerConverterLoader" class="org.apache.camel.converter.dozer.DozerTypeConverterLoader">
  <argument index="0" ref="myCamel"/>
  <argument index="1" ref="mapperConfiguration"/>
</bean>

<bean id="mapperConfiguration" class="org.apache.camel.converter.dozer.DozerBeanMapperConfiguration">
  <property name="mappingFiles">
    <list>
      <value>mapping.xml</value>
    </list>
  </property>
</bean>

<camelContext id="myCamel" xmlns="http://camel.apache.org/schema/spring">
  ...
</camelContext>
--------------------------------------------------------------------------------------------------

Now, where necessary, Camel will use Dozer to do conversions; in our
case between the new domain and legacy Customer types e.g.

[source,java]
---------------------------------------------------------------------------------------------------------------------------------------------
// given the following route
from("direct:legacy-service-in").bean(new CustomerProcessor());

// and a processor

public class CustomerProcessor {

    public Customer processCustomer(org.apache.camel.converter.dozer.model.Customer customer) {
       ...
    }
}

// service objects can be sent to the processor and automagically converted by Camel & Dozer
template.sendBody("direct:legacy-service-in", new org.apache.camel.converter.dozer.service.Customer("Bob", "Roberts", "12345", "1 Main st."));
---------------------------------------------------------------------------------------------------------------------------------------------




include::spring-boot:partial$starter.adoc[]
