Reputation: 97
I have a variable - "protected static Context jndi;" in my class where "Context" is an interface . When i try to access it in the below mentioned method, it generates the sonar violation mentioned in the title
public JMSQueueResource createQueueResource(String queueBindingName, String qcfBindingName, boolean messagePersisted, boolean autoAcknowledge, boolean nonJMS) throws JMSException, NamingException {
JMSQueueResource qResource = new JMSQueueResource();
try {
jndi = createInitialContext();
if (queueConnectionFactory == null) {
queueConnectionFactory = (QueueConnectionFactory) lookup(jndi, qcfBindingName);
}
qResource.theQueueConnection = queueConnectionFactory.createQueueConnection();
if (autoAcknowledge) {
qResource.theQueueSession = qResource.theQueueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
}
else {
qResource.theQueueSession = qResource.theQueueConnection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);
}
Queue queue = (Queue) lookup(jndi, queueBindingName);
//if (nonJMS && queue instanceof com.ibm.mq.jms.MQQueue) {
// com.ibm.mq.jms.MQQueue q = (com.ibm.mq.jms.MQQueue) queue;
// q.setTargetClient(JMSC.MQJMS_CLIENT_NONJMS_MQ);
//}
qResource.theQueueSender = qResource.theQueueSession.createSender(queue);
if (messagePersisted) {
qResource.theQueueSender.setDeliveryMode(DeliveryMode.PERSISTENT);
}
else {
qResource.theQueueSender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
}
qResource.theQueueConnection.start();
}
catch (JMSException jmse) {
throw jmse;
}
catch (NamingException ne) {
throw ne;
}
finally {
if(jndi != null){
jndi.close();
}
}
return qResource;
}
I could see there are suggestions like to use an Atomic Integer wrapper. What is the best fix for this problem?
Upvotes: 1
Views: 1939
Reputation: 564
The sonar violation is a valid one as mutating a static variable from an instance method can lead to some pretty messed up behavior like:
createQueueResource
method?Regarding the Java documentation, making it static and potentially accessed by multiple thread is a bad idea:
An InitialContext instance is not synchronized against concurrent access by multiple threads. Multiple threads each manipulating a different InitialContext instance need not synchronize. Threads that need to access a single InitialContext instance concurrently should synchronize amongst themselves and provide the necessary locking.
Having a local variable as suggested seems like a reasonable first way to avoid the warning and the related problems.
Whether the construction of the context is expensive depends also on the factory that is used to provide it.
First you need to worry about the correctness of the program, then you can optimize when you can test where the real bottlenecks are.
EDIT: This link should provide more insight into the Spring application context and how to leverage the dependency injection of the Spring container to make use of the Context instead of storing it in a variable in a class https://spring.io/understanding/application-context
Upvotes: 4