Skip to content
Advertisement

Factory design patter Spring Boot double bean

@Component
public abstract class CommandBase {

    @Autowired
    WebServiceProxy nbiService;

    @Autowired
    OperationCacheRepository cacheRepository;

    public CommandBase(
            WebServiceProxy nbiService,
            OperationCacheRepository cacheRepository) {

        this.nbiService = nbiService;
        this.cacheRepository = cacheRepository;
    }

    public abstract void executeSPV(SpeedTestDTO stDTO) throws NBIException;

    public abstract long executeGPV(long guid, OperationCache operationCache) throws NBIException;
@Slf4j
public class DownloadDiagnosticsCommand extends CommandBase {

    public DownloadDiagnosticsCommand(WebServiceProxy nbiService, OperationCacheRepository cacheRepository) {
        super(nbiService, cacheRepository);
    }

    @Override
    public void executeSPV(SpeedTestDTO stDTO) throws NBIException {
        // some executable code
    }

    @Override
    public long executeGPV(long guid, OperationCache operationCache) throws NBIException {
        // some executable code
    }
}

@Slf4j
public class UploadDiagnosticsCommand extends CommandBase {

    public UploadDiagnosticsCommand(WebServiceProxy nbiService, OperationCacheRepository cacheRepository) {
        super(nbiService, cacheRepository);
    }

    @Override
    public void executeSPV(SpeedTestDTO stDTO) throws NBIException {
        // some executable code
    }

    @Override
    public long executeGPV(long guid, OperationCache operationCache) throws NBIException {
        //some executable code
    }
}

@Component
public class RFACommandFactory {

    @Autowired
    WebServiceProxy nbiServiceProxy;

    @Autowired
    OperationCacheRepository cacheRepository;

    public final CommandBase createCommand(final String measureType) {
        if ("download".equalsIgnoreCase(measureType)) {
            return new DownloadDiagnosticsCommand(nbiServiceProxy, cacheRepository);
        } else if ("upload".equalsIgnoreCase(measureType)) {
            return new UploadDiagnosticsCommand(nbiServiceProxy, cacheRepository);
        }
        return null;
    }
}

Calling method executeSPV from abstract class

@RestController
@RequestMapping("/rfa/speedtest/v1")
@Slf4j
public class Controller {

    @Autowired
    CommandBase command;

    @Autowired
    RFACommandFactory rfaCommandFactory;

    @PostMapping(value = "{id}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    private ResponseEntity<String> post(
            @PathVariable String assetId,
            @RequestBody Payload payload) {

        log.info("Received new payload:{}", payload);

        command = rfaCommandFactory.createCommand(speedTestDTO.getType());

        try {
            command.executeSPV(speedTestDTO);
        } catch (NBIException e) {
            log.info("NBIException", e);
            return new ResponseEntity(payload, HttpStatus.BAD_REQUEST);
        }
        return new ResponseEntity(payload, HttpStatus.CREATED);
    }
}

If I remove @Componet from Upload and Download classes I receive error I need to add Bean for abstrcat class CommndBase

If I use @Compoment on Upload and Download classes I receive dual Bean is useed… Field command in .Controller required a single bean, but 2 were found:

Advertisement

Answer

You should not use @Component for abstract class, because Spring context will not be able to initialize that bean. You should remove it then.

Another thing is the way you want to implement a factory pattern here – I recommend you the way described here: https://stackoverflow.com/a/39361500/14056755, refactored version https://stackoverflow.com/a/55060326/14056755.

Advertisement