@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.