Tuesday, 29 May 2018

Spring Boot JMS integrated with Oracle Weblogic JMS API - Subscriber Code

In my previous post I demonstrated the publisher code to create and send a text message over a weblogic JMS queue.

In this post, we will be seeing the subscriber code required to receive the message sent by the sender. For this, We will create a spring starter project and the project structure should be like :


In my previous post I explained the steps to create a Spring starter project with required JMS libs.

Let's create the required classes stey by step.

1. We will be creating a configuration class. JMSConfig 

@Configuration
@EnableJms
public class JMSConfig {
 
 @Bean
 public JndiTemplate createJndiTemplate() {
  JndiTemplate jndi = new JndiTemplate();
  Properties jndiProperties = new Properties();
  jndiProperties.setProperty("java.naming.factory.initial","weblogic.jndi.WLInitialContextFactory");
  jndiProperties.setProperty("java.naming.provider.url","t3://localhost:7001");
  
  jndi.setEnvironment(jndiProperties);
  return jndi;
 }
 
 @Bean(name="CF")
 public JndiObjectFactoryBean createJndiObjectFactoryBean(@Autowired final JndiTemplate jndiTemplate) {
  JndiObjectFactoryBean factory = new JndiObjectFactoryBean();
  
  factory.setJndiTemplate(jndiTemplate);
  factory.setJndiName("/com/jms/dev/cf");
  
  factory.setProxyInterface(ConnectionFactory.class);
  return factory; 
 }
 
 @Bean(name="Queue")
 public JndiObjectFactoryBean createQueue(@Autowired final JndiTemplate jndiTemplate) {
  JndiObjectFactoryBean factory = new JndiObjectFactoryBean();
  
  factory.setJndiTemplate(jndiTemplate);
  factory.setJndiName("/com/jms/dev/distqueue");
  
  factory.setProxyInterface(Destination.class);
  return factory; 
 }
 
 @Bean 
 public JndiDestinationResolver createJndiDestinationResolver(@Autowired final JndiTemplate jndiTemplate) {
  JndiDestinationResolver destResolver = new JndiDestinationResolver();
  destResolver.setJndiTemplate(jndiTemplate);
  destResolver.setCache(true);
  
  return destResolver;
 }
 
 @Bean
 public JmsTemplate createJmsTemplate(@Autowired final ConnectionFactory connectionFactory, @Autowired final DestinationResolver destinationResolver) {
  JmsTemplate template = new  JmsTemplate();
  template.setConnectionFactory(connectionFactory);
  
  template.setDestinationResolver(destinationResolver);
  
  return template;
 }
 
 @Bean
 public JMSMessageReceiver createReceiver(@Autowired final JmsTemplate template) {
  
  JMSMessageReceiver receiver = new JMSMessageReceiver();
  receiver.setTemplate(template);
  return receiver;
 }
 
 @Bean
 public DefaultMessageListenerContainer createListener(@Autowired final JMSMessageReceiver mylistener, @Autowired final JndiTemplate jndiTemplate, @Autowired ConnectionFactory conFactory, @Autowired Destination destination) {
  DefaultMessageListenerContainer listener = new DefaultMessageListenerContainer();
  listener.setConcurrentConsumers(15);
  listener.setMessageListener(mylistener);
  listener.setDestination(destination);
  listener.setConnectionFactory(conFactory);
  return listener;
 }
}


The configuration class is similar to what we saw for the Producer Application. So I will not be dissecting this class.

2. Next, we will create a spring bean JMSMessageReceiver to receive the messages sent by the producer

public class JMSMessageReceiver {

 @Autowired
 private JmsTemplate template;
 @Value("/com/jms/dev/distqueue")
 private String destination;
 private static final Logger LOGGER = LoggerFactory.getLogger(JMSMessageReceiver.class);
 
 public void receiveMessage() throws JMSException {
  
  
  String message = (String)template.receiveAndConvert(destination);
  Message msg = template.receive(destination);
  
  
  
  LOGGER.info("\n\n\n======Received Message : "+message+" at : "+LocalDateTime.now());
  LOGGER.info("======Correlation Id ======"+msg.getJMSCorrelationID()+"\n\n\n");
 }

 public void setTemplate(JmsTemplate template) {
  this.template = template;
 }

 

}


The JMSMessageReceiver bean has jmsTemplate and destination instances autowired from JmsConfig class, the receiveMessage() method listens for the message on the queue "com/jms/dev/distqueue", the template.receive() method is a blocking operation and waits till the receivetimeout has been burst. Once we receive the message we are just logging it.

If you have any questions regarding the setup or any issues during implementation, please comment down below.

Thanks.

  

Monday, 28 May 2018

Spring Boot JMS integrated with Oracle Weblogic JMS API

As part of this example I will be creating a JMS queue using spring JMS API, which will be leveraging the JMS capability from the Oracle Weblogic Server. In this post I will be demonstrating only the publisher code which will create a text message and publish it on to a JMS queue. I will be using eclipse as my IDE with below versions for libraries.

1. spring boot - 1.5.10.RELEASE
2. weblogic-t3thinclient ( mvn install this jar locally from WL_HOME)

Firstly, we will create a Spring boot starter Project with JMS checkbox checked. This option will include all the required jars.

Follow along the below steps to create a Spring boot project in eclipse with the required classes.

1. Create a spring starter project in eclipse




2. Don't forget to include the JMS libraries while creating the project


3. This will be our resulting project structure.




4. Create  the Spring boot configuration through  Java class JmsConfig.java


@Configuration
@EnableJms
public class JmsConfig {

 @Bean
 public JndiTemplate createJndiTemplate() {
  JndiTemplate jndi = new JndiTemplate();
  Properties jndiProperties = new Properties();
  jndiProperties.setProperty("java.naming.factory.initial","weblogic.jndi.WLInitialContextFactory");
  jndiProperties.setProperty("java.naming.provider.url","t3://localhost:7001");
  
  jndi.setEnvironment(jndiProperties);
  return jndi;
 }
 
 @Bean
 public JndiObjectFactoryBean createJndiObjectFactoryBean(@Autowired final JndiTemplate jndiTemplate) {
  JndiObjectFactoryBean factory = new JndiObjectFactoryBean();
  
  factory.setJndiTemplate(jndiTemplate);
  factory.setJndiName("/com/jms/dev/cf");
  
  factory.setProxyInterface(ConnectionFactory.class);
  return factory; 
 }
 
 
 @Bean 
 public JndiDestinationResolver createJndiDestinationResolver(@Autowired final JndiTemplate jndiTemplate) {
  JndiDestinationResolver destResolver = new JndiDestinationResolver();
  destResolver.setJndiTemplate(jndiTemplate);
  destResolver.setCache(true);
  
  return destResolver;
 }
 
 @Bean
 public JmsTemplate createJmsTemplate(@Autowired final ConnectionFactory connectionFactory, @Autowired final DestinationResolver destinationResolver) {
  JmsTemplate template = new  JmsTemplate();
  template.setConnectionFactory(connectionFactory);
  
  template.setDestinationResolver(destinationResolver);
  
  return template;
 }
 
 @Bean
 public SpringWeblogicJmsPublisherApplication createSender(@Autowired final JmsTemplate jmsTemplate) {
  SpringWeblogicJmsPublisherApplication sender = new SpringWeblogicJmsPublisherApplication();
  sender.setJmsTemplate(jmsTemplate);
  sender.setDestination("/com/jms/dev/distqueue");
  return sender;
 }
}


In this configuration class, first I am creating a JNDITemplate using the weblogic initial context factory as we have to use the JMS queues configured on weblogic server, then we will create a JndiObjectFactoryBean which will serve as a ConnectionFactory for us, based upon which we will create a JmsTemplate for the queue /com/jms/dev/cf . 


5. Create a class SpringWeblogicJmsPublisherApplication  with below code
@SpringBootApplication
public class SpringWeblogicJmsPublisherApplication {

 private static final Logger LOG = LoggerFactory.getLogger(SpringWeblogicJmsPublisherApplication.class);
 private String destination;

 public String getDestination() {
  return destination;
 }

 public void setDestination(String destination) {
  this.destination = destination;
 }
 public static void main(String[] args) {
  ConfigurableApplicationContext context = SpringApplication.run(SpringWeblogicJmsPublisherApplication.class, args);
  JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
  
  jmsTemplate.convertAndSend(destination, "Hello To Weblogic 12.1.3 Queue and JMS API", new CorrelationIdPostProcessor("Custom-Corrleation-Id"));
  
  
  LOG.info("Message sent ..!!!");

 }
 
 private class CorrelationIdPostProcessor implements MessagePostProcessor {
  private final String correlationId;

  public CorrelationIdPostProcessor(final String correlationId) {
   this.correlationId = correlationId;
  }

  @Override
  public Message postProcessMessage(Message message) throws JMSException {
   message.setJMSCorrelationID(correlationId);
   return message;
  }
 }
 
}


We have annotated this class with @SpringBootApplication  A single @SpringBootApplication annotation can be used to enable three features @EnableAutoConfiguration@ComponentScan , @Configuration next we are getting the jmsTemplate instance from our spring application context to send a text message to the specified destination(wired from config class).

In the next post, I will demonstrate the the subscriber code to receive the JMS message which we sent.
If you any questions regarding creation of queues on weblogic, please comment down below and I will get back to you.
Thanks.