Saturday 2 March 2013

Project on Sourceforge: Pojo/Bean mapper

This is a work in progress but I am creating an ANT task to generate the conversion classes to allow you to create the code that transfers data from one POJO to an other..
While at first sight this may seem similar to dozer the primary difference is that this is code generation and does not have the overhead of using introspection at run time.


Project on Sourceforge: https://sourceforge.net/projects/pojobeanmapper/


The original use for this was to take data out of a set of Hibernate DAO objects and create a variety of XML DOM objects from them. In the project that instigated this work the mapping between the DAOs and the XML DOM was not one for one and encoding the conversion into the DOAs was not a good idea.

Use

To create the task ensure the ant-pojomapper-x.x.xx.jar is on your ANT path (I suggest in ANT_HOME/lib).
Create the task with this task def command:

<property name="ant.pojomapper.dir" value="./libs/pojomapper"/>
<path id="pojomapper.lib.classpath">
<fileset dir="${ant.pojomapper.dir}" includes="*.jar" />
</path>
<taskdef resource="pojomapper_ant.properties" classpathref="pojomapper.lib.classpath" />


Once declared this will allow you to call the pojomapper task.
This will look something like this:

<beanmapper
classPath="${build.classpath}"
settingsFolder="./src/templates"
srcPackage ="myproj.dom1"
dstPackage ="myproj.api"
dstDir ="${gensrc.java.dir}/pojomapping"
outputPackageName ="myproj.dom1.converters"
/>

To work correctly there needs to be at least the following file present in the settings folder:
This file is a "property" file which contains the classes that equate to each other.

beanmapper-classpairs.properties

This file is of the form:

srcClass1=destClass1
srcClass2=destClass2

In this example two classes will be created in the package myproj.dom1.converters:

SrcClass1ToDestClass1Copier.java
SrcClass2ToDestClass2Copier.java


The generator will create these files under the folder   ${gensrc.java.dir}/pojomapping/src
along with a copy of the beanmapper-classpairs.properties file.


Additionally two other files are auto-generated.
These files can be reused if the build process failed.

beanmapper-knownmethodmappings.properties

While the this pojo mapper will match beans of the same name.
There are some that it will not beable to convert.

destClass.setter=srcClass.getter

The file defines the mappings that are already known.

PojoB.pennies=PojoA.cash
PojoB.extra=PojoA.more

At the end of the generated file are a series of mappings the pojo mapper could not determine what should be done with them.
These will appear as follows:

## Missing mappings
# destClass.???=PojoA.getter1
# destClass.???=PojoA.getter2

This allows the developer to determine quickly which methods need some attention.

beanmapper-classconverters.properties

There are conversions that the pojomapper knows implicitly but some are not known.

These need to be defined for it as follows:

SrcType:DstType=ConverterClass.convertermethod

This will create a call in any of the generated code where a SrcType class needs to be converted into a dstType.

The call will be approximatly as follows:

SrcType a ;
DstType b ;
b = ConverterClass.convertermethod(a);


If the pojomapper will detect the need for converters that it is self will be creating.

MAVEN USE

It is possible to use this ant task as a plugin.
Add the following:

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.7</version>
                <executions>
                    <execution>
                        <id>download-files</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <echo>+++++++++++++++++ DOWNLOAD POJO BEAN MAPPER ++++++++++++++</echo>
                                <echo>Download pojobeanmapper to ${project.build.pojobeanmapper.jar}</echo>
                                <mkdir dir="${project.build.download.folder}" />
                                <get src="${project.build.pojobeanmapper.url}" 
                                        dest="${project.build.pojobeanmapper.jar}"
                                        verbose="false" 
                                        usetimestamp="true" />
                                <echo>Get commons-io 2.1</echo>
                                <get src="http://repo1.maven.org/maven2/commons-io/commons-io/2.1/commons-io-2.1.jar" 
                                        dest="${project.build.download.folder}"
                                        verbose="false" 
                                        usetimestamp="true" />
                                <echo>Get commons-lang 2.6</echo>
                                <get src="http://repo1.maven.org/maven2/commons-lang/commons-lang/2.6/commons-lang-2.6.jar" 
                                        dest="${project.build.download.folder}"
                                        verbose="false" 
                                        usetimestamp="true" />                                
                            </target>
                        </configuration>
                    </execution>
                    <execution>
                        <phase>generate-sources</phase>
                        <configuration>
                            <target>
                                <echo>+++++++++++++++++ INVOKE POJO BEAN MAPPER ++++++++++++++</echo>
                            
                                <!-- sEE: http://maven.apache.org/plugins/maven-antrun-plugin/examples/classpaths.html -->
                                <property name="compile_classpath" refid="maven.compile.classpath"/>
                                <property name="runtime_classpath" refid="maven.runtime.classpath"/>
                                <property name="test_classpath"    refid="maven.test.classpath"/>
                                <property name="plugin_classpath"  refid="maven.plugin.classpath"/>
                                <path id="pojomapper.lib.classpath">
                                     <fileset dir="${project.build.download.folder}" includes="*.jar" />
                                </path> 
                                <taskdef resource="pojomapper_ant.properties" 
                                         classpathref="pojomapper.lib.classpath" />

                                <beanmapper 
                                    classPath="${compile_classpath}"
                                    settingsFolder="./src/templates"
                                    srcPackage ="com.proj.src"
                                    dstPackage ="com.proj.dst"
                                    dstDir ="${project.build.directory}/pojomapping"
                                    outputPackageName ="com.proj.converters"
                                    />

                            </target>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>


and add the following properties:

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.build.pojobeanmapper.url>http://sourceforge.net/projects/pojobeanmapper/files/latest/download?source=files</project.build.pojobeanmapper.url>
        <project.build.download.folder>${project.build.directory}/downloads</project.build.download.folder>
        <project.build.pojobeanmapper.jar>${project.build.download.folder}/pojobeanmapper.jar</project.build.pojobeanmapper.jar>
    </properties>


------------------------------------------------------------------------------
Please return to the is blog entry for full information at a later date.
It will be updated over the month of decemper 2013.

3 comments:

  1. Dozer — each bean is created using reflection, mapping is customized using XML and Java code. (http://dozer.sourceforge.net/)
    Orika — beans are created and initialized using code generated by library, mapping can be customized using Java code and own expression language. (http://orika-mapper.github.io/orika-docs/index.html)
    Manual conversion — each bean is created and initialized with code written manually. All conversion is performed in Java code.

    ReplyDelete
  2. http://blog.sokolenko.me/2013/05/dozer-vs-orika-vs-manual.html

    ReplyDelete
  3. http://www.christianschenk.org/blog/java-bean-mapper-performance-tests/

    ReplyDelete