4

I have set qualifier name from properties file as isomessage.qualifier=isoMessageMember1:

public class BankBancsConnectImpl implements BankBancsConnect{

    @Autowired
    @Resource(name="${isomessage.qualifier}")
    private Iso8583Message iso8583Message;

    public BancsConnectTransferComp getFundTransfer(IpsDcBatchDetail ipsDcBatchDetail) {
        bancsxfr = iso8583Message.getFundTransfer(bancsxfr);
    }
}

The value of ${isomessage.qualifier} is static as it is defined in the properties file. However i want it to be dynamic and get it's value from database based on certain condition. For instance i have multiple implementation of Iso8583Message (member wise) and has to call respective class of member id that is currently logged in. Please guide me to achieve this in the best and java spring way.

And my implementation class will look like this:

@Service("isoMessageMember1")
public class Iso8583MessageEBLImpl implements Iso8583Message{
    public BancsConnectTransferComp getFundTransfer(BancsConnectTransferComp bancsxfr) throws Exception {
    ...
    }
nbrooks
  • 18,126
  • 5
  • 54
  • 66

2 Answers2

0

You can use Condition instead Qualifier if you are using Spring4+.

  1. First, you need a ConfigDAO which read the qualifier name which you need from database.

    public class ConfigDAO {
    
        public static String readFromDataSource() {
            return " ";
        }
    }
    
  2. Suppose there are two implemetions of Iso8583Message, you can create two Condition objects.

    IsoMessageMember1_Condition

    public class IsoMessageMember1_Condition implements Condition { 
    
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            String qualifier = ConfigDAO.readFromDataSource();
            if (qualifier.equals("IsoMessageMember1_Condition")) {
                return true;
            } else {
                return false;
            }
        }
    }
    

    IsoMessageMember2_Condition

    public class IsoMessageMember2_Condition implements Condition {
    
        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            String qualifier = ConfigDAO.readFromDataSource();
            if (qualifier.equals("IsoMessageMember2_Condition")) {
                return true;
            } else {
                return false;
            }
        }
    }
    
  3. Return different implemetion according to condition in config class.

    @Configuration
    public class MessageConfiguration {
    
        @Bean(name = "iso8583Message")
        @Conditional(IsoMessageMember1_Condition.class)
        public Iso8583Message isoMessageMember1() {
            return new Iso8583MessageEBLImpl();
        }
    
        @Bean(name = "iso8583Message")
        @Conditional(IsoMessageMember2_Condition.class)
        public Iso8583Message isoMessageMember2() {
            return new OtherMessageEBLImpl();
        }
    }
    
  4. Remove the @Qulifier and @Autowire annotations which you do not need anymore, you can retrieve the message from context every time you use it.

    public class BankBancsConnectImpl implements BankBancsConnect{
    
        private Iso8583Message iso8583Message;
    
        public BancsConnectTransferComp getFundTransfer(IpsDcBatchDetail ipsDcBatchDetail) {
            iso8583Message = (Iso8583Message)context.getBean("iso8583Message");
            bancsxfr = iso8583Message.getFundTransfer(bancsxfr);
        }
    }
    
xingbin
  • 27,410
  • 9
  • 53
  • 103
  • Here i see two limitation in my case: 1. I have 50+ implementation classes and expecting more to it as member increases. 2. The condition is event based ie, String qualifier = ConfigDAO.readFromDataSource(String memberId); The value of memberId is dependent on the selection by the user at the time of transaction. – Diwas Sapkota Feb 03 '18 at 09:38
  • @DiwasSapkota I see.. May be you can create a List, and retrieve concrete implemetion from the List at runtime according to memberId. – xingbin Feb 03 '18 at 09:51
  • I'll be glad if you can share me some of the example. – Diwas Sapkota Feb 03 '18 at 11:32
  • 1
    @DiwasSapkota https://stackoverflow.com/questions/15284851/spring-3-dynamic-autowiring-at-runtime-based-on-another-object-attribute – xingbin Feb 03 '18 at 13:44
0

In spring it is possible to autowire the application context, and retrieve any bean based on its name. For example, your interface signature similar to the below syntax

 public interface Iso8583Message {
        public String getFundDetails(String uniqueId);
    }

and 2 different implementations follow below format

@Service("iso8583-message1")
public class Iso8583MessageImpl1 implements Iso8583Message {
    @Override
    public String getFundDetails(String uniqueId) {
        return "Iso8583MessageImpl1 details ";
    }
}

and

@Service("iso8583-message2")
public class Iso8583MessageImpl2 implements Iso8583Message {
@Override
public String getFundDetails(String uniqueId) {
     return "Iso8583MessageImpl2 details ";
   }
}

We can retrieve the beans as follows

    public class BankBancsConnectImpl implements BankBancsConnect{

           @Autowired
            private ApplicationContext applicationContext;


            public BancsConnectTransferComp getFundTransfer(IpsDcBatchDetail 
             ipsDcBatchDetail) {
            //for retrieving 1st implementation
            Iso8583Message iso8583Message=applicationContext.getBean("iso8583-message1", Iso8583Message.class);
           //For retrieving 2nd implementation
            Iso8583Message iso8583Message=applicationContext.getBean("iso8583-message2", Iso8583Message.class);
                String result = iso8583Message.getFundTransfer(bancsxfr);
            }
        }

In this case, we can configure the bean names coming from the database instead of hard coded values("iso8583-message1","iso8583-message2").

Vineeth Bhaskaran
  • 2,161
  • 1
  • 29
  • 36