atos1990 / orika

Automatically exported from code.google.com/p/orika
0 stars 0 forks source link

(Orika 1.4.0) A sub type is not beeing mapped to the configured mapping type #77

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
This test case demonstrates the problem. We try to map B1 to B2:

    public static class A1 {

    }

    public static class B1 extends A1 {
        int someProperty;
    }

    public static class Container1 {
        private List<A1>    elements    = new ArrayList<A1>();
        private A1          singleElement;

        public List<A1> getElements() {
            return elements;
        }

        public void setElements(final List<A1> elements) {
            this.elements = elements;
        }

        public A1 getSingleElement() {
            return singleElement;
        }

        public void setSingleElement(final A1 singleElement) {
            this.singleElement = singleElement;
        }
    }

    public static class A2 {

    }

    public static class B2 extends A2 {
        int someProperty;
    }

    public static class Container2 {
        private List<A2>    elements    = new ArrayList<A2>();
        private A2          singleElement;

        public List<A2> getElements() {
            return elements;
        }

        public void setElements(final List<A2> elements) {
            this.elements = elements;
        }

        public A2 getSingleElement() {
            return singleElement;
        }

        public void setSingleElement(final A2 singleElement) {
            this.singleElement = singleElement;
        }
    }

    @Test
    public void testMappingSubTypes() {
        // Test data
        final Container1 c1 = new Container1();
        c1.elements.add(new B1());
        c1.singleElement = new B1();

        // mapper
        final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        mapperFactory.classMap(B1.class, B2.class).byDefault().register();
        mapperFactory.classMap(B2.class, B1.class).byDefault().register();
        final MapperFacade mapper = mapperFactory.getMapperFacade();

        // map
        final Container2 c2 = mapper.map(c1, Container2.class);

        // check
        assertTrue(c1.singleElement instanceof B1);
        assertTrue(c2.singleElement instanceof B2);
        assertTrue(c2.elements.get(0) instanceof B2);
    }

The first assert is successful the following two fail.

Orika should map registered types.

Orika 1.4.0, Oracle Java 1.7 x64, Windows.

Original issue reported on code.google.com by wirch.ed...@gmail.com on 16 Jan 2013 at 9:05

GoogleCodeExporter commented 9 years ago
I think the problem here is that your class Container2 has a property of type 
A2 (not B2), and you're expecting Orika to guess that you want to use a 
particular subclass of A2. 
What Orika has available to it (from looking at Container1 mapping to 
Container2) is that there's a property named 'singleElement' on one side of 
type A1 that's being mapped to a property of the same name on the other side of 
type A2. 
Even though we can resolve at runtime that your instance on once side is 
actually of type B1, the other side is still A2 (not B2), so Orika looks for a 
mapping of B1->A2, which it doesn't find, so it generates one.
I gather this from the debug log:
    Inputs:[ sourceClass: ma.glasnost.orika.test.community.Issue77TestCase.B1, sourceType: A1, destinationType: A2]
    Resolved:[ strategy: InstantiateAndUseCustomMapperStrategy, sourceType: B1, destinationType: A2, mapper: ma.glasnost.orika.generated.Orika_A2_B1_Mapper903913131@4af429d7, mapReverse?: false]

I've updated the order of search for destination type to favor explicitly 
registered type over the input type

Could you take a look at the current snapshot and confirm the fix?

Original comment by matt.deb...@gmail.com on 17 Jan 2013 at 9:32

GoogleCodeExporter commented 9 years ago
Can't find latest snapshot. 
https://repository-orika.forge.cloudbees.com/snapshot only contains a 
1.4.0-SNAPSHOT which is from December.

Original comment by wirch.ed...@gmail.com on 18 Jan 2013 at 8:25

GoogleCodeExporter commented 9 years ago
Sorry, it should be available now.

Original comment by matt.deb...@gmail.com on 19 Jan 2013 at 2:52

GoogleCodeExporter commented 9 years ago
1.4.1-SNAPSHOT looks good. None of my tests is failing.

Original comment by wirch.ed...@gmail.com on 23 Jan 2013 at 5:38

GoogleCodeExporter commented 9 years ago
I there any way I can work around this issue on v 1.4.0?

The reason I'm asking this is we were using v. 1.0 and Orika resolved mapping 
in a correct order (made a lookup based on the type of the imput argument). But 
when we switched to v. 1.4 to get access to a new features, our tests broke and 
mapping stopped working correctly, taking output argument as a reference.

We cannot add new repositories and can use only mvnrepository

Original comment by bogdan.w...@gmail.com on 5 Feb 2013 at 1:59

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
We will release 1.4.1 within this week and it will be available on maven 
central,
please stay tuned

Original comment by elaat...@gmail.com on 5 Feb 2013 at 9:25

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Just in case anyone has the same issue - I created a custom converter. For the 
example provided that would look like:

  final class B2Coverter extends CustomConverter<B2, B1> {

    private final MapperFacade mapper;

    public B2Coverter() {
      final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
      mapperFactory.registerClassMap(
        mapperFactory.classMap(B2.class, B1.class).byDefault()
      );
      mapperFactory.registerClassMap(
          mapperFactory.classMap(B2.class, B2.class).byDefault()
      );
      mapper = mapperFactory.getMapperFacade();
    }

    // TODO remove custom mapper when we switch to Orika 1.4.1
    // due to the bug in Orika 1.4.0: https://code.google.com/p/orika/issues/detail?id=77
    @Override
    public B1 convert(B2 source,
          Type<? extends B1> destinationType) {
      if (source instanceof B2) {
        final B2 result =
            mapper.map(source, B2.class);
        return result;
      }
      return mapper.map(source, B1.class);
    }
  }

Original comment by bogdan.w...@gmail.com on 5 Feb 2013 at 11:47

GoogleCodeExporter commented 9 years ago
Fixed in release : 1.4.1

Original comment by elaat...@gmail.com on 10 Feb 2013 at 12:05