Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autowiring inside abstract class made for mapstruct

I am trying to build a REST Controller using Spring. To format the data for readability and more integration, I have used Mapstruct. Here's how I wrote Mapper.

@Mapper
public abstract class DeviceDataMapper {

@Autowired
DeviceService deviceService;

public static DeviceDataMapper INSTANCE = Mappers.getMapper(DeviceDataMapper.class);

@Mappings({
    @Mapping(source = "deviceId", target = "iddevice"),
    @Mapping(source = "deviceName", target = "name")
})
public abstract TODevice deviceToTODevice(DeviceData device);

public DeviceData toDeviceToDeviceData(TODevice toDevice){
    DeviceData deviceData = new DeviceData();
    deviceData.setDeviceId(toDevice.getIddevice());
    deviceData.setDeviceName(toDevice.getName());
    deviceData.setDeviceTemplateId(toDevice.getDeviceTemplateId());
    try {
deviceData.setDeviceTemplateName(deviceService.findDeviceTemplateById(toDevice.getDeviceTemplateId()).getName());
    } catch (Exception e) {
        e.printStackTrace();
    }

    return deviceData;
}}

The API Controller function looks like this

@RequestMapping(value = "/{deviceId}",method = RequestMethod.GET)
public @ResponseBody DeviceData get(@PathVariable int deviceId) {
    DeviceData deviceData=new DeviceData();
    try {
        deviceData =    DeviceDataMapper.INSTANCE.toDeviceToDevice(deviceService.findOne(deviceId));
    } catch (Exception e) {
        e.printStackTrace();
    }
    return deviceData;
}

The output deviceData returns fine except for one detail. I couldn't get to this function deviceService.findDeviceTemplateById(toDevice.getDeviceTemplateId() (where deviceService is autowired). The error stack trace shows me NullPointerException. So I am wondering whether is there any general rule about the accessibility of the autowired resources in abstract class? Or is the way I am instantiating that makes this function inaccessible? What should I change to make it work? I have also tried with @Inject from javax.inject with same result.

like image 310
Abdul Wadhood Rehman Avatar asked May 08 '15 09:05

Abdul Wadhood Rehman


People also ask

Can we use @autowired in abstract class?

We can't use @Autowired on a constructor of an abstract class. Spring doesn't evaluate the @Autowired annotation on a constructor of an abstract class. The subclass should provide the necessary arguments to the super constructor.

Can we inject bean in abstract class?

Once ObjectB will be injected into ObjectA, ObjectA will be able to access ObjectB properties and methods. To inject ObjectB in ObjectA, a constructor or a setter make it possible. In both cases, ObjectB is injected in ObjectA. And thus, usable within ObjectA.

Can we create Bean for abstract class?

You don't. You only declare the beans which have a concrete subclass of that abstract class.

What is MapStruct used for?

MapStruct is a code generator tool that greatly simplifies the implementation of mappings between Java bean types based on a convention over configuration approach. The generated mapping code uses plain method invocations and thus is fast, type-safe, and easy to understand.


1 Answers

You could use Spring as the component model for the mapper:

@Mapper(componentModel="spring")
public abstract class DeviceDataMapper {
    ...
}

That way you can inject dependencies into it (e.g. other hand-written it uses) as well as inject the mapper into other classes instead of resorting to the INSTANCE pattern.

like image 158
Gunnar Avatar answered Sep 19 '22 23:09

Gunnar