2787184
2787184

Reputation: 3871

How to create Autowire with custom constructor arguments

How to create Autowire in Spring with custom constructor arguments? following is my sample code. I am getting Could not autowire field; No default constructor found errors.I can't introduce default constructor as AbstractExecutor class does not have default constructor.

IExecutor

public interface IExecutor {
    Object execute();
}

AbstractExecutor

public abstract class AbstractExecutor implements IExecutor {
    private IInputPropertyBean inputObject;
    private IOutputPropertyBean outputObject;
    public AbstractExecutor(IInputPropertyBean inputObject, IOutputPropertyBean outputObject) {
        this.inputObject = inputObject;
        this.outputObject = outputObject;
    }
    public abstract boolean isValidInput(IInputPropertyBean inputObject) ;
    public abstract  IInputPropertyBean getInputValues(IInputPropertyBean inputObject);
    public abstract  IOutputPropertyBean process(IInputPropertyBean attribute);
    public abstract  IOutputPropertyBean getOutputValues(IInputPropertyBean inputObject, IOutputPropertyBean outputObject;
    @Override
    public Object execute(){
        if(isValidInput(inputObject)){
            IInputPropertyBean inputAttribute = getInputValues(inputObject);
            IOutputPropertyBean outputAttribute = process(inputAttribute);
            outputObject = (IOutputPropertyBean) getOutputValues(outputAttribute, outputObject);
            return outputObject;
        }
    }
}

UserExecutor

@Repository("userExecutor")
public class UserExecutor extends AbstractExecutor { 
    public UserExecutor(@Qualifier("userInput") IInputPropertyBean inputObject, @Qualifier("userOutput")IOutputPropertyBean outputObject) {
        super(inputObject, outputObject);
    }

//override methods
}

IInputPropertyBean

public interface IInputPropertyBean { }

IOutputPropertyBean

public interface IOutputPropertyBean { }

UserInput

@Component("userInput")
public class UserInput implements IInputPropertyBean { //user sepecific properties }

UserOutput

@Component("userOutput")
public class UserOutput implements IOutputPropertyBean { //user sepecific properties }

UserServiceImpl

@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    @Qualifier("userExecutor")
    private UserExecutor userExecutor;


    @Override
    public UserOutput userOperation(UserInput userInput, UserOutput userOutput) {
        // How to @Autowire UserExecutor with  userInput, userOutput comming in service parameter.

                //IExecutor executor = new UserExecutor(userInput, userOutput);
    //return (UserOutput) executor.execute();
    }
}

Upvotes: 0

Views: 1673

Answers (1)

manish
manish

Reputation: 20135

You are missing @Autowired on the UserExecutor constructor. The following will work:

@Repository("userExecutor")
public class UserExecutor extends AbstractExecutor {
  @Autowired
  public UserExecutor(@Qualifier("userInput") UserInput input
    , @Qualifier("userOutput") UserOutput output) { super(input, output); }
}

Working code available on Github.


You will also benefit from using generics.

public interface IInput {}
public interface IOutput {}

public interface IExecutor<I extends IInput, O extends IOutput> {
  O execute(I i);
}

public class AbstractExecutor<I extends IInput, O extends IOutput>
       implements IExecutor<I, O> {
  private final I input;
  private final O output;

  protected AbstractExecutor(I input, O output) {
    this.input = input;
    this.output = output;
  }

  public O execute(I i) {
    ...
  }
}

@Component
public class UserInput implements IInput {}
@Component
public class UserOutput implements IOutput {}
@Repository
public class UserExecutor extends AbstractExecutor<UserInput, UserOutput> {
  @Autowired
  public UserExecutor(UserInput input, UserOutput output) {
    super(input, output);
  }
}

public interface IUserService {
  UserOutput execute(UserInput input, UserOutput output);
}

@Service
public UserService implements IUserService {
  private final UserExecutor executor;

  @Autowired
  public UserService(UserExecutor executor) {
    this.executor = executor;
  }

  public UserOutput execute(UserInput input) {
    return executor.execute(input);
  }
}

You will avoid use of @Qualifier, Object and type-casting everywhere.

Upvotes: 1

Related Questions