title: MapStruct inheritance, more than one configuration prototype is application
body: <p>All my entities extends a base entity that has a <code>Customer createdBy</code> and <code>String createdById</code> field, and some more that work the same. I want to exclude the full <code>Customer</code> object when data is transferred around.</p>
  
  <p>Some others entities extends another entity that itself extends the base entity, hence the following mappers :</p>
  
  <pre class="lang-java prettyprint-override"><code>@MapperConfig(componentModel = "spring", mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_FROM_CONFIG)
  public interface AuditingEntityMapper&lt;Dto, Entity&gt; {
  
      @Mapping(target = "createdBy", source = "createdById")
      @Mapping(target = "lastModifiedBy", source = "lastModifiedById")
      Dto toDto(Entity entity);
  
      @Mapping(target = "createdBy", ignore = true)
      @Mapping(target = "lastModifiedBy", ignore = true)
      Entity toEntity(Dto dto);
  }
  
  
  @MapperConfig(componentModel = "spring", mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_FROM_CONFIG)
  public interface ManageableEntityMapper&lt;ManageableDtoType extends ManageableDTO, ManageableType extends Manageable&gt; {
  
      ManageableDtoType toDto(ManageableType manageable);
  
      @Mapping(target = "project", ignore = true)
      ManageableType toEntity(ManageableDtoType dto);
  }
  
  </code></pre>
  
  <p>Then I exploit those two mappers :</p>
  
  <pre class="lang-java prettyprint-override"><code>@Mapper(config = AuditingEntityMapper.class)
  public interface ManageableStatusMapper {
  
      @Mapping(target = "project", ignore = true)
      @Mapping(target = "organization", ignore = true)
      ManageableStatus toEntity(ManageableStatusDTO manageableStatusDTO);
  
      default ManageableStatus fromId(String id) {
          if (id == null) {
              return null;
          }
          ManageableStatus manageableStatus = new ManageableStatus();
          manageableStatus.setId(id);
          return manageableStatus;
      }
  }
  
  // Returns this error and therefore others about mapping problems :
  // More than one configuration prototype method is applicable. Use @InheritConfiguration to select one of them explicitly: java.lang.Object toDto(java.lang.Object entity), java.lang.Object toEntity(java.lang.Object dto).
  
  
  @Mapper(config = ManageableEntityMapper.class)
  public interface TaskMapper {
  
      @Mapping(target = "timeEntries", ignore = true)
      @Mapping(target = "assignments", ignore = true)
      Task toEntity(TaskDTO taskDTO);
  
      default Task fromId(String id) {
          if (id == null) {
              return null;
          }
          Task task = new Task();
          task.setId(id);
          return task;
      }
  }
  // Returns this error and one more of the same type :
  // Can't map property "java.lang.String createdBy" to "com.acme.domain.Customer createdBy". Consider to declare/implement a mapping method: "com.acme.domain.Customer map(java.lang.String value)".
  </code></pre>
  
  <p>If my business mapper doesn't need extra mapping it works fine.
  Also, MapStruct seems to try to generate an implementation of both <code>@MapperConfig</code> annotated classes, which generates a lot of errors, but it's probably connected to all those classes connected to them.</p>
  
  <p>How am I supposed to implement this behavior ? The <a href="https://mapstruct.org/documentation/stable/reference/html/#shared-configurations" rel="noreferrer">doc</a> about inheritance and/or shared configuration is very confusing to me.</p>