Change JNDI Provider Dynamically

I have two standalone HornetQ servers (2.2.14) (backup servers) on the same computer; Consider this scenario:

  • Live server crashes, now the backup server is in real time.
  • Client A (does not know that the Live server has crashed) wants to connect to the Live server (he must look for his Factory connection with the JNDI server with the Live servers).
  • Client A cannot find the JNDI provider Live server , so it must connect to the backup server (it must look for its Factory connection with the JNDI provider backup server).

How can I change the JNDI provider (change URL) dynamically for client A? Is there a way to switch to another JNDI resource?

I have an integrated spring application and this is my applicationContext.xml:

<!-- Default JndiTemplate --> <bean id="defaultJndiTemplate" class="org.springframework.jndi.JndiTemplate"> <property name="environment"> <props> <prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop> <prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</prop> <prop key="java.naming.provider.url">jnp://localhost:1099</prop> </props> </property> </bean> <!-- Backup JndiTemplate --> <bean id="backupJndiTemplate" class="org.springframework.jndi.JndiTemplate"> <property name="environment"> <props> <prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop> <prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</prop> <prop key="java.naming.provider.url">jnp://localhost:2099</prop> </props> </property> </bean> <!-- Destinations --> <bean id="defaultDestination" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiTemplate" ref="defaultJndiTemplate" /> <property name="jndiName" value="/queue/exampleQueue" /> </bean> <!-- ConnectionFactories --> <bean id="defaultConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiTemplate" ref="defaultJndiTemplate" /> <property name="jndiName" value="/ConnectionFactory" /> </bean> <!-- JMS Template --> <bean name="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="defaultConnectionFactory" /> <property name="sessionTransacted" value="true" /> </bean> <!-- Message Producer --> <bean name="messageSender" class="messaging.producer.MessageSender"> <property name="jmsTemplate" ref="jmsTemplate" /> <property name="destination" ref="defaultDestination" /> </bean> 

Update: I can handle searching for a Factory connection from the current live serrver in my application this way: For each message

  • Check available JNDI provider (from the current server in real time)
  • find factory connection
  • send a message

Something like this (from my MessageSender class):

  //init initialContexts for live and backup servers public init() throws NamingException, CommunicationException { Hashtable<String, String> environment = new Hashtable<String, String>(); environment.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); environment.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); environment.put(Context.PROVIDER_URL, "jnp://localhost:1099"); initialContext_live = new InitialContext(environment); environment = new Hashtable<String, String>(); environment.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); environment.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); environment.put(Context.PROVIDER_URL, "jnp://localhost:2099"); initialContext_backup = new InitialContext(environment); jmsTemplate = new JmsTemplate(); } //Sending message to toQueue public void send(final AbstractMessage message, String toQueue) throws NamingException { Destination destination; try { connectionFactory = (ConnectionFactory)initialContext_live.lookup("/ConnectionFactory"); jmsTemplate.setConnectionFactory(connectionFactory); destination = (Destination) initialContext_live.lookup(toQueue); System.out.print("[to-live]-"); } catch(Exception e) //live server is down { connectionFactory = (ConnectionFactory)initialContext_backup.lookup("/ConnectionFactory"); jmsTemplate.setConnectionFactory(connectionFactory); destination = (Destination) initialContext_backup.lookup(toQueue); System.out.print("[to-backup]-"); } jmsTemplate.send(destination, new MessageCreator() { @Override public Message createMessage(Session session) throws JMSException { ObjectMessage objMessage = session.createObjectMessage(message); return objMessage; } }); System.out.println("[MessageSender] Message sent."); } 

But this is a very time (about one message in two seconds) !!!

+4
source share
1 answer

what I found here are two things.

first you set one global flag and set, if still conditions

 flag=true; if(flag){ try { connectionFactory = (ConnectionFactory)initialContext_live.lookup("/ConnectionFactory"); jmsTemplate.setConnectionFactory(connectionFactory); destination = (Destination) initialContext_live.lookup(toQueue); System.out.print("[to-live]-"); } }else{ connectionFactory = (ConnectionFactory)initialContext_backup.lookup("/ConnectionFactory"); jmsTemplate.setConnectionFactory(connectionFactory); destination = (Destination) initialContext_backup.lookup(toQueue); System.out.print("[to-backup]-"); } catch(Exception e) //live server is down { flag=false; connectionFactory = (ConnectionFactory)initialContext_backup.lookup("/ConnectionFactory"); jmsTemplate.setConnectionFactory(connectionFactory); destination = (Destination) initialContext_backup.lookup(toQueue); System.out.print("[to-backup]-"); } 

so here he won’t check the code for the live server if some connection lost between them connects directly to the backup server

and if your live server is installed, you can set the flag to true.

and the second in the catch block declares it for a specific exception instead of an exception. it also affects performance.

0
source

Source: https://habr.com/ru/post/1447168/


All Articles