简体   繁体   中英

Accessing Reactive CRUD repository from MapStruct Mapper stuck in block()

I am somewhat new to Spring and have recently generated a JHipster monolith application with the WebFlux option. My current aim is to make it compatible with Firestore and implement some missing features like inserting document references. To do so, I am currently having the following structure:

  • A domain object class " Device " which holds a field String firmwareType;
  • A domain object class " FirmwareType "
  • A DTO object DeviceDTO which holds a field FirmwareType firmwareType;

Correspondingly, I also have the corresponding Repository (extending FirestoreReactiveRepository which extends ReactiveCrudRepository ) and Controller implementations, which all work fine. To perform the conversion from a "full object" of FirmwareType in the DTO-object to a String firmwareTypeId; in the Device-object, I implemented a MapStruct Mapper :

@Mapper(unmappedTargetPolicy = org.mapstruct.ReportingPolicy.IGNORE, componentModel = "spring")
public abstract class  DeviceMapper {

    private final Logger logger = LoggerFactory.getLogger(DeviceMapper.class);
    @Autowired
    protected FirmwareTypeRepository fwTypeRepo;

    public abstract Device dtoToDevice(DeviceDTO deviceDTO);

    public abstract DeviceDTO deviceToDto(Device device);

    public abstract List<DeviceDTO> devicesToDTOs(List<Device> devices);


    public abstract List<Device> dtosToDevices(List<DeviceDTO> dtos);

    public String map(FirmwareType value) {
        if (value == null || value.getId() == null || value.getId().isEmpty()) {
            return null;
        }
        return value.getId();
    }

    public FirmwareType map(String value) {
        if (value == null || value.isEmpty()) {
            return null;
        }
        return fwTypeRepo.findById(value).block(); // <<-- this gets stuck!
    }
}

The FirmwareTypeRepository which is autowired as fwTypeRepo field:

@Repository
public interface FirmwareTypeRepository extends FirestoreReactiveRepository<FirmwareType> {
    Mono<FirmwareType> findById(String id);
}

The corresponding map functions get called perfectly fine, but the fwTypeRepo.findById(..) call in the marked line (third-last line) seems to get stuck somewhere and never returns or throws an error. When the "fwTypeRepo" via its Controller-endpoint is called, it works without any issues.

I suppose it must be some kind of calling context issue or something? Is there another way to force a result by Mono synchronously than block?

Thanks for your help in advance, everyone!

Edit: At this point, I am sure it has something to do with Autowiring the Repository. It seems to not correctly do so / use the correct instance. While a customized Interface+Impl is called correctly, the underlying logic (from FirestoreReactive/ReactiveCrudRepository) doesn't seem to supply data correctly (also when @Autowire is used in other components.). I found some hints pointing at the package-structure but (ie Application class needs to be in a root package) but that isn't an issue.

Mapstruct is not reactive as i know so this approach won't work, you'll need mapstruct to return a mono that builds the object itself but that wouldn't make sense as it's a mapping lib which is only for doing blocking things.

Could try use 2 Mono/Mappers, 1 for each DB call and then just Mono.zip(dbCall1, dbCall2) and set the the mapped db call output into the other objects field.

var call1 = Mono.fromFuture(() -> db.loadObject1()).map(o -> mapper1.map(o));
var call2 = Mono.fromFuture(() -> db.loadObject2()).map(o -> mapper2.map(o));

Mono.zip(call1, call2)
  .map(t -> {
    var o1 = t.getT1();
    var o2 = t.getT2();
    o1.setField(o2);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM