Skip to content

feature: evaluate MapStruct for type-safe bean mapping in PHI-critical codeΒ #2243

@github-actions

Description

@github-actions

Context

Following the migration from Apache Commons BeanUtils to Spring BeanUtils (PR #2241, issue #2202), we should evaluate MapStruct as a long-term replacement for bean mapping in PHI-critical areas of the codebase.

Current State

Key areas using bean mapping:

  • REST API converters (20+ files)
  • Demographic data handling (PHI-critical)
  • Billing data transformations
  • Lab result processing
  • Appointment/scheduling data
  • Clinical notes and encounter data

Why MapStruct?

MapStruct is an annotation-based code generator that provides compile-time bean mapping with several advantages over runtime reflection:

Security Benefits

  • βœ… Zero reflection = no classloader manipulation attacks possible (CVE-2014-0114, CVE-2019-10086 class)
  • βœ… Compile-time validation = catches mapping errors before runtime
  • βœ… Type-safe = prevents accidental data leaks between incompatible types
  • βœ… No security patches needed = generated code has no runtime dependencies

Performance Benefits

  • βœ… Faster execution = plain method calls instead of reflection
  • βœ… Better JIT optimization = compiler can inline and optimize generated code
  • βœ… Lower memory overhead = no reflection metadata caching

Development Benefits

  • βœ… IDE autocomplete = mappers are normal Java interfaces
  • βœ… Compile-time errors = catches mismatched types immediately
  • βœ… Explicit mappings = clear documentation of data transformations
  • βœ… Custom conversion logic = easy to add PHI sanitization, validation, etc.

Evaluation Goals

This issue tracks the evaluation of MapStruct to determine:

  1. Feasibility Assessment

    • Analyze compatibility with Spring Framework 5.3.39
    • Test integration with existing Struts2 actions
    • Evaluate impact on build times (annotation processing)
    • Assess learning curve for development team
  2. Priority Area Identification

    • Identify highest-value migration targets:
      • REST API converters (already abstracted, easy wins)
      • Demographic data (PHI-critical, highest security priority)
      • Billing transformations (performance-sensitive)
      • Lab result processing (high volume)
    • Estimate migration effort for each area
  3. Proof of Concept

    • Create sample mapper for REST converter (e.g., TicklerMapper)
    • Benchmark performance vs Spring BeanUtils
    • Test compile-time validation with intentional errors
    • Evaluate generated code quality
  4. Integration Strategy

    • Document integration with Spring dependency injection
    • Define coding standards for mapper interfaces
    • Create templates for common patterns (entity ↔ DTO, partial updates, etc.)
    • Plan gradual adoption approach (coexist with Spring BeanUtils)
  5. Risk Assessment

    • Identify potential breaking changes
    • Evaluate impact on existing tests
    • Document rollback strategy if issues arise
    • Consider team training requirements

Example Implementation

Before (Spring BeanUtils - runtime reflection):

@RestController
public class TicklerConverter {
    public TicklerLinkTo1 getAsTransferObject(TicklerLink entity) {
        TicklerLinkTo1 dto = new TicklerLinkTo1();
        BeanUtils.copyProperties(entity, dto); // Runtime reflection
        return dto;
    }
}

After (MapStruct - compile-time generation):

@Mapper(componentModel = "spring")
public interface TicklerMapper {
    TicklerLinkTo1 toDto(TicklerLink entity);
    TicklerLink toEntity(TicklerLinkTo1 dto);
    
    @Mapping(target = "id", ignore = true)
    void updateEntity(@MappingTarget TicklerLink target, TicklerLinkTo1 source);
}

@RestController
public class TicklerConverter {
    @Autowired
    private TicklerMapper ticklerMapper;
    
    public TicklerLinkTo1 getAsTransferObject(TicklerLink entity) {
        return ticklerMapper.toDto(entity); // Type-safe, no reflection
    }
}

Success Criteria

This evaluation should result in:

  • Decision document: Adopt MapStruct fully, partially, or not at all
  • If adopted: Migration plan with phased rollout strategy
  • If adopted: Developer documentation and code templates
  • Performance benchmarks comparing MapStruct vs Spring BeanUtils
  • Security analysis confirming elimination of reflection-based risks

Priority

Medium - This is a long-term improvement for security and performance. Spring BeanUtils (Phase 1) already eliminated the CVE exposure, so this is about incremental improvement rather than urgent remediation.

Dependencies

Proposed dependency:

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.6.3</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.6.3</version>
    <scope>provided</scope>
</dependency>

Related

Resources


Note: This issue is for evaluation only. Implementation would be tracked in separate issues for each migration area if we decide to proceed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions