orika-mapper / orika

Simpler, better and faster Java bean mapping framework
http://orika-mapper.github.io/orika-docs/
Apache License 2.0
1.29k stars 269 forks source link

Wrong ObjectFactory generated when destination object has no args and all args constructor #389

Open knfs9 opened 2 years ago

knfs9 commented 2 years ago

Source class:

public class Data {
  private List<Entity> entities;

  public List<Entity> getEntities() {
    return entities;
  }

  public void setEntities(List<Entity> entities) {
    this.entities = entities;
  }
}

Destination class:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class DataDTO {

  private List<InnerEntity> innerDtoEntities;

}
public class Entity {
  private List<InnerEntity> innerEntities;

  public List<InnerEntity> getInnerEntities() {
    return innerEntities;
  }

  public void setInnerEntities(List<InnerEntity> innerEntities) {
    this.innerEntities = innerEntities;
  }
}
public class InnerEntity {
  private String field;

  public String getField() {
    return field;
  }

  public void setField(String field) {
    this.field = field;
  }
}

Mapping written like this:

mapperFactory.classMap(Data.class, DataDTO.class)
        .field("entities{innerEntities}", "innerDtoEntities")
        .mapNulls(true)
        .mapNullsInReverse(true)
        .byDefault()
        .register();

Generated ObjectFactory method:

public Object create(Object s, ma.glasnost.orika.MappingContext mappingContext) {if(s == null) throw new java.lang.IllegalArgumentException("source object must be not null");if (s instanceof test.Data) {test.Data source = (test.Data) s;
try {

java.util.List arg0 = null; if ( !(((java.util.List)source.getInnerEntities()) == null)) {

java.util.List new_arg0 = ((java.util.List)new java.util.ArrayList()); 

new_arg0.addAll(mapperFacade.mapAsList(((java.util.List)source.getInnerEntities()), ((ma.glasnost.orika.metadata.Type)usedTypes[0]), ((ma.glasnost.orika.metadata.Type)usedTypes[0]), mappingContext)); 
arg0 = new_arg0; 
} else {
 if ( !(arg0 == null)) {
arg0 = null;
};
}return new test.DataDTO(arg0);
} catch (java.lang.Exception e) {

if (e instanceof RuntimeException) {

throw (RuntimeException)e;

} else {
throw new java.lang.RuntimeException("Error while constructing new DataDTO instance", e);
}
}
}return new test.DataDTO();
}

I'm getting Caused by: javassist.compiler.CompileError: getInnerEntities() not found in test.Data

In generated ObjectFactory it tries to getInnerEntities from Data - (java.util.List)source.getInnerEntities(), howevever, InnerEntity dos not belong to Data directly

Not sure if I'm doing the right mapping here and it is not supported by Orika or it's a bug.

knfs9 commented 2 years ago

It's fixed by removing @AllArgsConstructor, so ma.glasnost.orika.impl.DefaultMapperFactory#lookupObjectFactory(ma.glasnost.orika.metadata.Type<T>, ma.glasnost.orika.metadata.Type<S>, ma.glasnost.orika.MappingContext) returns DefaultConstructorObjectFactory when there is only one constructor, instead of generated ObjectFactory. But still i believe it could be bug in generated ObjectFactory