Hello,
I've ran into problems while setting up global configuration XML file. I use Dozer 4.2 and configure DozerBeanMapper in Spring, like this:
...
<bean id="domainDtoMapper" class="net.sf.dozer.util.mapping.DozerBeanMapper">
<property name="customConverters">
<list>
<ref bean="fileDomainDtoConverter" />
</list>
</property>
<property name="mappingFiles">
<list>
<value>global.dozer.xml</value>
<value>Tour.dozer.xml</value>
<value>Map.dozer.xml</value>
<value>Point.dozer.xml</value>
<value>Link.dozer.xml</value>
<value>ImageAttachment.dozer.xml</value>
<value>Image.dozer.xml</value>
</list>
</property>
</bean>
...
global.dozer.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mappings PUBLIC "-//DOZER//DTD MAPPINGS//EN" "http://dozer.sourceforge.net/dtd/dozerbeanmapping.dtd">
<mappings>
<configuration>
<stop-on-errors>true</stop-on-errors>
<date-format>yyyy-MM-dd HH:mm:ss</date-format>
<wildcard>true</wildcard>
<custom-converters>
<converter type="com.shiftlabs.imagestroll.portalfacebook.controller.service.impl.mapping.FileDomainDtoConverter">
<class-a>com.shiftlabs.imagestroll.model.File</class-a>
<class-b>com.shiftlabs.imagestroll.portalfacebook.controller.dto.FileDto</class-b>
</converter>
</custom-converters>
</configuration>
</mappings>
My custom converter simply didn't work when performing conversions. So I've started debugging the source and found out that global configuration is simply empty in runtime. Then I found the following piece of code in the method of CustomMappingsLoader class (inside the loop):
// the last configuration is the 'global' configuration
globalConfiguration = mappings.getConfiguration();
So all mapping files are loaded one by one, but exactly the last one is treated as global. I didn't find this particular feature in documentation of Dozer and found it a bit confusing. Now my global configuration XML file is listed the last one in Spring and works fine, like this:
<bean id="domainDtoMapper" class="net.sf.dozer.util.mapping.DozerBeanMapper">
<property name="customConverters">
<list>
<ref bean="fileDomainDtoConverter" />
</list>
</property>
<property name="mappingFiles">
<list>
<value>Tour.dozer.xml</value>
<value>Map.dozer.xml</value>
<value>Point.dozer.xml</value>
<value>Link.dozer.xml</value>
<value>ImageAttachment.dozer.xml</value>
<value>Image.dozer.xml</value>
<value>global.dozer.xml</value>
</list>
</property>
To summarize, it is bad that the feature mentioned above is not documented, thus making the detection of the problem much painless. May be it is even more essential to change the rule for global configuration identification?
Thank you.
Logged In: YES
user_id=464596
Originator: NO
I'd like to second the OP's opinion. This also took me quite a while... I didn't figure it out until I came here to and read this post. I think it would be good if this behaviour is at least documented very in the various places where examples are shown how to configure the mapper (Spring, programatically, ...)
That said, I really like this project. Good work :-)
Just my 2 cents
Bastian
Logged In: YES
user_id=195862
Originator: NO
This also took me quite a while to debug. After digging through the code I applied a patch that might be useful and help others that run into this issue as well. The patch will set the global configuration only if one has been included in the file. This way the configuration definition can be included in any file (and any order) and will not be overwritten. If multiple config files have a configuration section, a warning will be logged and the previous global configuration will be overwritten. Hopefully this can help others save a day of debugging the problem like I did today.
Here's the patch:
diff -c -r dozer-4.2.1/pom.xml dozer-4.2.1_patch/pom.xml
*** dozer-4.2.1/pom.xml 2008-07-30 17:08:04.000000000 -0700
--- dozer-4.2.1_patch/pom.xml 2008-07-30 17:08:15.000000000 -0700
***************
*** 9,15 ****
Dozer is a powerful, yet simple Java Bean to Java Bean mapper that recursively copies data from one object to
another
</description>
! <version>4.2.1</version>
<name>dozer</name>
<dependencies>
<dependency>
--- 9,15 ----
Dozer is a powerful, yet simple Java Bean to Java Bean mapper that recursively copies data from one object to
another
</description>
! <version>4.2.1_patch</version>
<name>dozer</name>
<dependencies>
<dependency>
diff -c -r dozer-4.2.1/src/main/java/net/sf/dozer/util/mapping/classmap/Configuration.java dozer-4.2.1_patch/src/main/java/net/sf/dozer/util/mapping/classmap/Configuration.java
*** dozer-4.2.1/src/main/java/net/sf/dozer/util/mapping/classmap/Configuration.java 2007-12-15 22:48:58.000000000 -0800
--- dozer-4.2.1_patch/src/main/java/net/sf/dozer/util/mapping/classmap/Configuration.java 2008-07-30 16:58:22.000000000 -0700
***************
*** 32,37 ****
--- 32,38 ----
*/
public class Configuration {
+ private boolean isParsed;
private Boolean wildcard;
private Boolean stopOnErrors;
private Boolean trimStrings;
***************
*** 42,47 ****
--- 43,60 ----
private CopyByReferenceContainer copyByReferences;
private AllowedExceptionContainer allowedExceptions;
+ public Configuration() {
+ this(false);
+ }
+
+ public Configuration(boolean parsed) {
+ isParsed = parsed;
+ }
+
+ public boolean isParsed() {
+ return isParsed;
+ }
+
public AllowedExceptionContainer getAllowedExceptions() {
return allowedExceptions;
}
diff -c -r dozer-4.2.1/src/main/java/net/sf/dozer/util/mapping/util/CustomMappingsLoader.java dozer-4.2.1_patch/src/main/java/net/sf/dozer/util/mapping/util/CustomMappingsLoader.java
*** dozer-4.2.1/src/main/java/net/sf/dozer/util/mapping/util/CustomMappingsLoader.java 2007-08-07 23:07:19.000000000 -0700
--- dozer-4.2.1_patch/src/main/java/net/sf/dozer/util/mapping/util/CustomMappingsLoader.java 2008-07-30 16:58:22.000000000 -0700
***************
*** 48,53 ****
--- 48,54 ----
Map customMappings = new HashMap();
ListOrderedSet customConverterDescriptions = new ListOrderedSet();
Configuration globalConfiguration = new Configuration();
+ String globalConfigurationMappingFileName = new String();
if (mappingFiles != null && mappingFiles.size() > 0) {
InitLogger.log(log, "Using the following xml files to load custom mappings for the bean mapper instance: " + mappingFiles);
***************
*** 61,68 ****
Mappings mappings = mappingFileReader.read();
InitLogger.log(log, "Successfully loaded custom xml mappings from URL: [" + url + "]");
! // the last configuration is the 'global' configuration
! globalConfiguration = mappings.getConfiguration();
// build up the custom converters to make them global
if (mappings.getConfiguration() != null && mappings.getConfiguration().getCustomConverters() != null
&& mappings.getConfiguration().getCustomConverters().getConverters() != null) {
--- 62,77 ----
Mappings mappings = mappingFileReader.read();
InitLogger.log(log, "Successfully loaded custom xml mappings from URL: [" + url + "]");
! // the last configuration is the 'global' configuration, warn the user if it is overwritten
! if (mappings.getConfiguration() != null && mappings.getConfiguration().isParsed()) {
! if (globalConfiguration.isParsed()) {
! log.warn("globalConfiguration from " + globalConfigurationMappingFileName
! + " will be overwritten by globalConfiguration from " + mappingFileName);
! }
! globalConfigurationMappingFileName = mappingFileName;
! globalConfiguration = mappings.getConfiguration();
! }
!
// build up the custom converters to make them global
if (mappings.getConfiguration() != null && mappings.getConfiguration().getCustomConverters() != null
&& mappings.getConfiguration().getCustomConverters().getConverters() != null) {
diff -c -r dozer-4.2.1/src/main/java/net/sf/dozer/util/mapping/util/XMLParser.java dozer-4.2.1_patch/src/main/java/net/sf/dozer/util/mapping/util/XMLParser.java
*** dozer-4.2.1/src/main/java/net/sf/dozer/util/mapping/util/XMLParser.java 2007-12-15 22:46:13.000000000 -0800
--- dozer-4.2.1_patch/src/main/java/net/sf/dozer/util/mapping/util/XMLParser.java 2008-07-30 16:58:22.000000000 -0700
***************
*** 410,416 ****
}
private void parseConfiguration(Element ele) {
! Configuration config = new Configuration();
mappings.setConfiguration(config);
NodeList nl = ele.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
--- 410,416 ----
}
private void parseConfiguration(Element ele) {
! Configuration config = new Configuration(true);
mappings.setConfiguration(config);
NodeList nl = ele.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Logged In: YES
user_id=195862
Originator: NO
I moved the patch over here:
https://sourceforge.net/tracker/index.php?func=detail&aid=2033478&group_id=133517&atid=727370
and have attached the patch file (rather than have it directly pasted in the comment section) to help with line breaks, etc.
We agree with your comments regarding the global config. For the 4.4 release we will throw an exception if more than one global config is found instead of silently ignoring. This should help with debugging and providing better clues as to the expected usage. Thanks.
https://sourceforge.net/tracker/index.php?func=detail&aid=2398621&group_id=133517&atid=727368