Skip to content

Option to remove the source type descriptor from call to the ConversionService for ExternalConversion #153

@ddnyer

Description

@ddnyer

Hi,

I'm using JMolecules that introduces some wrappers around id values. It comes with standard Spring Converters so the ConversionService of Spring can convert those wrappers from and to the UUID they are holding.

I would like to be able to convert my entities containing those wrappers into DTOs using MapStruct. For that, I use the ExternalConversion annotation like this:

@SpringMapperConfig(
    externalConversions = {
      @ExternalConversion(sourceType = Association.class, targetType = UUID.class),
      @ExternalConversion(sourceType = Identifier.class, targetType = UUID.class)
    })
public interface MapperConfiguration {}

Identifier is an interface defined by JMolecules to identify ID values. It's used like this:

public record StoreId(@NotNull UUID id) implements Identifier {}

MapStruct generates the following ConversionServiceAdapter:

  private static final TypeDescriptor TYPE_DESCRIPTOR_ORG_JMOLECULES_DDD_TYPES_ASSOCIATION = TypeDescriptor.valueOf(Association.class);

  private static final TypeDescriptor TYPE_DESCRIPTOR_JAVA_UTIL_UUID = TypeDescriptor.valueOf(UUID.class);

  private static final TypeDescriptor TYPE_DESCRIPTOR_ORG_JMOLECULES_DDD_TYPES_IDENTIFIER = TypeDescriptor.valueOf(Identifier.class);


  public UUID mapAssociationToUUID(final Association source) {
    return (UUID) conversionService.convert(source, TYPE_DESCRIPTOR_ORG_JMOLECULES_DDD_TYPES_ASSOCIATION, TYPE_DESCRIPTOR_JAVA_UTIL_UUID);
  }

  public UUID mapIdentifierToUUID(final Identifier source) {
    return (UUID) conversionService.convert(source, TYPE_DESCRIPTOR_ORG_JMOLECULES_DDD_TYPES_IDENTIFIER, TYPE_DESCRIPTOR_JAVA_UTIL_UUID);
  }

At first sight, it looks good, but that does not work. The issue is that when calling the ConversionService, the ConversionServiceAdapter specifies the source type using the type descriptor of Identifier. Identifier is just an interface; the actual type I need to convert is StoreId. The Converter registered by JMolecules is not able to determine if it can deal with this conversion or not, the source type Identifier does not hold enough information (not all Identifier can be converted into UUID, it needs to know the actual type StoreId to figure out if it's the case). I also open a ticket on JMolecules to discuss this issue.

If I manually adapt the ConversionServiceAdapter like this, Spring will retrieve the source type at runtime and find out it's a StoreId. The Converter registered by JMolecules will match this time, and the conversion works fine.

public UUID mapIdentifierToUUID(final Identifier source) {
    return (UUID) conversionService.convert(source, TYPE_DESCRIPTOR_JAVA_UTIL_UUID);
  }

Would it be possible to omit the source type descriptor in the ConversionServiceAdapter for ExternalConversion? Either by default or through a parameter in @ExternalConversion.

Thanks

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions