0

I have a Spring bean which refers connection factory to access J2C resource. This code is deployed in webSphere server in 2 jvms load balanced. I had the readAuth method as init-method in bean xml but it was called multiple times during a load test. Since Spring singleton is per bean per container, I assumed there are multiple containers causing it to load multiple times. So I removed the init-method and changed the username and password to static and added null check in get methods. But now also, readAuth method is being called multiple times. I want to ensure this method is called only once per jvm since this method access server resource and connection is timing out during load test. Please suggest a best approach on how to write this class. Thanks in advance.

    <bean id="J2CUtils"
        class="test.J2CUtils">
        <property name="connectionFactory" ref="connectionFactory" />
    </bean>
    <jee:jndi-lookup id="connectionFactory" jndi-name="eis/J2CAuth" />

public class J2Ctils {
    private ConnectionFactory connectionFactory;
    private static String userName;
    private static String password;

    private void readAuth() throws ResourceException {
        System.out.println("Auth loaded");
            Connection conn = connectionFactory.getConnection();
            Interaction interaction = (Interaction) conn.createInteraction();
            Config config = interaction.getConfig();
            userName = config.getUserName();
            password = config.getPassword();
    }
    public String getUserName() {
        if(null == userName) {
            readAuth();
        }
        return userName;
    }
    public String getPassword() {
        if(null == password) {
            readAuth();
        }
        return password;
    }
    public void setConnectionFactory(ConnectionFactory connectionFactory) {
        this.connectionFactory = connectionFactory;
    }
}
Gokul
  • 1
  • 1

1 Answers1

0

Singletons or static methods don't help if you want to access a resource exactly once because every member of the cluster has it's own instance of the class.

Take in mind that neither the Java EE specification the Spring specification do define any kind of cluster behavior. You need to search for specific vendor solution to achieve this kind of requirement. Just as an example see have a look at @ApplicationScped in a cluster.

Other approaches to archive the expected behaviour are using a distributed lock like Zookeeper or maybe even a Queue with duplicate message filter.

Community
  • 1
  • 1
andih
  • 5,570
  • 3
  • 26
  • 36
  • There are 2 jvms in the cluster. I am okay if there are one instance per jvm in the cluster. But load test for 2 mins and 5 mins showed the method being called 7 and 12 times. And for 30,000 requests, I got around 100 connection timeouts with 4 jvms. So my intent is to avoid these connection timeouts. Is there a way we can ensure only once instance per jvm using Static class/method/variables? – Gokul May 15 '17 at 13:44
  • Per default Spring Beans are Singletons, i.e. they exist only once per JVM. If you mark `getUserName()` and `getPassword()` as `synchronized` `readAuth()` will only be called once per bean except username or password are `null` or the spring context gets reloaded. – andih May 15 '17 at 14:32