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 — Support generic `@Context` · Issue #3711 · mapstruct/mapstruct

Support generic @Context #3711

New issue
Copy link
New issue
Copy link
Closed
#3867
Closed
Support generic @Context#3711
#3867
Copy link
Labels
bug
Milestone
1.7.0.Beta1

Description

@ilia1243
ilia1243
opened on Sep 12, 2024
Issue body actions

Use case

Consider the following example mapstruct-jpa-child-parent but with generic JpaContext:

@Data
class ParentDto {
    ChildDto child;
}

@Data
class ChildDto {
    ParentDto parent;
}

@Data
class ParentEntity {
    ChildEntity child;
}

public interface ParentRelation<T> {
    void setChildToParent(T parent);
}

@Data
class ChildEntity implements ParentRelation<ParentEntity> {
    ParentEntity childToParent;
}

class JpaContext<T> {
    T parentEntity;

    @BeforeMapping
    void setEntity(@MappingTarget T parentEntity) {
        this.parentEntity = parentEntity;
    }

    @AfterMapping
    void establishRelation(@MappingTarget ParentRelation<T> childEntity) {
        childEntity.setChildToParent(parentEntity);
    }
}

interface BaseMapper<T, E> {
    default E toEntity(T s) {
        return toEntity(s, new JpaContext<>());
    }

    E toEntity(T s, @Context JpaContext<E> ctx);
}

@Mapper
interface SourceTargetMapper extends BaseMapper<ParentDto, ParentEntity> {
}

In this case MapStruct does not invoke @BeforeMapping and @AfterMapping methods in SourceTargetMapperImpl, although it is allowed by Java assignment rules.

Generated Code

Desired generated code:

@Generated(
    value = "org.mapstruct.ap.MappingProcessor"
)
class SourceTargetMapperImpl implements SourceTargetMapper {

    @Override
    public ParentEntity toEntity(ParentDto s, Ctx ctx) {
        if ( s == null ) {
            return null;
        }

        ParentEntity parentEntity = new ParentEntity();

        ctx.setEntity( parentEntity );

        parentEntity.setChild( childDtoToChildEntity( s.getChild(), ctx ) );

        return parentEntity;
    }

    protected ChildEntity childDtoToChildEntity(ChildDto childDto, Ctx ctx) {
        if ( childDto == null ) {
            return null;
        }

        ChildEntity childEntity = new ChildEntity();

        ctx.establishRelation( childEntity );

        return childEntity;
    }
}

Possible workarounds

Work around of this issue is to create derived class from JpaContext and use extra type parameter in the mapper to supply the derived class. The following example generates exactly the desired Generated Code above.

interface BaseMapper<T, E, C extends JpaContext<E>> {
    default E toEntity(T s) {
        return toEntity(s, getCtx());
    }

    E toEntity(T s, @Context C ctx);

    C getCtx();
}

@Mapper
interface SourceTargetMapper extends BaseMapper<ParentDto, ParentEntity, SourceTargetMapper.Ctx> {
    default Ctx getCtx() {
        return new Ctx();
    }

    class Ctx extends JpaContext<ParentEntity> {
    }
}

MapStruct Version

1.6.0

Activity

  1. filiphr commented on Sep 13, 2024

    @filiphr
    filiphr
    on Sep 13, 2024
    Member
    More actions

    This looks like some exotic edge case. Will look into it.

    Just out of curiosity, did this work in 1.5?

  2. filiphr
    added
    bug
    on Sep 13, 2024
  3. filiphr
    added this to the 1.6.1 milestone on Sep 13, 2024
  4. filiphr commented on Sep 14, 2024

    @filiphr
    filiphr
    on Sep 14, 2024
    Member
    More actions

    I checked this and it isn't working in 1.5 as well. We need to look into it, but I'll move it out of 1.6.1 for now

    Reacted by ilia1243
  5. filiphr
    modified the milestones: 1.6.1, 1.7.0 on Sep 14, 2024
  6. filiphr
    changed the title [-]Support generic Context to set parent-child relations[/-] [+]Support generic `@Context`[/+] on May 31, 2025
  7. filiphr
    closed this as completedin #3867on May 31, 2025
  8. filiphr
    added a commit that references this issue on May 31, 2025

    #3711: Support generic `@Context`

    5464c3c
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.7.0.Beta1

      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.