#65 ClassMapFinder does not find ClassMap for interfaces

closed
None
5
2014-08-25
2006-12-14
No

Environment: Spring 2.0
Dozer: 2.4

IN Dozer 2.2, my mappings were defined specifying interfaces. Everything worked well.

Upgrading to 2.4, and this happens in 2.3 as well, causes mappings to break when a field has a map-id defined and the class mappings within that map are specified as interfaces.

In 2.2, the MappingProcessor would try to determine the ClassMap based upon map-id, if one was provided.

MappingProcessor: line 1214: determineClassMap(Object sourceObj, Class destClass, String mapId, boolean isInstance)

But in 2.4, the determineClassMap method was replaced with getClassMap, which utilizes the ClassMapFinder class. This class performs a lookup based upon a generated key rather than relying upon only the map-id.

When executing my app, the keys that resided within the customerMappings were as follows:
[com.sybase.it.rosettanet.pip3A4.purchaseorder.ShipTocom.sybase.it.cosmos.domain.ShipToShipTo, com.sybase.it.rosettanet.pip3A4.purchaseorder.PhysicalAddress01com.sybase.it.cosmos.domain.PhysicalLocationPhysicalAddress, com.sybase.it.cosmos.domain.PhysicalLocationcom.sybase.it.rosettanet.pip3A4.purchaseorder.PhysicalAddress01PhysicalAddress, com.sybase.it.cosmos.domain.ShipTocom.sybase.it.rosettanet.pip3A4.purchaseorder.ShipToShipTo, com.sybase.it.rosettanet.pip3A4.purchaseorder.Pip3A4PurchaseOrderRequestcom.sybase.it.cosmos.domain.ShipToCBSS, com.sybase.it.cosmos.domain.ShipTocom.sybase.it.rosettanet.pip3A4.purchaseorder.Pip3A4PurchaseOrderRequestCBSS]

But the generated key was as follows:
com.sybase.it.rosettanet.pip3A4.purchaseorder.impl.ShipToImplcom.sybase.it.cosmos.domain.ShipToShipTo

The newly generated key utilizes the passed in source class and destination class to generate a key. The problem is that my mappings for my source object are based upon interfaces rather than on implementations, so the lookup fails. The lookup would have succeeded had the key been as follows:
com.sybase.it.rosettanet.pip3A4.purchaseorder.ShipTocom.sybase.it.cosmos.domain.ShipToShipTo
rather than
com.sybase.it.rosettanet.pip3A4.purchaseorder.impl.ShipToImplcom.sybase.it.cosmos.domain.ShipToShipTo

Discussion

  • Franz Garsombke

    Franz Garsombke - 2006-12-14
    • assigned_to: nobody --> fgarsombke
     
  • Franz Garsombke

    Franz Garsombke - 2006-12-14

    Logged In: YES
    user_id=550744
    Originator: NO

    We should be covering that with:

    public ClassMap findInterfaceOrAbstractMapping(Map customMappings, Class destClass, Object sourceObj, String mapId) {

    But apparently we are not in this specific use case...it looks like we can fix this bug since there is another method:

    public List findInterfaceMappings(Map customMappings, Class sourceClass, Class destClass) {

    that looks better suited for what we need done. I just need to reproduce this use case...

     
  • bilousme

    bilousme - 2007-01-08

    Logged In: YES
    user_id=1686499
    Originator: NO

    I have the same problem.
    Context :
    I use Dozer to map my Domain Object to my transfert Object. The persistence in domain object model is managed by Hibernate. Hibernate use proxy in place of my real class. Dozer use thus the method
    "public ClassMap findInterfaceOrAbstractMapping(Map customMappings, Class destClass, Object sourceObj, String mapId)"
    to determine the ClassMap.

    There is a bug in this method because you use never the parameter "String mapId".

    The resolution is simple (that work for my use cases), in the test done, we must add a test on mapId :
    && ( mapId == null || ((String)keys[i]).endsWith(mapId))

    The (possible) corrected method :

    public ClassMap findInterfaceOrAbstractMapping(Map customMappings, Class destClass, Object sourceObj, String mapId) {
    ClassMap newClassMap = null;
    Class newClass = null;
    //Use object array for keys to avoid any rare thread synchronization issues while iterating
    //over the custom mappings. See bug #1550275.
    Object[] keys = customMappings.keySet().toArray();
    for (int i = 0; i < keys.length; i++) {
    ClassMap map = (ClassMap) customMappings.get(keys[i]);
    Class dest = map.getDestClass().getClassToMap();

    // is Assignable?
    // now that we have the a sub class for the abstract class or interface we need to
    // verify that the source class in the map IS a super class of the source object...or the source object itself.
    if (destClass.isAssignableFrom(dest)
    && (map.getSourceClass().getClassToMap().isAssignableFrom(sourceObj.getClass()) || map.getSourceClass()
    .getClassToMap().isInstance(sourceObj))
    // look for most specific mapping
    && (newClass == null || newClass.isAssignableFrom(dest))
    && ( mapId == null || ((String)keys[i]).endsWith(mapId))) {
    newClassMap = map;
    newClass = dest;
    }
    }
    return newClassMap;
    }

     
  • Franz Garsombke

    Franz Garsombke - 2007-01-08

    Logged In: YES
    user_id=550744
    Originator: NO

    I actually have a patch for this. I just need to apply it to the 2.5 codebase. I will update this ticket when I have done that.

    Franz

     
  • bilousme

    bilousme - 2007-01-09

    Logged In: YES
    user_id=1686499
    Originator: NO

    Do you have an idea on the date of the release 2.5 ?
    I'm working on an important application who must be finished at the february's beginning. Can I hope that the release 2.5 will be released at this date ?
    This bug is blocking for me but I can find a workaround if the release 2.5 arrives after february.

    Thks.

    Julien

     
  • Franz Garsombke

    Franz Garsombke - 2007-01-10

    Logged In: YES
    user_id=550744
    Originator: NO

    Let me talk with the other developer. I hope to release before then.

    Thanks,

    Franz

     
  • Franz Garsombke

    Franz Garsombke - 2007-01-15
    • status: open --> pending
     
  • Franz Garsombke

    Franz Garsombke - 2007-01-15

    Logged In: YES
    user_id=550744
    Originator: NO

    Change has been added to 2.5 branch.

     
  • bilousme

    bilousme - 2007-01-15

    Logged In: YES
    user_id=1686499
    Originator: NO

    I tested this morning your patch but it doesn't resolve my bug.
    I think that I didn't explain correctly my problem.

    I have one class with two differents mappings. To differentiate the two mappings, I use thus the "map-id" property in my xml file.

    <mappings>
    <!-- mapping used in case of getCampaign ... All attributes are mapped -->
    <mapping map-id="fullMapping">
    <class-a>mypackage.crm.dim.domain.Campaign</class-a>
    <class-b>mypackage.crm.dim.to.CampaignTO</class-b>
    ...
    </mapping>

    <!-- mapping used in case of listCampaign ... For performance reason, only attribute displayed are mapped !-->
    <mapping map-id="softMapping">
    <class-a>mypackage.crm.dim.domain.Campaign</class-a>
    <class-b>mypackage.crm.dim.to.CampaignTO</class-b>
    ...
    </mapping>
    </mappings>

    As I use Hibernate, proxies are used in place of mypackage.crm.dim.domain.Campaign and Dozer uses thus the method "findInterfaceOrAbstractMapping(Map customMappings, Class destClass, Object sourceObj, String mapId)" to determine the ClassMap.

    But in this method, you don't use the parameter "String mapId" to determine the class map. And thus when Dozer calls this method with differents map-id, it returns always the same mapping !!

    I think that we can avoid this bug in adding the follow test :
    ( mapId == null || ((String)keys[i]).endsWith(mapId) ) to determine the class map (see previous comment)

    I would like to thank you for your fast support.

     
  • Franz Garsombke

    Franz Garsombke - 2007-01-15

    Logged In: YES
    user_id=550744
    Originator: NO

    I will test this and apply for the 2.5 release.

     
  • Franz Garsombke

    Franz Garsombke - 2007-01-17

    Logged In: YES
    user_id=550744
    Originator: NO

    I have applied this change into the 2.5 branch...

    I think that we can avoid this bug in adding the follow test :
    ( mapId == null || ((String)keys[i]).endsWith(mapId) ) to determine the
    class map (see previous comment)

     
  • Matt Tierney

    Matt Tierney - 2007-02-09
    • status: pending --> closed
     

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks