Search code examples
javamapstruct

mapstruct - Use mapper from another package


I use mapstruct in my projects and it works fine for the straight forward way (All mapper in one package). Now I have the requirement to move one mapper to another package, but this doesn't work well.

working package structure (1):

de.zinnchen
├── dto
│   └── Car.java
├── entity
│   └── CarEntity.java
└── mapper
    └── a
        ├── CarMapper.java
        └── DateMapper.java

NOT working package structure (2):

de.zinnchen
├── dto
│   └── Car.java
├── entity
│   └── CarEntity.java
└── mapper
    ├── a
    │   └── CarMapper.java
    └── b
        └── DateMapper.java

my java files:

package de.zinnchen.dto;

import java.time.LocalDateTime;

public class Car {

  private String manufacturer;
  private String model;
  private String color;
  private LocalDateTime productionDate;
...
package de.zinnchen.entity;

import java.sql.Timestamp;
import java.time.Instant;
import java.time.LocalDateTime;

public class CarEntity {
  private String manufacturer;
  private String model;
  private String color;
  private Instant productionDate;
...
package de.zinnchen.mapper.a;

import de.zinnchen.dto.Car;
import de.zinnchen.entity.CarEntity;
import de.zinnchen.mapper.b.DateMapper;
import org.mapstruct.Mapper;

@Mapper(
    uses = DateMapper.class
)
public interface CarMapper {


  Car asDto(CarEntity entity);

  CarEntity asEntity(Car car);

}
package de.zinnchen.mapper.b;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;

public class DateMapper {

  LocalDateTime instantToLocalDateTime(Instant instant) {
    return instant
        .atZone(ZoneId.of("UTC"))
        .toLocalDateTime();
  }

  Instant LocalDateTimeToInstant(LocalDateTime localDateTime) {
    return localDateTime.toInstant(ZoneOffset.UTC);
  }
}

Once I try to compile the variant with mappers in different packages I get the following error message: Can't map property "Instant productionDate" to "LocalDateTime productionDate". Consider to declare/implement a mapping method: "LocalDateTime map(Instant value)".

Can you please help me for solving this problem?

Edit Resulting CarMapperImpl.java of package structure 1:

package de.zinnchen.mapper.a;

import de.zinnchen.dto.Car;
import de.zinnchen.entity.CarEntity;
import javax.annotation.processing.Generated;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2021-01-06T09:36:43+0100",
    comments = "version: 1.4.1.Final, compiler: javac, environment: Java 11.0.9.1 (AdoptOpenJDK)"
)
public class CarMapperImpl implements CarMapper {

    private final DateMapper dateMapper = new DateMapper();

    @Override
    public Car asDto(CarEntity entity) {
        if ( entity == null ) {
            return null;
        }

        Car car = new Car();

        car.setManufacturer( entity.getManufacturer() );
        car.setModel( entity.getModel() );
        car.setColor( entity.getColor() );
        car.setProductionDate( dateMapper.instantToLocalDateTime( entity.getProductionDate() ) );

        return car;
    }

    @Override
    public CarEntity asEntity(Car car) {
        if ( car == null ) {
            return null;
        }

        CarEntity carEntity = new CarEntity();

        carEntity.setManufacturer( car.getManufacturer() );
        carEntity.setModel( car.getModel() );
        carEntity.setColor( car.getColor() );
        carEntity.setProductionDate( dateMapper.LocalDateTimeToInstant( car.getProductionDate() ) );

        return carEntity;
    }
}

Solution

  • The reason why it isn't working is due to the fact that the methods in the DateMapper are package protected and are not available from other packages.

    So if you add public to the methods then it will work.