Marthin
Marthin

Reputation: 6543

select spring bean during runtime

I have a problem to select the correct spring bean that should get injected. I need a way to tell the spring container what bean to inject depeding on the call to a previous class. I do all the spring bean wiring in xml.

My question: is this possible and if it is any reference on an implementation?

I have created some sample code to illustrate what i´m trying to accomplish. Feel free to change it so that it will work to get the correct ReportHeader bean injected depending on the selected reportType during runtime.

public enum ReportType{
    Credit,
    Annul   
}

public class ReportService {

    private ReportHeaderService reportHeaderService;
    private ReportType reportType;

    public ReportService (){}

    public setReportType(ReportType reportType){
        this.reportType = reportType;
    }

    public void setReportHeaderService(ReportHeaderService reportHeaderService){
        this.reportHeaderService = reportHeaderService;
    }

    private void generateHeader(){
        //i would like to call my service like this and have the correct bean injected to ReportHeader.
        reportHeaderService.generateHeader(reportType)
    }
}

public class ReportHeaderService {

    private ReportHeader reportHeader;

    //this will call the injected bean that needs to be selected accoring to the ReportType
    public void generateHeader(ReportType type){
        reportHeader.createHeader();
    }
}

public interface ReportHeader{
    public void createHeader();
}

public class CreditReportHeader implements ReportHeader{
    public void createHeader(){
        ..dostuff();
    }
}

public class AnnulReportHeader implements ReportHeader{
    public void createHeader(){
        ..dostuff();
    }
}

Upvotes: 0

Views: 318

Answers (2)

Debojit Saikia
Debojit Saikia

Reputation: 10632

You can define a ReportHeaderFactory to get the ReportHeader according to ReportType:

public class ReportHeaderFactory {
    private CreditReportHeader creditReportHeader;
    private AnnulReportHeader annulReportHeader;

    public ReportHeader getReportHeader(ReportType reportType) {
        switch (reportType) {
        case Credit:
            return creditReportHeader;
        case Annul:
            return annulReportHeader;
        default:
            throw new IllegalArgumentException("No Such Header");
        }
    }
}

Re-define the ReportHeaderService with an instance of ReportHeaderFactory:

public class ReportHeaderService {

    //private ReportHeader reportHeader;
    private ReportHeaderFactory headerFactory;

    //this will call the injected bean that needs to be selected accoring to the ReportType
    public void generateHeader(ReportType type){
        //reportHeader.createHeader();
        headerFactory.getReportHeader(type);
    }
}

As you are doing all the spring bean wiring in xml, you just need to make below entries in the config file:

    <bean id="ReportHeaderService" class="x.y.ReportHeaderService">
        <property name="headerFactory" ref="headerFactory" />
    </bean>

    <bean id="headerFactory" class="x.y.ReportHeaderFactory">
        <property name="creditReportHeader" ref="creditReportHeader" />
        <property name="annulReportHeader" ref="annulReportHeader" />
    </bean>

    <bean id="creditReportHeader" class="x.y.CreditReportHeaderImpl" />
    <bean id="annulReportHeader" class="x.y.AnnulReportHeaderImpl" />

Upvotes: 1

Adrian Shum
Adrian Shum

Reputation: 40036

Consider injecting a Map<ReportType, ReportHeader> to ReportHeaderService, so that generateHeader works as:

public class ReportHeaderService {

    private Map<ReportType, ReportHeader> reportHeaderMap;

    public void generateHeader(ReportType type){
        ReportHeader reportHeader = reportHeaderMap.get(type);
        if (reportHeader != null) {
            reportHeader.createHeader();
        }
    }
}

Upvotes: 3

Related Questions