JMS

Implementing SOA using Opensource Apache Camel JMS Component on WebLogic 12c

Hi,

In one of our previous example we have talked about how we can use “Apache Camel based EJB Client accessing the EJBs deployed on WebLogic 12c”, Now we will see how we can develop a simple Web Application using Apache Camel Servlet which will accept inputs form the user and then will process those inputs (like adding the input numbers) and then the generated HTMPL output will be send to the WebLogic JMS Queue.

As part of this example we are going to use the “org.apache.camel.component.jms.JmsComponent” and Apache Camel “servlet:” endpoint. The Camel JMS component is a general purpose JMS integration point that can be used to integrate Apache Camel with any JMS client library. Using the Camel JMS component, it is possible to define JMS consumer endpoints (at the start of a Camel route) and JMS producer endpoints (at the end of a Camel route). Similarly The servlet: component provides HTTP based endpoints for consuming HTTP requests that arrive at a HTTP endpoint that is bound to a published Servlet.

For more information on Camel JMS Endpoint can be found at : http://camel.apache.org/jms.html . This component allows messages to be sent to (or consumed from) a JMS Queue or Topic. It uses Spring’s JMS support for declarative transactions, including Spring’s JmsTemplate for sending and a MessageListenerContainer for consuming.

Apache Camel’s API and out-of-the-box components implement many common enterprise integration patterns (EIPs), making it relatively simple and easy to do integration tasks such as connecting web services, performing XSL transformations, logging audits, and more. Camel supports most of the Enterprise Integration Patterns. See: http://camel.apache.org/enterprise-integration-patterns.html

What this demo is about ?

As part of this demo we will see how to use Apache Camel based WAR on latest WebLogic 12.2.1 (12c). While running this demo we will learn about the following things:

1. How to develop a Apache Camel based Camel Servlet to accept http request param inputs and to process them.

2. How to use the Apache Camel JMS Component to send the JMS Message (processed data) to the WebLogic Queue.

3. How to deploy the Camel based WebApplication on WebLogic using WebLogic 12.2.1 using maven plugin “weblogic-maven-plugin”. If you get any kind of error while using this plugin then refer to the article How to use WebLogic 12c provided Maven Synchronization Plug-In ?

4. Configuring JMS Connection Factory and the JMS Queues using WLST.

5. We are going to use Apache Camel 2.16.0, Spring 4.1.6.RELEASE and WebLogic 12.2.1 release for this demo.

Configuring JMS Queue and ConnectionFactory

Step-1). First create a directory some where in our filesystem where we will be keeping our projects. We will create a directory as “CamelServlet_With_JMSEndpoint_Demo”

 $ mkdir -p Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo

 $ mkdir -p Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo/src/main/java/beans

 $ mkdir -p Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo/src/main/resources

 $ mkdir -p Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo/src/main/webapp/WEB-INF

Step-2). Lets write the “Camel-on-WebLogic12c/domains.properties” file where we will define all the properties which will be used by the WLST script to configure the JMS Queue and ConnectionFactory.

############ WebLogic 12c JMS Queue and Connection Factory related Configuration #########

# 1 - Connecting details
server.url = t3://localhost:7001
username = weblogic
password = weblogic1
 
# 2 - JMSServer details
jms.server.name = My_JMSServer
store.name = MyJDBCStore
tragated.jms.server.name = AdminServer
 
# 3 - SystemModule Details
system.module.name = My_SystemModule
tragated.system.module.name = AdminServer
 
# 4 - ConnectionFactory Details
connection.factory.name = My_ConnectionFactory
connection.factory.jndi.name = My_CF
 
# 5 - Unit Of Order Details
unit.of.order.value = 1
 
# 6 - SubDeployment & Queue Details
queue.sub.deployment.name = Sub_My_Queue
queue.name = My_Queue
queue.jndi.name = My_Q

Step-3). Now we will write a simple WLST Script which will use the above properties file and configure the JMS resources on WebLogic. Create a file as “Camel-on-WebLogic12c/configureJMS.py”

#############################################################################
#
# @author Copyright (c) 2010 - 2011 by Middleware Magic, All Rights Reserved.
#
#############################################################################
 
from java.io import FileInputStream
import java.lang
import os
import string
 
propInputStream = FileInputStream("domain.properties")
configProps = Properties()
configProps.load(propInputStream)
 
# 1 - Connecting details
serverUrl = configProps.get("server.url")
Username = configProps.get("username")
Password = configProps.get("password")
 
# 2 - JMSServer details
jmsServerName = configProps.get("jms.server.name")
storeName = configProps.get("store.name")
tragatedJMSServerName = configProps.get("tragated.jms.server.name")
 
# 3 - SystemModule Details
systemModuleName = configProps.get("system.module.name")
tragatedSystemModuleName = configProps.get("tragated.system.module.name")
 
# 4 - ConnectionFactory Details
connectionFactoryName = configProps.get("connection.factory.name")
ConnectionFactoryJNDIName = configProps.get("connection.factory.jndi.name")
 
# 5 - Unit Of Order Details
unitOfOrderValue = configProps.get("unit.of.order.value")
 
# 6 - SubDeployment & Queue Details
queueSubDeploymentName = configProps.get("queue.sub.deployment.name")
queueName = configProps.get("queue.name")
queueJNDIName = configProps.get("queue.jndi.name")
 
#7 - Weblogic Bridge Details:
weblogicDestinationBridge = configProps.get("weblogic.destination.bridge")
weblogicAdapterJNDINoTX = configProps.get("weblogic.adapter.jndi.name")

#8 - Widlfly bridge details:
wildflyDestinationBridge = configProps.get("wildfly.destination.bridge")
wildflyServerUrl = configProps.get("wildfly.server.url")
wildflyJMSUsername = configProps.get("wildfly.jms.username")
wildflyJMSUserPassword = configProps.get("wildfly.jms.password")
wildflyInitialContextFactory = configProps.get("wildfly.initial.context.factory")
wildflyJMSConnectionFactory = configProps.get("wildfly.remote.connection.factory.jndi.name")
wildflyJMSQueueJndi = configProps.get("wildfly.jms.destination.jndi.name")




redirect('wlst.log','false')
 
# 1 - Connecting to the Destination 
connect(Username,Password,serverUrl)
 
edit()
 
# 2 - JMSServer details
print "================== JMSSever ==================="
startEdit()
cmo.createJMSServer(jmsServerName)
print "Created a JMSServer !!"
cd('/Deployments/'+jmsServerName)
cmo.setPersistentStore(getMBean('/FileStores/'+storeName))
print "PersistentStore has been set for the JMSServer !!"
set('Targets',jarray.array([ObjectName('com.bea:Name='+tragatedJMSServerName+',Type=Server')], ObjectName))
print "Targeted the JMSServer !!"
activate()
print ""
 
# 3 - SystemModule Details
print "================== SystemModule ==================="
startEdit()
cd('/')
cmo.createJMSSystemResource(systemModuleName)
print "Created a SystemModule !!"
cd('/SystemResources/'+systemModuleName)
set('Targets',jarray.array([ObjectName('com.bea:Name='+tragatedSystemModuleName+',Type=Server')], ObjectName))
print "Targeted the SystemModule !!"
activate()
print ""
 
# 4 - ConnectionFactory Details
print "================== ConnectionFactory ==================="
startEdit()
cd('/JMSSystemResources/'+systemModuleName+'/JMSResource/'+systemModuleName)
cmo.createConnectionFactory(connectionFactoryName)
cd('/JMSSystemResources/'+systemModuleName+'/JMSResource/'+systemModuleName+'/ConnectionFactories/'+connectionFactoryName)
cmo.setJNDIName(ConnectionFactoryJNDIName)
print "Created a ConnectionFactory !!"
cd('/JMSSystemResources/'+systemModuleName+'/JMSResource/'+systemModuleName+'/ConnectionFactories/'+connectionFactoryName+'/SecurityParams/'+connectionFactoryName)
cmo.setAttachJMSXUserId(false)
cd('/JMSSystemResources/'+systemModuleName+'/JMSResource/'+systemModuleName+'/ConnectionFactories/'+connectionFactoryName)
cmo.setDefaultTargetingEnabled(true)
print "Targeted the ConnectionFactory !!"
activate()
print ""
 
# 5 - SubDeployment & Queue Details
print "================== SubDeployment & Queue ==================="
startEdit()
cd('/SystemResources/'+systemModuleName)
cmo.createSubDeployment(queueSubDeploymentName)
print "Created a SubDeployment for Queue !!"
cd('/JMSSystemResources/'+systemModuleName+'/JMSResource/'+systemModuleName)
cmo.createQueue(queueName)
print "Created a Queue !!"
cd('/JMSSystemResources/'+systemModuleName+'/JMSResource/'+systemModuleName+'/Queues/'+queueName)
cmo.setJNDIName(queueJNDIName)
cmo.setSubDeploymentName(queueSubDeploymentName)
cd('/SystemResources/'+systemModuleName+'/SubDeployments/'+queueSubDeploymentName)
set('Targets',jarray.array([ObjectName('com.bea:Name='+jmsServerName+',Type=JMSServer')], ObjectName))
print "Targeted the Queue to the created subdeployment !!"
activate()
print ""

cmd = "rm -f wlst.log"
os.system(cmd)

Step-4). Now we will start the WebLogic 12.2.1 instance and then we will open a terminal to run the above mentioned WLST script. We will run the “setWLSEnv.sh” script in the terminal first so that it will set the CLASSPATH properly with the required JARs.

$ cd /Users/jsensharma/NotBackedUp/Installed/wls1221/wlserver/server/bin

$ . ./setWLSEnv.sh 

CLASSPATH=/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/lib/tools.jar:/Users/jsensharma/NotBackedUp/Installed/wls1221/wlserver/modules/features/wlst.wls.classpath.jar:
PATH=/Users/jsensharma/NotBackedUp/Installed/wls1221/wlserver/server/bin:/Users/jsensharma/NotBackedUp/Installed/wls1221/wlserver/../oracle_common/modules/org.apache.ant_1.9.2/bin:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/bin:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/jsensharma/NotBackedUp/Installed/wls1221/wlserver/../oracle_common/modules/org.apache.maven_3.2.5/bin
Your environment has been set.

Step-5). Running the WLST script in the same terminal.

######  Running the WLST commands as following: #######

$ cd /PATH/TO/Camel-on-WebLogic12c

$ java weblogic.WLST configureJMS.py 

Initializing WebLogic Scripting Tool (WLST) ...
Welcome to WebLogic Server Administration Scripting Shell
Type help() for help on available commands

================== JMSSever ===================
Created a JMSServer !!
PersistentStore has been set for the JMSServer !!
Targeted the JMSServer !!

================== SystemModule ===================
Created a SystemModule !!
Targeted the SystemModule !!

================== ConnectionFactory ===================
Created a ConnectionFactory !!
Targeted the ConnectionFactory !!

================== SubDeployment & Queue ===================
Created a SubDeployment for Queue !!
Created a Queue !!
Targeted the Queue to the created subdeployment !!

Developing the Camel Based WebApp

Step-6). First of all we will write a Simple Bean which will include out business logic of adding two numbers and produce an HTML output containing the sum. For this we will write “MathBean.java” inside the “CamelServlet_With_JMSEndpoint_Demo/src/main/java/beans” as following:

package beans;

public class MathBean {
     private String firstNo="1000";
     private String secondNo="2000";

	public String getFirstNo() {
		return firstNo;
	}

	public void setFirstNo(String firstNo) {
		this.firstNo = firstNo;
	}

	public String getSecondNo() {
		return secondNo;
	}

	public void setSecondNo(String secondNo) {
		this.secondNo = secondNo;
	}
 
    public String addTwoNumbers(String firstNo, String secondNo) {
        System.out.println("[MathBean] addTwoNumbers("+firstNo+","+secondNo+") invoked.");
        int sum = Integer.parseInt(firstNo) + Integer.parseInt(secondNo);
        String result=    "<HTML>" +
                          "   <HEAD><TITLE> Add Numbers Camel Servlet test </TITLE></HEAD>" +
                          "   <BODY>" +
                          "       [MathBean] Sum of " +firstNo+" And "+secondNo+ " is = " + sum + 
                          "   </BODY>" +
                          "</HTML>";
            return result;
        }
}

Step-7). Now we will write a simple “web.xml” file as following which will define the CamelServlet and also declare the Spring “ContextLoaderListener” listener. In the same file we will define the Camel configuration file via “contextConfigLocation” context param. Place the “web.xml” file inside the “CamelServlet_With_JMSEndpoint_Demo/src/main/webapp/WEB-INF/”

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

  <display-name>Camel Servlet WAR</display-name>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:camel-config.xml</param-value>
  </context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <servlet>
    <servlet-name>CamelServlet</servlet-name>
    <servlet-class>org.apache.camel.component.servlet.CamelHttpTransportServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>CamelServlet</servlet-name>
    <url-pattern>/camel/*</url-pattern>
  </servlet-mapping>

</web-app>

Step-8). Now we will write a simple “index.html” page inside the “CamelServlet_With_JMSEndpoint_Demo/src/main/webapp/”. This Html page will simple provide a form to the user so that they can enter two number which will be later processed bu the camel servlet after submitting the HTML form.

<html>
	<body>
		<h2>MiddlewareMagic: Camel Add Servlet Demo</h2>
		<table>
			<form action="camel/addNumbers">
				<TR><TD>Enter First Number </TD> <TD><input type="text" name="firstNumber" value="200"/></TD></TR>
				<TR><TD>Enter Second Number </TD> <TD> <input type="text" name="secondNumber" value="300"/></TD></TR>
				<TR><TD><input type="reset" value="Clear"/> </TD> <TD> <input type="Submit" value="Add the Numbers and Store result in WebLogic JMS Queue My_Q" /></TD></TR>
			</form>
		</table>
	</body>
</html>

Step-9). Now we will write the Apache Camel context file “camel-config.xml” which defines how the various camel endpoints will work. In order to know more about this please refer to: http://camel.apache.org/configuring-camel.html
Lets create the “camel-config.xml” file inside “CamelServlet_With_JMSEndpoint_Demo/src/main/resources”

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring" xmlns:p="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

     <bean id="mathBean" class="beans.MathBean" />

     <camelContext xmlns="http://camel.apache.org/schema/spring">
       <route id="addNumbersRoute">
           <from uri="servlet:///addNumbers"/>
           <transform>
               <method bean="mathBean" method="addTwoNumbers(${header.firstNumber},${header.secondNumber})"/> 
           </transform>
           <inOnly uri="weblogicJMS:My_Q" />
       </route>
     </camelContext>


     <!-- WebLogic JndiTemplate Settings --> 
     <bean id="jmsJndiTemplate" class="org.springframework.jndi.JndiTemplate">
           <property name="environment">
              <props>
                 <prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
                 <prop key="java.naming.provider.url">t3://localhost:7001</prop>
              </props>
           </property>
     </bean>

     <bean id="jndiDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
          <property name="jndiTemplate" ref="jmsJndiTemplate"/>
     </bean>

     <bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
          <property name="jndiTemplate" ref="jmsJndiTemplate"/>
          <property name="jndiName" value="My_CF"/>
     </bean>
     
     <bean id="jmsConfiguration" class="org.apache.camel.component.jms.JmsConfiguration">
          <property name="connectionFactory" ref="jmsConnectionFactory"/>
          <property name="destinationResolver" ref="jndiDestinationResolver"/>
     </bean>
          
     <bean id="weblogicJMS" class="org.apache.camel.component.jms.JmsComponent">
          <property name="configuration" ref="jmsConfiguration" />
     </bean>

</beans>

Step-10). Now the most important part in which we will be writing the maven “pom.xml” which will compile and build the above artifacts and will package them as part fo a WAR file. We will be using the “weblogic-maven-plugin” Weblogic plugin in this pom sothat we can easily deploy the WAR to weblogic 12c as well.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

	<modelVersion>4.0.0</modelVersion>
	<groupId>my.camel.servlet.demo</groupId>
	<artifactId>HelloCamelServletWebApp</artifactId>
	<version>1.0</version>
	<packaging>war</packaging>
	<name>HelloCamelServletWebApp Demo</name>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<version.compiler.plugin>2.3.1</version.compiler.plugin>
		<maven.compiler.target>1.7</maven.compiler.target>
		<maven.compiler.source>1.7</maven.compiler.source>
		
		<!-- Camel and Spring related properties -->
		<version.apache.camel>2.16.0</version.apache.camel>
		<version.spring>4.1.6.RELEASE</version.spring>
		
		<!-- Weblogic Plugin related properties -->
		<middleware.home>/Users/jsensharma/NotBackedUp/Installed/wls1221</middleware.home>
        <admin.server.url>t3://localhost:7001</admin.server.url>
        <admin.username>weblogic</admin.username>
        <admin.password>weblogic1</admin.password>
	</properties>

	<dependencies>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${version.spring}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-spring</artifactId>
			<version>${version.apache.camel}</version>

			<!-- As we do not want the following JARs inside the "WEB-INF/lib" Hence excluding them : jaxb-api-2.2.7.jar jaxb-core-2.2.7.jar jaxb-impl-2.2.7.jar -->
			<exclusions>
				<exclusion>
					<groupId>com.sun.xml.bind</groupId>
					<artifactId>jaxb-api</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.xml.bind</groupId>
					<artifactId>jaxb-impl</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.xml.bind</groupId>
					<artifactId>jaxb-core</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.apache.camel</groupId>
			<artifactId>camel-servlet</artifactId>
			<version>${version.apache.camel}</version>
			<!-- As we do not want the following JARs inside the "WEB-INF/lib" Hence excluding them : jaxb-api-2.2.7.jar jaxb-core-2.2.7.jar jaxb-impl-2.2.7.jar -->
			<exclusions>
				<exclusion>
					<groupId>com.sun.xml.bind</groupId>
					<artifactId>jaxb-api</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.xml.bind</groupId>
					<artifactId>jaxb-impl</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.xml.bind</groupId>
					<artifactId>jaxb-core</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-jms</artifactId>
            <version>${version.apache.camel}</version>
			<!-- As we do not want the following JARs inside the "WEB-INF/lib" Hence excluding them : jaxb-api-2.2.7.jar jaxb-core-2.2.7.jar jaxb-impl-2.2.7.jar -->
			<exclusions>
				<exclusion>
					<groupId>com.sun.xml.bind</groupId>
					<artifactId>jaxb-api</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.xml.bind</groupId>
					<artifactId>jaxb-impl</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.xml.bind</groupId>
					<artifactId>jaxb-core</artifactId>
				</exclusion>
			</exclusions>
        </dependency>
	</dependencies>

	<build>
		<finalName>${project.artifactId}</finalName>
		<resources>
			<resource>
				<directory>src/main/resources</directory>
				<filtering>true</filtering>
			</resource>
		</resources>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>${version.compiler.plugin}</version>
				<configuration>
					<source>${maven.compiler.source}</source>
					<target>${maven.compiler.target}</target>
				</configuration>
			</plugin>
			
			<plugin>
                <groupId>com.oracle.weblogic</groupId> 
                <artifactId>weblogic-maven-plugin</artifactId> 
                <version>12.2.1-0-0</version> 
                <configuration> 
                    <middlewareHome>${middleware.home}</middlewareHome>
                    <adminurl>${admin.server.url}</adminurl>
                    <user>${admin.username}</user>
                    <password>${admin.password}</password>
                    <name>${project.build.finalName}</name>
                    <upload>true</upload> 
                    <action>deploy</action> 
                    <source>${project.build.directory}/${project.build.finalName}.${project.packaging}</source>          
                </configuration> 
            </plugin>
		</plugins>
	</build>

</project>

Building and Deploying the Camel WebApp

Now we are going to build and deploy the WebApplication to WebLogic 12.2.1 version. We will use Maven plugins to achieve the same. So before using the maven we need to setup the PATH and M2_HOME as following:

For Unix Based OS

$ export M2_HOME=/PATH/TO/apache_maven_3.2.3
$ export JAVA_HOME=/PATH/TO/jdk1.8.0_60
$ export PATH=$JAVA_HOME/bin:/PATH/TO/apache_maven_3.2.3/bin:$PATH

$ cd /PAYTH/TO/Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo
$ mvn clean install weblogic:deploy

For Windows Based OS

$ set M2_HOME=C:\PATH\TO\apache_maven_3.2.3
$ set JAVA_HOME=C:\PATH\TO\jdk1.8.0_60
$ set PATH=%JAVA_HOME%/bin;C:\PATH\TO\apache_maven_3.2.3\bin;%PATH%

$ cd C:\Camel-on-WebLogic12c\CamelServlet_With_JMSEndpoint_Demo
$ mvn clean install  weblogic:deploy

Step-11). Now we are going to build and deploy it on WebLogic as following using mvn clean install weblogic:deploy:


$ cd CamelServlet_With_JMSEndpoint_Demo

$  mvn clean install weblogic:deploy

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building HelloCamelServletWebApp Demo 1.0
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ HelloCamelServletWebApp ---
[INFO] Deleting /Users/jsensharma/NotBackedUp/MM_Tests/WLS/Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo/target
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ HelloCamelServletWebApp ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.1:compile (default-compile) @ HelloCamelServletWebApp ---
[INFO] Compiling 1 source file to /Users/jsensharma/NotBackedUp/MM_Tests/WLS/Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ HelloCamelServletWebApp ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/jsensharma/NotBackedUp/MM_Tests/WLS/Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:2.3.1:testCompile (default-testCompile) @ HelloCamelServletWebApp ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ HelloCamelServletWebApp ---
[INFO] No tests to run.
[INFO] 
[INFO] --- maven-war-plugin:2.2:war (default-war) @ HelloCamelServletWebApp ---
[INFO] Packaging webapp
[INFO] Assembling webapp [HelloCamelServletWebApp] in [/Users/jsensharma/NotBackedUp/MM_Tests/WLS/Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo/target/HelloCamelServletWebApp]
[INFO] Processing war project
[INFO] Copying webapp resources [/Users/jsensharma/NotBackedUp/MM_Tests/WLS/Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo/src/main/webapp]
[INFO] Webapp assembled in [45 msecs]
[INFO] Building war: /Users/jsensharma/NotBackedUp/MM_Tests/WLS/Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo/target/HelloCamelServletWebApp.war
[INFO] WEB-INF/web.xml already added, skipping
[INFO] 
[INFO] --- maven-install-plugin:2.4:install (default-install) @ HelloCamelServletWebApp ---
[INFO] Installing /Users/jsensharma/NotBackedUp/MM_Tests/WLS/Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo/target/HelloCamelServletWebApp.war to /Users/jsensharma/.m2/repository/my/camel/servlet/demo/HelloCamelServletWebApp/1.0/HelloCamelServletWebApp-1.0.war
[INFO] Installing /Users/jsensharma/NotBackedUp/MM_Tests/WLS/Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo/pom.xml to /Users/jsensharma/.m2/repository/my/camel/servlet/demo/HelloCamelServletWebApp/1.0/HelloCamelServletWebApp-1.0.pom
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building HelloCamelServletWebApp Demo 1.0
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- weblogic-maven-plugin:12.2.1-0-0:deploy (default-cli) @ HelloCamelServletWebApp ---
weblogic.Deployer invoked with options:  -noexit -deploy -username weblogic -name HelloCamelServletWebApp -source /Users/jsensharma/NotBackedUp/MM_Tests/WLS/Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo/target/HelloCamelServletWebApp.war -upload -adminurl t3://localhost:7001
<Dec 13, 2015 5:49:59 PM IST> <Info> <J2EE Deployment SPI> <BEA-260121> <Initiating deploy operation for application, HelloCamelServletWebApp [archive: /Users/jsensharma/NotBackedUp/MM_Tests/WLS/Camel-on-WebLogic12c/CamelServlet_With_JMSEndpoint_Demo/target/HelloCamelServletWebApp.war], to configured targets.> 
Task 6 initiated: [Deployer:149026]deploy application HelloCamelServletWebApp on AdminServer.
Task 6 completed: [Deployer:149026]deploy application HelloCamelServletWebApp on AdminServer.
Target state: deploy completed on Server AdminServer

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.831 s
[INFO] Finished at: 2015-12-13T17:50:01+05:30
[INFO] Final Memory: 37M/699M
[INFO] ------------------------------------------------------------------------

Once the Application is deployed on WebLogic we should be able to see the following kind of output on weblogic logs which indicates that the camel context is initialized.

Output on WebLogic console.


Dec 13, 2015 5:50:00 PM org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization started
Dec 13, 2015 5:50:00 PM org.springframework.web.context.support.XmlWebApplicationContext prepareRefresh
INFO: Refreshing Root WebApplicationContext: startup date [Sun Dec 13 17:50:00 IST 2015]; root of context hierarchy
Dec 13, 2015 5:50:00 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [camel-config.xml]
Dec 13, 2015 5:50:00 PM org.apache.camel.impl.DefaultCamelContext start
INFO: Apache Camel 2.16.0 (CamelContext: camel-1) is starting
Dec 13, 2015 5:50:00 PM org.apache.camel.management.ManagedManagementStrategy doStart
INFO: JMX is enabled
Dec 13, 2015 5:50:00 PM org.apache.camel.impl.converter.DefaultTypeConverter doStart
INFO: Loaded 189 type converters
Dec 13, 2015 5:50:00 PM org.apache.camel.impl.DefaultRuntimeEndpointRegistry doStart
INFO: Runtime endpoint registry is in extended mode gathering usage statistics of all incoming and outgoing endpoints (cache limit: 1000)
Dec 13, 2015 5:50:00 PM org.apache.camel.impl.DefaultCamelContext doStartCamel
INFO: AllowUseOriginalMessage is enabled. If access to the original message is not needed, then its recommended to turn this option off as it may improve performance.
Dec 13, 2015 5:50:00 PM org.apache.camel.impl.DefaultCamelContext doStartCamel
INFO: StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at http://camel.apache.org/stream-caching.html
Dec 13, 2015 5:50:01 PM org.apache.camel.impl.DefaultCamelContext doStartOrResumeRouteConsumers
INFO: Route: addNumbersRoute started and consuming from: Endpoint[servlet:///addNumbers]
Dec 13, 2015 5:50:01 PM org.apache.camel.impl.DefaultCamelContext start
INFO: Total 1 routes, of which 1 is started.
Dec 13, 2015 5:50:01 PM org.apache.camel.impl.DefaultCamelContext start
INFO: Apache Camel 2.16.0 (CamelContext: camel-1) started in 0.156 seconds
Dec 13, 2015 5:50:01 PM org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization completed in 898 ms
Dec 13, 2015 5:50:01 PM org.apache.camel.component.servlet.CamelHttpTransportServlet init
INFO: Initialized CamelHttpTransportServlet[name=CamelServlet, contextPath=/HelloCamelServletWebApp]

Testing the Web Application

Now as the application is deployed on WebLogic 12.2.1 hence lets access the URL and submit the form:

http://localhost:7001/HelloCamelServletWebApp/
OR
http://localhost:7001/HelloCamelServletWebApp/camel/addNumbers?firstNumber=200&secondNumber=300

As soon as we submit the data (two numbers) in the form presented by the application we will be able to see that the JMS Queue has got a JMS Message in it.

Listing JMS Queue Messages on WLS Console

Listing JMS Queue Messages on WLS Console

Source Code:
The Source code for this demo can be found at:

https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/WebLogic/JMS/Camel-on-WebLogic12c
.
.

Regards
Jay SenSharma


WebLogic 12c JMS Bridge to connect to WildFly 8.2 HornetQ Broker.

Hi,

As part of this article we will see how to configure a JMS Message bridge on WebLogic 12c side so that any message sent to the JMS Queue present on WebLogic will be automatically transfered to WildFly 8.2 Instance. The WebLogic Messaging Bridge is a forwarding mechanism that provides interoperability between WebLogic JMS implementations, and between JMS and other messaging products. We are going to use the Messaging Bridge to integrate WildFly 8.2 offered HornetQ messaging broker communication. A messaging bridge instance forwards messages between a pair of bridge source and target destinations. These destinations are mapped to a pair of bridge source and target destinations. The messaging bridge reads messages from the source bridge destination and forwards those messages to the target bridge destination.

In order to know how to create a WebLogic Message bridge between WebLogic and JBoss 5 please refer to : http://middlewaremagic.com/weblogic/?p=6066

As part of this article we will learn:

1). How to create a WebLogic Message Bridge using WLST.
2). How to create a JMS Queue on WildFly 8.2 side.
NOTE: These steps will remain almost same for JBoss AS7 or JBoss EAP6, the only change will be in the Connection URL of WildFly or JBossAS. In WildFly we use “http-remoting://localhost:8080” where as in JBossAS7/EAP6 we use “remote://localhost:4447”).
3). Then we will send some messages to WebLogic JMS Queues and will receive them from WildFly 8.2 JMS Queues.

Creating A Simple JMS Queue on WildFLy 8.2 side

Step-1). Start the WildFly 8.2 (or JBoss EAP6/JBossAS7) full profile (which has messaging) as following:

   $ cd /PATH/TO/wildfly-8.2.1.Final/bin
   $ ./standalone.sh -c standalone-full.xml

I am running Weblogic 12c and WildFLy on the same host hence i am running both on “localhost” users can change it based on their need.

Step-2). Create a simple JMS user on WildFly 8.2 side and this user must belong to “guest” role. Please see the “messaging subsystem” configuration of “standalone-full.xml” to know more about “guest” role.
username: jmsuser
password: jmsuser@123
user role: guest
Realm: ApplicationRealm

   $ cd /PATH/TO/wildfly-8.2.1.Final/bin
   $ ./add-user.sh 

What type of user do you wish to add? 
 a) Management User (mgmt-users.properties) 
 b) Application User (application-users.properties)
(a): b

Enter the details of the new user to add.
Using realm 'ApplicationRealm' as discovered from the existing property files.
Username : jmsuser
Password recommendations are listed below. To modify these restrictions edit the add-user.properties configuration file.
 - The password should not be one of the following restricted values {root, admin, administrator}
 - The password should contain at least 8 characters, 1 alphabetic character(s), 1 digit(s), 1 non-alphanumeric symbol(s)
 - The password should be different from the username
Password :  jmsuser@123
Re-enter Password :  jmsuser@123
What groups do you want this user to belong to? (Please enter a comma separated list, or leave blank for none)[  ]: guest
About to add user 'jmsuser' for realm 'ApplicationRealm'
Is this correct yes/no? yes
Added user 'jmsuser' to file '/PATH/TO/wildfly-8.2.1.Final/standalone/configuration/application-users.properties'
Added user 'jmsuser' to file '/PATH/TO/wildfly-8.2.1.Final/domain/configuration/application-users.properties'
Added user 'jmsuser' with groups guest to file '/PATH/TO/wildfly-8.2.1.Final/standalone/configuration/application-roles.properties'
Added user 'jmsuser' with groups guest to file '/PATH/TO/wildfly-8.2.1.Final/domain/configuration/application-roles.properties'
Is this new user going to be used for one AS process to connect to another AS process? 
e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls.
yes/no? yes
To represent the user add the following to the server-identities definition <secret value="am1zdXNlckAxMjM=" />

Step-3). Creating a simple JMS Queue using the WildFly CLI command line utility. NOTE the JNDI name should contain “java:/jboss/exported” prefix or else the JMS queue will can not be looked up remotely.

   $ cd /PATH/TO/wildfly-8.2.1.Final/bin
   $ ./jboss-cli.sh -c
   
   [standalone@localhost:9990 /] /subsystem=messaging/hornetq-server=default/jms-queue=TestQ/:add(entries=["java:/jboss/exported/jms/queue/TestQ"],durable=false)
     {"outcome" => "success"}
     
   [standalone@localhost:9990 /] :reload
     {
       "outcome" => "success",
       "result" => undefined
     }

Starting WebLogic 12c and configuring it

First of all Copy the WildFly client jar “/PATH/TO/wildfly-8.2.1.Final/bin/client/jboss-client.jar” and place it inside the “$DOMAIN_HOME/lib” directory of WebLogic 12c.

Step-4). Start WebLogic 12c normally.

   $ cp -f /PATH/TO/wildfly-8.2.1.Final/bin/client/jboss-client.jar     /PATH/TO/wls12130/user_projects/domains/mydomain/lib

   $ cd /PATH/TO/wls12130/user_projects/domains/mydomain/bin
   $ ./startWebLogic.sh

Writing WLST script to configure JMS Bridge

Step-5). Now create a directory like “WebLogic_JMS_Bridge” where we will place our project artifacts.

   $ mkdir  WebLogic_JMS_Bridge
   $ cd WebLogic_JMS_Bridge

Step-6). Inside the “WebLogic_JMS_Bridge” directory write the following kind of file “domain.properties” which will contain all the configuration details.


############ WebLogic 12c JMS Queue and Connection Factory related Configuration #########

# 1 - Connecting details
server.url = t3://localhost:7001
username = weblogic
password = weblogic1
 
# 2 - JMSServer details
jms.server.name = My_JMSServer
store.name = MyJDBCStore
tragated.jms.server.name = myserver
 
# 3 - SystemModule Details
system.module.name = My_SystemModule
tragated.system.module.name = myserver
 
# 4 - ConnectionFactory Details
connection.factory.name = My_ConnectionFactory
connection.factory.jndi.name = My_CF
 
# 5 - Unit Of Order Details
unit.of.order.value = 1
 
# 6 - SubDeployment & Queue Details
queue.sub.deployment.name = Sub_My_Queue
queue.name = My_Queue
queue.jndi.name = My_Q


############ JMS Bridge related Configuration #########
weblogic.destination.bridge = WLS_Source_Bridge
weblogic.adapter.jndi.name = eis.jms.WLSConnectionFactoryJNDINoTX


wildfly.destination.bridge = WildFly_Destination_Bridge
wildfly.server.url = http-remoting://localhost:8080

# When using JBoss EAP6 or JBossAS7 then change the URL to following:
# wildfly.server.url =remote://localhost:4447

wildfly.initial.context.factory = org.jboss.naming.remote.client.InitialContextFactory
wildfly.remote.connection.factory.jndi.name = jms/RemoteConnectionFactory
wildfly.jms.destination.jndi.name = jms/queue/TestQ

wildfly.jms.username = jmsuser
wildfly.jms.password = jmsuser@123

Step-7). Now we will write simple WLST Script to configure the JMS Bridge , Create JMS Queue, JMS ConnectionFactory on WebLogic side. So write a file like “weblogicJMS_Setup.py” inside the same directory “WebLogic_JMS_Bridge” as following:

#############################################################################
#
# @author Copyright (c) 2010 - 2011 by Middleware Magic, All Rights Reserved.
#
#############################################################################
 
from java.io import FileInputStream
import java.lang
import os
import string
 
propInputStream = FileInputStream("domain.properties")
configProps = Properties()
configProps.load(propInputStream)
 
# 1 - Connecting details
serverUrl = configProps.get("server.url")
Username = configProps.get("username")
Password = configProps.get("password")
 
# 2 - JMSServer details
jmsServerName = configProps.get("jms.server.name")
storeName = configProps.get("store.name")
tragatedJMSServerName = configProps.get("tragated.jms.server.name")
 
# 3 - SystemModule Details
systemModuleName = configProps.get("system.module.name")
tragatedSystemModuleName = configProps.get("tragated.system.module.name")
 
# 4 - ConnectionFactory Details
connectionFactoryName = configProps.get("connection.factory.name")
ConnectionFactoryJNDIName = configProps.get("connection.factory.jndi.name")
 
# 5 - Unit Of Order Details
unitOfOrderValue = configProps.get("unit.of.order.value")
 
# 6 - SubDeployment & Queue Details
queueSubDeploymentName = configProps.get("queue.sub.deployment.name")
queueName = configProps.get("queue.name")
queueJNDIName = configProps.get("queue.jndi.name")
 
#7 - Weblogic Bridge Details:
weblogicDestinationBridge = configProps.get("weblogic.destination.bridge")
weblogicAdapterJNDINoTX = configProps.get("weblogic.adapter.jndi.name")

#8 - Widlfly bridge details:
wildflyDestinationBridge = configProps.get("wildfly.destination.bridge")
wildflyServerUrl = configProps.get("wildfly.server.url")
wildflyJMSUsername = configProps.get("wildfly.jms.username")
wildflyJMSUserPassword = configProps.get("wildfly.jms.password")
wildflyInitialContextFactory = configProps.get("wildfly.initial.context.factory")
wildflyJMSConnectionFactory = configProps.get("wildfly.remote.connection.factory.jndi.name")
wildflyJMSQueueJndi = configProps.get("wildfly.jms.destination.jndi.name")




redirect('wlst.log','false')
 
# 1 - Connecting to the Destination 
connect(Username,Password,serverUrl)
 
edit()
 
# 2 - JMSServer details
print "================== JMSSever ==================="
startEdit()
cmo.createJMSServer(jmsServerName)
print "Created a JMSServer !!"
cd('/Deployments/'+jmsServerName)
cmo.setPersistentStore(getMBean('/FileStores/'+storeName))
print "PersistentStore has been set for the JMSServer !!"
set('Targets',jarray.array([ObjectName('com.bea:Name='+tragatedJMSServerName+',Type=Server')], ObjectName))
print "Targeted the JMSServer !!"
activate()
print ""
 
# 3 - SystemModule Details
print "================== SystemModule ==================="
startEdit()
cd('/')
cmo.createJMSSystemResource(systemModuleName)
print "Created a SystemModule !!"
cd('/SystemResources/'+systemModuleName)
set('Targets',jarray.array([ObjectName('com.bea:Name='+tragatedSystemModuleName+',Type=Server')], ObjectName))
print "Targeted the SystemModule !!"
activate()
print ""
 
# 4 - ConnectionFactory Details
print "================== ConnectionFactory ==================="
startEdit()
cd('/JMSSystemResources/'+systemModuleName+'/JMSResource/'+systemModuleName)
cmo.createConnectionFactory(connectionFactoryName)
cd('/JMSSystemResources/'+systemModuleName+'/JMSResource/'+systemModuleName+'/ConnectionFactories/'+connectionFactoryName)
cmo.setJNDIName(ConnectionFactoryJNDIName)
print "Created a ConnectionFactory !!"
cd('/JMSSystemResources/'+systemModuleName+'/JMSResource/'+systemModuleName+'/ConnectionFactories/'+connectionFactoryName+'/SecurityParams/'+connectionFactoryName)
cmo.setAttachJMSXUserId(false)
cd('/JMSSystemResources/'+systemModuleName+'/JMSResource/'+systemModuleName+'/ConnectionFactories/'+connectionFactoryName)
cmo.setDefaultTargetingEnabled(true)
print "Targeted the ConnectionFactory !!"
activate()
print ""
 
# 5 - Unit Of Order Details
print "================== Unit Of Order ==================="
startEdit()
cd('/JMSSystemResources/'+systemModuleName+'/JMSResource/'+systemModuleName+'/ConnectionFactories/'+connectionFactoryName+'/DefaultDeliveryParams/'+connectionFactoryName)
cmo.setDefaultUnitOfOrder(unitOfOrderValue)
print "Changed Unit Of Order !!"
activate()
print ""
 
# 6 - SubDeployment & Queue Details
print "================== SubDeployment & Queue ==================="
startEdit()
cd('/SystemResources/'+systemModuleName)
cmo.createSubDeployment(queueSubDeploymentName)
print "Created a SubDeployment for Queue !!"
cd('/JMSSystemResources/'+systemModuleName+'/JMSResource/'+systemModuleName)
cmo.createQueue(queueName)
print "Created a Queue !!"
cd('/JMSSystemResources/'+systemModuleName+'/JMSResource/'+systemModuleName+'/Queues/'+queueName)
cmo.setJNDIName(queueJNDIName)
cmo.setSubDeploymentName(queueSubDeploymentName)
cd('/SystemResources/'+systemModuleName+'/SubDeployments/'+queueSubDeploymentName)
set('Targets',jarray.array([ObjectName('com.bea:Name='+jmsServerName+',Type=JMSServer')], ObjectName))
print "Targeted the Queue to the created subdeployment !!"
activate()
print ""



print "================== Creating  WebLogic Destination Bridge ==================="
startEdit()
cd('/')
cmo.createJMSBridgeDestination(weblogicDestinationBridge)
cd('/JMSBridgeDestinations/'+weblogicDestinationBridge)
cmo.setConnectionURL(serverUrl)
cmo.setAdapterJNDIName(weblogicAdapterJNDINoTX)
cmo.setConnectionFactoryJNDIName(ConnectionFactoryJNDIName)
cmo.setDestinationJNDIName(queueJNDIName)
activate()


print "================== Creating  WildFly Destination Bridge ==================="
startEdit()
cd('/')
cmo.createJMSBridgeDestination(wildflyDestinationBridge)
cd('/JMSBridgeDestinations/'+wildflyDestinationBridge)
cmo.setConnectionURL(wildflyServerUrl)
cmo.setAdapterJNDIName(weblogicAdapterJNDINoTX)
cmo.setConnectionFactoryJNDIName(wildflyJMSConnectionFactory)
cmo.setDestinationJNDIName(wildflyJMSQueueJndi)
activate()

startEdit()
cd('/JMSBridgeDestinations/'+weblogicDestinationBridge)
cmo.setUserName(Username)
cmo.setUserPassword(Password)
activate()

startEdit()
cd('/JMSBridgeDestinations/'+wildflyDestinationBridge)
cmo.setUserName(wildflyJMSUsername)
cmo.setUserPassword(wildflyJMSUserPassword)
cmo.setInitialContextFactory(wildflyInitialContextFactory);
activate()

print "================== Creating  JMS Bridge on WebLogic12c ==================="
startEdit()
cd('/')
cmo.createMessagingBridge('WLS12c_to_WildFly8_Bridge')
cd('/MessagingBridges/WLS12c_to_WildFly8_Bridge')
set('Targets',jarray.array([ObjectName('com.bea:Name=myserver,Type=Server')], ObjectName))
cmo.setSourceDestination(getMBean('/JMSBridgeDestinations/'+weblogicDestinationBridge))
cmo.setTargetDestination(getMBean('/JMSBridgeDestinations/'+wildflyDestinationBridge))
cmo.setStarted(true)
cmo.setSelector('')
cmo.setQualityOfService('Atmost-once')
activate()

cmd = "rm -f wlst.log"
os.system(cmd)

Step-8). Now we will run the WLST script. As following:

   $ cd /PATH/TO/wls12130/user_projects/domains/mydomain/bin
   $ . ./setDomainEnv.sh
   $ cd /PATH/TO/WebLogic_JMS_Bridge
   $  java  weblogic.WLST  webLogicJMS_Setup.py
   
   
   
   OUTPUT:
   
Initializing WebLogic Scripting Tool (WLST) ...

Welcome to WebLogic Server Administration Scripting Shell

Type help() for help on available commands


================== JMSSever ===================
Created a JMSServer !!
PersistentStore has been set for the JMSServer !!
Targeted the JMSServer !!

================== SystemModule ===================
Created a SystemModule !!
Targeted the SystemModule !!

================== ConnectionFactory ===================
Created a ConnectionFactory !!
Targeted the ConnectionFactory !!

================== Unit Of Order ===================
Changed Unit Of Order !!

================== SubDeployment & Queue ===================
Created a SubDeployment for Queue !!
Created a Queue !!
Targeted the Queue to the created subdeployment !!

================== Creating  WebLogic Destination Bridge ===================
================== Creating  WildFly Destination Bridge ===================
================== Creating  JMS Bridge on WebLogic12c ===================

Writing Java Code to send messages to WebLogic JMS Queue

Step-9). Now In the “WebLogic_JMS_Bridge” create a sub directory with name “src” where we will create file “QueueSend.java”:

import java.io.IOException;
import java.util.Hashtable;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class QueueSend {
  public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";
  public final static String JMS_FACTORY="My_CF";
  public final static String QUEUE="My_Q";

  private QueueConnectionFactory qconFactory;
  private QueueConnection qcon;
  private QueueSession qsession;
  private QueueSender qsender;
  private Queue queue;
  private TextMessage msg;

  public void init(Context ctx, String queueName) throws NamingException, JMSException {
    qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
    qcon = qconFactory.createQueueConnection();
    qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
    queue = (Queue) ctx.lookup(queueName);
    qsender = qsession.createSender(queue);
    msg = qsession.createTextMessage();
    qcon.start();
  }

  public void send(String message,int counter) throws JMSException {
    msg.setText(message);
    msg.setIntProperty("counter", counter);
    qsender.send(msg);
  }

  public void close() throws JMSException {
    qsender.close();
    qsession.close();
    qcon.close();
  }

  public static void main(String[] args) throws Exception {
    if (args.length != 1) {
      System.out.println("Usage: java QueueSend WebLogicURL");
      return;
    }
    InitialContext ic = getInitialContext(args[0]);
    QueueSend qs = new QueueSend();
    qs.init(ic, QUEUE);
    readAndSend(qs);
    qs.close();
  }

  private static void readAndSend(QueueSend qs) throws IOException, JMSException {
    String line="Test Message Body with counter = ";
    for(int i=0;i<10;i++) {
          qs.send(line+i,i);
          System.out.println("JMS Message Sent: "+line+i+"\n");
       }
  }

  private static InitialContext getInitialContext(String url) throws NamingException {
    Hashtable env = new Hashtable();
    env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
    env.put(Context.PROVIDER_URL, url);
    return new InitialContext(env);
  }
}

Step-10). Now we will write a simple ANT “build.xml” file inside the “WebLogic_JMS_Bridge” as following:

<project name="ApplicationLevelJMSDemo" default="run">
<property name="wls.home" value="/Users/jsensharma/NotBackedUp/Installed/wls12130" /> <!-- CHANGE ME!! -->
<property name="basedir" value="." />
<property name="tmp.dir" value="tmp" />
<property name="output.dir" value="build" />
<property name="src.dir" value="src" />
<property name="client.jar.name" value="jms_WLS_Client.jar" />

        <path id="wls.classpath">
             <fileset dir="${wls.home}">
                 <include name="**/*.jar"/>
             </fileset>
        </path>
        <target name="init">
           <delete dir="${output.dir}" />
           <mkdir dir="${output.dir}" />
           <delete dir="${tmp.dir}" />
           <mkdir dir="${tmp.dir}" />
        </target>

        <target name="run">
           <delete dir="${tmp.dir}" />
           <mkdir dir="${tmp.dir}" />
           <javac srcdir="${src.dir}" destdir="${tmp.dir}"  includes="QueueSend.java" classpathref="wls.classpath"/>
           <jar jarfile="${output.dir}/${client.jar.name}" basedir="${tmp.dir}" compress="true" />
           <java classname="QueueSend" fork="true">
               <classpath>
                  <pathelement location="${tmp.dir}"/>
                  <path refid="wls.classpath"/>
               </classpath>
               <arg value="t3://localhost:7001"/>
           </java>
           <delete dir="${tmp.dir}" />
        </target>  
</project>

Make sure to change the “wls.home” to point to your own WebLogic installation in this file.

Step-11). Now lets run the ANT project to send some messages to WLS “My_Q”

     $ cd /PATH/TO/WebLogic_JMS_Bridge
     $ export ANT_HOME=/PATH/TO/apache_ant_1.9.2
     $ export JAVA_HOME=/PATH/TO/jdk1.8.0_60
     $ export PATH=$JAVA_HOME/bin:$ANT_HOME/bin:$PATH
     
     $ ant
     
     
     OUTPUT:
     Buildfile: /Users/jsensharma/NotBackedUp/MM_Tests/WLS/JMS_Bridge/build.xml

run:
    [mkdir] Created dir: /PATH/TO/WebLogic_JMS_Bridge/tmp
    [javac] /Users/jsensharma/NotBackedUp/MM_Tests/WLS/JMS_Bridge/build.xml:28: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 1 source file to /PATH/TO/WebLogic_JMS_Bridge/tmp
    [javac] warning: Supported source version 'RELEASE_6' from annotation processor 'org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor' less than -source '1.8'
    [javac] warning: Supported source version 'RELEASE_6' from annotation processor 'org.sonatype.guice.bean.scanners.index.SisuIndexAPT6' less than -source '1.8'
    [javac] Note: /PATH/TO/WebLogic_JMS_Bridge/src/QueueSend.java uses unchecked or unsafe operations.
    [javac] Note: Recompile with -Xlint:unchecked for details.
    [javac] 2 warnings
      [jar] Building jar: /PATH/TO/WebLogic_JMS_Bridge/build/jms_WLS_Client.jar
      JMS Message Sent: Test Message Body with counter = 0
      
      JMS Message Sent: Test Message Body with counter = 1
      
      JMS Message Sent: Test Message Body with counter = 2
      
      JMS Message Sent: Test Message Body with counter = 3
      
      JMS Message Sent: Test Message Body with counter = 4
      
      JMS Message Sent: Test Message Body with counter = 5
      
      JMS Message Sent: Test Message Body with counter = 6
      
      JMS Message Sent: Test Message Body with counter = 7
      
      JMS Message Sent: Test Message Body with counter = 8
      
      JMS Message Sent: Test Message Body with counter = 9
      
   [delete] Deleting directory /PATH/TO/WebLogic_JMS_Bridge/tmp

BUILD SUCCESSFUL
Total time: 4 seconds

Step-12). Now login to WildFly 8.2 console and then check the JMS Queue “TestQ” runtime stats whether those messages reached to it or not.
http://localhost:9990/console/App.html#jms-metrics

Reference

I am just pasting the WebLogic side JMS Bridge configuration XML snippet here from “config.xml”

  <messaging-bridge>
    <name>WLS12c_to_WildFly8_Bridge</name>
    <target>myserver</target>
    <source-destination>WLS_Source_Bridge</source-destination>
    <target-destination>WildFly_Destination_Bridge</target-destination>
    <selector></selector>
    <quality-of-service>Atmost-once</quality-of-service>
    <started>true</started>
  </messaging-bridge>
  .
  .
  .
  <jms-server>
    <name>My_JMSServer</name>
    <target>myserver</target>
    <persistent-store xsi:nil="true"></persistent-store>
  </jms-server>
  
  <jms-bridge-destination>
    <name>WLS_Source_Bridge</name>
    <adapter-jndi-name>eis.jms.WLSConnectionFactoryJNDINoTX</adapter-jndi-name>
    <user-name>weblogic</user-name>
    <user-password-encrypted>{AES}MZthQtsuT4GH55R5es9TQFUOU8dK8tvLy5xJl5DcN1E=</user-password-encrypted>
    <connection-factory-jndi-name>My_CF</connection-factory-jndi-name>
    <connection-url>t3://localhost:7001</connection-url>
    <destination-jndi-name>My_Q</destination-jndi-name>
  </jms-bridge-destination>
  
  <jms-bridge-destination>
    <name>WildFly_Destination_Bridge</name>
    <adapter-jndi-name>eis.jms.WLSConnectionFactoryJNDINoTX</adapter-jndi-name>
    <user-name>jmsuser</user-name>
    <user-password-encrypted>{AES}0hlGNKwgZkSw+YxjxJSAbkPJm0EnV5tn5Czd5CLTJgk=</user-password-encrypted>
    <connection-factory-jndi-name>jms/RemoteConnectionFactory</connection-factory-jndi-name>
    <initial-context-factory>org.jboss.naming.remote.client.InitialContextFactory</initial-context-factory>
    <connection-url>http-remoting://localhost:8080</connection-url>
    <destination-jndi-name>jms/queue/TestQ</destination-jndi-name>
  </jms-bridge-destination>
  
  <jms-system-resource>
    <name>My_SystemModule</name>
    <target>myserver</target>
    <sub-deployment>
      <name>Sub_My_Queue</name>
      <target>My_JMSServer</target>
    </sub-deployment>
    <descriptor-file-name>jms/my_systemmodule-jms.xml</descriptor-file-name>
  </jms-system-resource>

Source Code: All the relative contents can be found in the following link:
https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/WebLogic/JMS/WebLogic_JMS_Bridge

Regards
Jay SenSharma


JMS Message Delivered To Busy Instance of JMS Consumer

Shashidhar Mruthyunjaya

Shashidhar Mruthyunjaya

DISCLAIMER:

In this article we may see an abnormal behaviors of weblogic. Which may not be necessarily a BUG but it is always to be aware of such behavior while using Weblogic. The idea behind making this page is just to make awareness among the WebLogic Admins to be alert specially when the some of these behaviors are related to WebLogic Security/JMS.

Some of the behaviors of WebLogic which may be due to inappropriate Security/JMS implementation in the Security/JMS system of WebLogic, Even if in some cases it is work as designed, Still it suggests to keep an eye on it and try to make those features more enhanced. Some of them are now fixed by the Application Server Vendor but still some need to be fixed or enhanced. The intentions here are not to point to the weak points of any Application Server but solely to make people aware about such strange or uncommon behaviors.

==========================================================================

We specially thank to “Mr. Shashidhar Mruthyunjaya” (MiddlewareMagic Subscriber) for making us aware about an abnormal behavior of WebLogic JMS subsystem as part of his comment in http://middlewaremagic.com/weblogic/?page_id=6231#comment-5504

The below code is shared by Shashidhar, we have just  made few changes in sending the messages just to make it more understanding for others and we have tested this code as well as were able to replicated this issue in WLS 10.3.0.

Again thanking Mr. Shashidhar for taking time for us and sharing the complete details about the issue and the steps to reproduce it. Shashidhar also proactively reported this issue to Oracle WebLogic Support team and it resulted in

Bug 13436706 – JMS MESSAGE DELIVERED TO BUSY INSTANCE OF CONSUMER

The Abnormal behavior is happening on weblogic 10.3.2, but I think this bug is lurking in all weblogic servers starting from weblogic 6.x onwards I think. Send 17 messages quickly in succession, 1st one as Long running and other 16 short running messages. You will notice that all the 16 messages run, but the 17th message gets stuck behind the 1st message which is a long running one (and is still running). This is because we have 16 sessions by default and due to weblogic bug, it just cycles around these 16 sessions without checking for free sessions (which there are plenty as short running messages complete quickly and free their JMS sessions)

Basic buggy behavior with weblogic jms code is that it is not looking for free JMS session (or consumer), but going around in a cycle allocating new JMS message arrived to the next session – NOT the next free session as expected. So if the session is already running a long-running message(transaction), the new message will get stuck behind this and will wait until the long-running message finishes. This was causing us frustration as we have some transaction running for hours together!!

==========================
Instructions to simulate
==========================
JMS Configuration: Create JMS step-up by using the WLST script given in the article Setup JMS with Unit-Of-Order using WLST , Script , however you can put “unit.of.order.value = 0″ in the domain.properties file.

Step1) You need to create an EJB project and include ResourceAdapterMDB.java in the same, deploy this

Step2) Create a new Java Project and include this TestMsgSender.java file within that project src.

Step3) Once all setup is done and checking that the EJB is active and listening to the Queue, run the TestMsgSender which has a main method,
which will send 17 messages, 1st one Long running (10 min) and other 16 short running messages. You will notice that the 17th message gets stuck behind the 1st message which is a long running one.

NOTE: Change the queue name and connection factory name and other values to match yours in both these files if required.

ResourceAdapterMDB.java:

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

import weblogic.javaee.TransactionTimeoutSeconds;

/**
* Message driven bean for the Resource Adapter This bean is configured to
* listen to the ResAdptQueue queue
*
* @author Shashidhar Mruthyunjaya
*
*/
@MessageDriven(activationConfig = {
	@ActivationConfigProperty(propertyName = "messageListenerInterface", propertyValue = "javax.jms.MessageListener"),
	@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
	@ActivationConfigProperty(propertyName = "MaxDeliveryCnt", propertyValue = "1"),
	@ActivationConfigProperty(propertyName = "ConnectionFactoryName", propertyValue="My_CF")
}
, mappedName="My_Q")
/*
* @TransactionTimeoutSeconds – Resource Adapter Transaction is set to 24 hours
* 24 x 60 x60 = 86400 seconds.
*/
@TransactionTimeoutSeconds(86400)
public class ResourceAdapterMDB implements MessageListener {

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void onMessage(Message message) {

TextMessage textMessage = (TextMessage) message;

long millisToSleep = 1000 * 2 ;//2 sec

try {
if("msg= LONG_RUNNING".equals(textMessage.getText())) {
 millisToSleep = 1000 * 60 * 1 ; // Sleep for 1 min
}
} catch (JMSException e) {
e.printStackTrace();
}

try {
Thread.sleep(millisToSleep);
System.out.println("t==> MyMDB Received: "+ textMessage.getText() +", time= "+ millisToSleep/1000 +" sec.");
}
catch (InterruptedException e) {
e.printStackTrace();
}
catch (JMSException e) {
            e.printStackTrace();
        }
}
}

Step4) Following is the code for the JMS Message Sender “TestMsgSender.java” :

import java.util.Date;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.NamingException;
import weblogic.jndi.Environment;

/**
* Provides the capability to send asynchronous messages to the defined target
* queues
*
* @author Shashidhar Mruthyunjaya
*
*/
public class TestMsgSender {
private static final String QUEUE = "My_Q";
private static final String CONN_FACTORY = "My_CF";
private static final String WEBLOGIC_USER = "weblogic";
private static final String WEBLOGIC_PASSWORD = "weblogic";
private static final String WEBLOGIC_URL = "t3://localhost:7001";

public void sendMsg(String textMessage) {
QueueConnection connection = null;
QueueSender sender = null;
QueueSession session = null;

try {
QueueConnectionFactory qcf = (QueueConnectionFactory) jndiLookup(CONN_FACTORY);
Queue targetQ = (Queue) jndiLookup(QUEUE);
connection = qcf.createQueueConnection();
session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
connection.start();
sender = session.createSender(targetQ);
TextMessage textMsg = session.createTextMessage();
textMsg.setText(textMessage);
sender.send(textMsg);
System.out.println(textMsg+": Sent at "+(new Date()));
} catch (Exception e) {
System.out.println("Exception occurred while sending message: " + e.getMessage());
throw new RuntimeException(e);
} finally {
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
System.out.println("Exception occurred while closing jms connection " + e.getMessage());
throw new RuntimeException(e);
} finally {
connection = null;
}
}
}
}

/**
* Helper method to perform JNDI lookup
*
* @param name
* @return
* @throws NamingException
*/
private Object jndiLookup(String name) throws NamingException {
Environment env = new Environment();
env.setProviderUrl(WEBLOGIC_URL);
env.setSecurityPrincipal(WEBLOGIC_USER);
env.setSecurityCredentials(WEBLOGIC_PASSWORD);
Context ctx = env.getInitialContext();

// Context ctx = new InitialContext();
Object ret = ctx.lookup(name);
ctx.close();

return ret;
}

public static void main(String[] args) throws InterruptedException {
TestMsgSender genericMsgSender = new TestMsgSender();

String textMessage;

// Send a long running message here
textMessage = "msg= LONG_RUNNING";
genericMsgSender.sendMsg(textMessage);

// Send 16 short running message here
for (int i = 1; i < 17; i++) {
genericMsgSender.sendMsg("msg= "+i);
Thread.sleep(1000 * 1); // wait for 1 sec
}
System.out.println("++++++++++++++++++ DONE Sending all messages ++++++++++++++++++");
}
}

Out put of the above code can be seen in the below snap-short which would make things much more easier to understand

Now from the above snap-shot you can see that the first messages “msg= LONG_RUNNING” was sent which takes 60 seconds to get consumed and just after that 16 more messages are been sent which should get consumed within 2 seconds, that makes total of 17 messages are been sent. You would notice that the messages from msg=1 to msg=15 has been consumed by the MDB within 2 seconds for each, but as the first message is still not been consumed due to which the last messages msg=16 (i.e. 17th number message) is been stuck behind and only gets consumed when the first message get consumed.

Workaround/Solution for this Issue:

================================================
Updated on : 16-Dec-2011 Based on Comment: http://middlewaremagic.com/weblogic/?p=7653#comment-5662

We need to define connection-factory-jndi-name” in “weblogic-ejb-jar.xml” along with setting MaximumMessages to 1 . This somehow makes this issue go away. After these changes the messages get allocated to a free consumer!!
.

.
.
Thanks


Copyright © 2010-2012 Middleware Magic. All rights reserved. |