Dozer deep mapping not working

匆匆过客 提交于 2020-02-05 17:12:47

问题


I am trying to use dozer 4.1 to map between classes. I have a source class that looks like this:

    public class initRequest{
     protected String id;
     protected String[] details
}

I have a destination class that looks like this:

public class initResponse{
       protected String id;
       protected DetailsObject detObj;
}

public class DetailsObject{
 protected List<String>  details;
}

So essentially i want the string in the details array to be populated into the List in the Details object.

I have tried a mapping like this:

<mapping wildcard="true" >
  <class-a>initRequest</class-a>
  <class-b>initResponse</class-b>   
  <field>
    <a is-accessible="true">details</a>
    <b is-accessible="true">detObj.details</b>
  </field>
</mapping>

But I get this error:

Exception in thread "main" net.sf.dozer.util.mapping.MappingException: java.lang.NoSuchFieldException: detObj.details
    at net.sf.dozer.util.mapping.util.MappingUtils.throwMappingException(MappingUtils.java:91)
    at net.sf.dozer.util.mapping.propertydescriptor.FieldPropertyDescriptor.<init>(FieldPropertyDescriptor.java:43)
    at net.sf.dozer.util.mapping.propertydescriptor.PropertyDescriptorFactory.getPropertyDescriptor(PropertyDescriptorFactory.java:53)
    at net.sf.dozer.util.mapping.fieldmap.FieldMap.getDestPropertyDescriptor(FieldMap.java:370)
    at net.sf.dozer.util.mapping.fieldmap.FieldMap.getDestFieldType(FieldMap.java:103)
    at net.sf.dozer.util.mapping.util.MappingsParser.processMappings(MappingsParser.java:95)
    at net.sf.dozer.util.mapping.util.CustomMappingsLoader.load(CustomMappingsLoader.java:77)
    at net.sf.dozer.util.mapping.DozerBeanMapper.loadCustomMappings(DozerBeanMapper.java:149)
    at net.sf.dozer.util.mapping.DozerBeanMapper.getMappingProcessor(DozerBeanMapper.java:132)
    at net.sf.dozer.util.mapping.DozerBeanMapper.map(DozerBeanMapper.java:94)

How can i map this so that it works?


回答1:


This works for me. I am using 5.2.1 version

 <mapping wildcard="true" >
      <class-a>initRequest</class-a>
      <class-b>initResponse</class-b>   
      <field>
        <a>details</a>
        <b is-accessible="true">detObj.details</b>
      </field>
    </mapping>

Note that "is-accessable" is not required for . Hope it helps




回答2:


Problem solved...

  • is-accesible allows an object to be updated regardless of access modifier and presence of getters/setters (essential for objects generated using JAXB)

  • "dot" notation for deep mapping works to access nested objects

Combining the two is a feature that does not work in Dozer (maybe it does in a newer version)

solution... modify the xsd such that the deep mapping is not required. This is not my ideal solution but its better than writing a custom converter for every object




回答3:


In case of JaxB, use can download and use the plugin for generating the setters. Refer to this link for more details, https://jaxb2-commons.dev.java.net/collection-setter-injector/




回答4:


I would guess that accessors (getter / setter) are missing. By the way I think that you'll also need to provide an empty constructor for DetailsObject so dozer can instanciate it.




回答5:


<b is-accessible="true">detObj.details</b>

Should be replaced with

<b is-accessible="true">DetailsObject.details</b>



回答6:


While it does seem you cannnot use the "is-accessible" and dot notation together another approach is to break your deep mapping into smaller mappings.

We ran into this situation with JAX-WS generated code. You have lists that have no setter methods and in our case were deeply nested. We found our solution by simply breaking the large deep mapping into smaller mappings that "walked" our way to what we wanted. I tried to explain this in my blog here:

http://btarlton.blogspot.com/2014/08/dozer-deep-nestinga-different-approach.html

But the trick is just walking the object tree by smaller mappings and using is-accessible="true" when necessary to access the list with no setter and using "this" as the property name to keep passing the source along.

Hope this helps!




回答7:


To summarize there are following options for this issue 1) Use JaxB pluggin to enable setters as discussed by Naveen 2) Use is-accessible for such properties

I believe using first approach unnecessarily exposes setters for collections/lists as you can risk of setting them with null.

We decided to enable is-accessible for such fields (and not to entire class) to avoid any side effects.

I have discussed the solution at Dozer Mapping Class level is-accessible



来源:https://stackoverflow.com/questions/3018006/dozer-deep-mapping-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!