Package org.mapstruct

Annotation Type Context


  • @Target(PARAMETER)
    @Retention(CLASS)
    public @interface Context
    Marks a parameter of a method to be treated as mapping context. Such parameters are passed to other mapping methods, @ObjectFactory methods or @BeforeMapping/@AfterMapping methods when applicable and can thus be used in custom code.

    The type of an @Context parameter is also inspected for @BeforeMapping/@AfterMapping methods, which are called on the provided context parameter value if applicable.

    Note: no null checks are performed before calling before/after mapping methods or object factory methods on @Context annotated parameters. The caller needs to make sure that no null are passed in that case.

    For generated code to call a method that is declared with @Context parameters, the declaration of the mapping method being generated needs to contain at least those (or assignable) @Context parameters as well. MapStruct will not create new instances of missing @Context parameters nor will it pass null instead.

    Example 1: Using @Context parameters for passing data down to hand-written property mapping methods and @BeforeMapping methods:

     
     // multiple @Context parameters can be added
     public abstract CarDto toCar(Car car, @Context VehicleRegistration context, @Context Locale localeToUse);
    
     protected OwnerManualDto translateOwnerManual(OwnerManual ownerManual, @Context Locale locale) {
         // manually implemented logic to translate the OwnerManual with the given Locale
     }
    
     @BeforeMapping
     protected void registerVehicle(Vehicle mappedVehicle, @Context VehicleRegistration context) {
         context.register( mappedVehicle );
     }
    
     @BeforeMapping
     protected void notCalled(Vehicle mappedVehicle, @Context DifferentMappingContextType context) {
         // not called, because no context parameter of type DifferentMappingContextType is available
         // within toCar(Car, VehicleRegistration, Locale)
     }
    
     // generates:
    
     public CarDto toCar(Car car, VehicleRegistration context, Locale localeToUse) {
         registerVehicle( car, context );
    
         if ( car == null ) {
             return null;
         }
    
         CarDto carDto = new CarDto();
    
         carDto.setOwnerManual( translateOwnerManual( car.getOwnerManual(), localeToUse );
         // more generated mapping code
    
         return carDto;
     }
     
     

    Example 2: Using an @Context parameter with a type that provides its own @ BeforeMapping methods to handle cycles in Graph structures:

     
     // type of the context parameter
     public class CyclicGraphContext {
         private Map<Object, Object> knownInstances = new IdentityHashMap<>();
    
         @BeforeMapping
         public <T extends NodeDto> T getMappedInstance(Object source, @TargetType Class<T> targetType) {
             return (T) knownInstances.get( source );
         }
    
         @BeforeMapping
         public void storeMappedInstance(Object source, @MappingTarget NodeDto target) {
             knownInstances.put( source, target );
         }
     }
    
     @Mapper
     public interface GraphMapper {
         NodeDto toNodeDto(Node node, @Context CyclicGraphContext cycleContext);
     }
    
    
     // generates:
    
     public NodeDto toNodeDto(Node node, CyclicGraphContext cycleContext) {
         NodeDto target = cycleContext.getMappedInstance( node, NodeDto.class );
         if ( target != null ) {
             return target;
         }
    
         if ( node == null ) {
             return null;
         }
    
         NodeDto nodeDto = new NodeDto();
    
         cycleContext.storeMappedInstance( node, nodeDto );
    
         nodeDto.setParent( toNodeDto( node.getParent(), cycleContext ) );
         List<NodeDto> list = nodeListToNodeDtoList( node.getChildren(), cycleContext );
         if ( list != null ) {
             nodeDto.setChildren( list );
         }
    
         // more mapping code
    
         return nodeDto;
     }
     
     

    Example 3: Using @Context parameters for creating an entity object by calling an @ObjectFactory methods:

     
     // type of the context parameter
     public class ContextObjectFactory {
         @PersistenceContext(unitName = "my-unit")
         private EntityManager em;
    
         @ObjectFactory
         public Valve create( String id ) {
            Query query = em.createNamedQuery("Valve.findById");
            query.setParameter("id", id);
            Valve result = query.getSingleResult();
            if ( result != null ) {
                result = new Valve( id );
            }
            return result;
         }
    
     }
    
     @Mapper
     public interface ContextWithObjectFactoryMapper {
         Valve map(ValveDto dto, @Context ContextObjectFactory factory, String id);
     }
    
    
     // generates:
     public class ContextWithObjectFactoryMapperImpl implements ContextWithObjectFactoryMapper {
    
       @Override
       public Valve map(ValveDto dto, ContextObjectFactory factory, String id) {
           if ( dto == null ) {
               return null;
           }
    
           Valve valve = factory.create( id );
    
           valve.setOneWay( dto.isOneWay() );
    
           return valve;
       }
     }
     
     
    Since:
    1.2
    Author:
    Andreas Gudian