GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Method with `@Condition` acts strange when applying to source · Issue #3459 · mapstruct/mapstruct

Method with @Condition acts strange when applying to source  #3459

New issue
Copy link
New issue
Copy link
Closed
#3543
Closed
Method with @Condition acts strange when applying to source #3459
#3543
Copy link
Labels
bug
Milestone
1.6.0.Beta2

Description

@foxii-cn
foxii-cn
opened on Dec 1, 2023
Issue body actions

Expected behavior

when @Condition annotated method's parameter type is same to mapping source

    DTO toDto(E entity);

    @Condition
    default boolean isEntityAvailable(E entity) {
        if (entity == null) {
            return false;
        }
        return Persistence.getPersistenceUtil().isLoaded(entity);
    }

hope to generate something like

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        if ( !isEntityAvailable( entity ) ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();
        subCategoryDto.id( entity.getId() );
        subCategoryDto.name( entity.getName() );
        subCategoryDto.nick( entity.getNick() );
        return SubCategoryDto.build();
    }

or just ignore it

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();
        subCategoryDto.id( entity.getId() );
        subCategoryDto.name( entity.getName() );
        subCategoryDto.nick( entity.getNick() );
        return SubCategoryDto.build();
    }

Actual behavior

but now I got this

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();

        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.id( entity.getId() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.name( entity.getName() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.nick( entity.getNick() );
        }

        return SubCategoryDto.build();
    }

Steps to reproduce the problem

using JPA with Mapstruct
I have a base interface:

public interface EntityMapper<DTO extends EntityDto, E extends BasicEntity> {
    E toEntity(DTO dto);

    DTO toDto(E entity);

    // try to avoid JPA lazy loading issue
    // and this one worked well
    @Condition
    default boolean isCollectionAvailable(Collection<E> collection) {
        if (collection == null) {
            return false;
        }
        return Persistence.getPersistenceUtil().isLoaded(collection);
    }

    // try to avoid JPA lazy loading issue
    // got problem with this
    @Condition
    default boolean isEntityAvailable(E entity) {
        if (entity == null) {
            return false;
        }
        return Persistence.getPersistenceUtil().isLoaded(entity);
    }

    @MapperConfig(mappingControl = DeepClone.class,
                  mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_ALL_FROM_CONFIG)
    interface Config {
    }
}

and entity mappers:

@Mapper(config = EntityMapper.Config.class, uses = {SubCategoryMapper.class})
public interface ParentCategoryMapper extends EntityMapper<ParentCategoryDto, ParentCategory> {
}

@Mapper(config = EntityMapper.Config.class, uses = {ParentCategoryMapper.class})
public interface SubCategoryMapper extends EntityMapper<SubCategoryDto, SubCategory> {
}

and then I got this:

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();
        // Calling isEntityAvailable() so much times does not make any sense.
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.id( entity.getId() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.name( entity.getName() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.nick( entity.getNick() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.theOrder( entity.getTheOrder() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.icon( entity.getIcon() );
        }
        if ( isEntityAvailable( entity ) ) {
            subCategoryDto.link( entity.getLink() );
        }
        // this is right
        if ( ParentCategoryMapper.isEntityAvailable( entity.getParentCategory() ) ) {
            subCategoryDto.parentCategory( ParentCategoryMapper.toDto( entity.getParentCategory() ) );
        }
        return SubCategoryDto.build();
    }

and what I want is:

    @Override
    public SubCategoryDto toDto(SubCategory entity) {
        if ( entity == null ) {
            return null;
        }
        if ( !isEntityAvailable( entity ) ) {
            return null;
        }
        SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();
        subCategoryDto.id( entity.getId() );
        subCategoryDto.name( entity.getName() );
        subCategoryDto.nick( entity.getNick() );
        subCategoryDto.theOrder( entity.getTheOrder() );
        subCategoryDto.icon( entity.getIcon() );
        subCategoryDto.link( entity.getLink() );
        if ( ParentCategoryMapper.isEntityAvailable( entity.getParentCategory() ) ) {
            subCategoryDto.parentCategory( ParentCategoryMapper.toDto( entity.getParentCategory() ) );
        }
        return SubCategoryDto.build();
    }

MapStruct Version

MapStruct 1.6.0.Beta1

Activity

  1. foxii-cn
    added
    bug
    on Dec 1, 2023
  2. thunderhook
    changed the title [-]Methmod with @Condition act strange when applying to source [/-] [+]Method with @Condition acts strange when applying to source [/+] on Dec 3, 2023
  3. filiphr
    changed the title [-]Method with @Condition acts strange when applying to source [/-] [+]Method with `@Condition` acts strange when applying to source [/+] on Dec 11, 2023
  4. filiphr commented on Dec 11, 2023

    @filiphr
    filiphr
    on Dec 11, 2023
    Member
    More actions

    Thanks @foxii-cn, this is a known issue. See #3270. I think that the main root cause is #3209 and we should do it with #2610

  5. filiphr
    added this to the 1.6.0.Beta2 milestone on Dec 11, 2023
  6. filiphr
    added a commit that references this issue on Apr 29, 2024

    #2610 Add support for conditions on source parameters + fix incorrect…

    0a2a0aa
  7. filiphr
    closed this as completedin #3543on Apr 29, 2024
  8. filiphr commented on Apr 29, 2024

    @filiphr
    filiphr
    on Apr 29, 2024
    Member
    More actions

    @foxii-cn, with #3543 we've added proper support for conditions on source parameters.

    So in your case the mapper would look like:

        DTO toDto(E entity);
    
        @SourceParameterCondition
        default boolean isEntityAvailable(E entity) {
            if (entity == null) {
                return false;
            }
            return Persistence.getPersistenceUtil().isLoaded(entity);
        }

    which would generate:

        @Override
        public SubCategoryDto toDto(SubCategory entity) {
            if ( !isEntityAvailable( entity ) ) {
                return null;
            }
    
            SubCategoryDto.SubCategoryDtoBuilder<?, ?> subCategoryDto = SubCategoryDto.builder();
            subCategoryDto.id( entity.getId() );
            subCategoryDto.name( entity.getName() );
            subCategoryDto.nick( entity.getNick() );
            return SubCategoryDto.build();
        }
    Reacted by Foxii
    Reacted by Foxii
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug

    Type

    No type

    Projects

    No projects

      Milestone

      • 1.6.0.Beta2

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.