Showing posts with label JMS Server. Show all posts
Showing posts with label JMS Server. Show all posts

Tuesday, August 18, 2015

Third Party Queue Connection using Foreign JMS Server in OSB/SOA

Hi,

There are cases where we need to establish third party JMS connection. To achieve that in ESB, we can use JMS Bridges, which creates a reliable connection oriented link to any weblogic JMS queue or to other Third Party Queue. One other way to establish the same is using Foreign JMS Server.

There are other ways listed below
Q. What tools are available for integrating with remote JMS providers?
A. The following table summarizes the tools available for integrating with remote JMS providers:
Method
Automatic Enlistment
JMS Resource Pooling
Direct use of the remote provider's JMS client
Yes for a WebLogic server provider. Other providers must perform enlistment programmatically.
No. Can be done programmatically.
Messaging Bridge
Yes
N/A
Foreign JMS Server Definition
No. To get automatic enlistment, use in conjunction with a JMS resource reference or MDB.
No. To get resource pooling, use in conjunction with a JMS resource reference or MDB.
JMS Resource Reference
Yes
Yes
Message Driven EJBs
Yes
Yes


Both of the messaging bridge and the foreign JMS server allow you to receive/send messages via a WLS server to a JMS destination that is running on a remote WLS server/cluster/domain or a 3rd party messaging product.


Conceptual Diagram


So when to use what ?

Q. When should I use a messaging bridge?
A. Typically, messaging bridges are used to provide store-and-forward high availability design requirements. A messaging bridge is configured to consume from a sender's local destination and forward it to the sender's actual target remote destination. This provides high availability because the sender is still able to send messages to its local destination even when the target remote destination is unreachable. When a remote destination is not reachable, the local destination automatically begins to store messages until the bridge is able to forward them to the target destination when the target becomes available again.

Q. When should I avoid using a messaging bridge?
A. Other methods are preferred in the following situations:
  • Receiving from a remote destination—use a message driven EJB or implement a client consumer directly.
  • Sending messages to a local destination—send directly to the local destination.
  • Environment with low tolerance for message latency. Messaging Bridges increase latency and may lower throughput. Messaging bridges increase latency for messages as they introduce an extra destination in the message path and may lower throughput because they forward messages using a single thread.


Q. When is it best to use a Foreign JMS Server Definition?
A. For this release, a Foreign JMS Server definition conveniently moves JMS JNDI parameters into one central place. You can share one definition between EJBs, servlets, and messaging bridges. You can change a definition without recompiling or changing deployment descriptors. They are especially useful for:
  • Any message driven EJB (MDB) where it is desirable to administer standard JMS communication properties via configuration rather than hard code them into the application's EJB deployment descriptors. This applies even if the MDB's source destination isn't remote.
  • Any MDB that has a destination remote to the cluster. This simplifies deployment descriptor configuration and enhances administrative control.
  • Any EJB or servlet that sends or receives from a remote destination.
  • Enabling resource references to refer to remote JMS providers. 

Here it is how you can configure it.

https://docs.oracle.com/cd/E57014_01/wls/WLACH/taskhelp/jms_modules/foreign_servers/ConfigureForeignServers.html


If you are connecting it to a third party queue, you need to have their JMS libraries in weblogic lib. For MQ it comes by default.

Now to use the JMS Server resource reference in OSB or in SOA, you can use it normally as you do for internal weblogic Queue push and pop.

In OSB, you can skip giving the host:port and jms:///ConnectionFactoryJNDI/QueueJNDI will work.

In SOA, you can configure JMS Adapter with  Connection factory location details and refer to the Queue while designing your process and it will work as it does for local queue.

Thanks









Saturday, January 10, 2015

Weblogic WLST Script to Create JMS Artifacts in Clustered Environment

As a part one event, I had developed a WLST script to deploy JMS artifacts in a clustered environment. The script can deploy as many JMS Servers, JDBC Stores, File Stores, DQueues, DTopics with JMS Modules and Sub Deployments in a clustered web-logic environment.

Below figure depicts conventionally followed JMS Deployment Architecture.
JMS Deployment Architecture





Now let us start with the script :

There are two files as a whole. One is the python script or wlst script and the other is a properties file which contains metadata for the script.

1. createGenieJMSResources.py
2. crowdGenieJMS.properties

Let me first lay down the properties file contents.


################Start of the properties file###############

username=weblogic
password=weblogic@123
providerURL=t3://localhost:7001

#Cluster name on which the module is to be targeted
jms_clusterName=GenieCluster

#jms module and its sub deployment
jms_module=GenieModule

#files stores and data source and their respective store directory path - note: name assumed is "Store_"+jms_persistent_store_type+"_"+jms_targetManageServerName
jms_persistent_store_type=File,JDBC
optional_explicit_fileStoreDirectory=
dataSourceJNDIName=localDS

#manage servers which are to be targeted by JMS Servers and file stores respectively - note: name assumed for JMSServer is jms_module+"_JMSServer_"+jms_targetManageServerName
jms_targetManageServerName=Server-Genie1,Server-Genie2

#Destination Name and their respective jndi
jms_destination_jndi_name=jms/GenieQueue1,jms/GenieQueue2,jms/GenieQueue3,jms/GenieQueue4,jms/GenieQueue5,jms/GenieTopic1,jms/GenieTopic2,jms/GenieTopic3,jms/GenieTopic4
jms_type=Queue,Queue,Queue,Queue,Topic,Topic,Topic,Topic

#Connection Factories and their respective jndi's
jms_connFacJNDIName=fac/GenieConnFac1,fac/GenieConnFac2
xa_conn_flag=true,false

#flag for logging - if true then logs in the domain path with genieWLST.log else it stdouts on the console
log_file=true
log_path=

#flag to check if existing resources needs to be deleted and recreated, or error should log/pop out.
delete_if_exist_flag=true

#################End of the properties file#################

The important thing to note in the properties file is the comma separated values of several properties like jms_destination_jndi_name, jms_targetManageServerName. The script reads the values in a array loop on values split delimited by the ','. Look at the script code to better understand.
There are also naming convention to the file or data stores.

Now let us look at the script :


#the part contains import from java python lib. FOS and FIS is required for loading the properties file.
from java.io import FileOutputStream
from java.io import FileInputStream
from java.util import Properties
from java.io import File
import sys

try:


# Load the properties file.
def loadProperties(fileName):
properties = Properties()
input = FileInputStream(fileName)
properties.load(input)
input.close()

result= {}

for entry in properties.entrySet(): result[entry.key] = entry.value

return result


properties = loadProperties("crowdGenieJMS.properties")


#This is it checks if the WLST output files is to be generated a a user defined path or default same directory path where WLST script is kept.
if(properties['log_path']==""):
logFilePath="genieWLST.log"
else:
logFilePath=properties['log_path']+"//genieWLST.log"

#Setting the output log file
if(properties['log_file'] == "true"):
f = File(logFilePath)
fos = FileOutputStream(f)
theInterpreter.setOut(fos)


# Initializing

username = properties['username']

password = properties['password']
url = properties['providerURL']

moduleName = properties['jms_module']

subDeploymentName = moduleName+"SubDeployment"
storeType = properties['jms_persistent_store_type']

destinationJNDIName = properties['jms_destination_jndi_name']
destinationType = properties['jms_type']

CFJNDIName = properties['jms_connFacJNDIName']

clusterName = properties['jms_clusterName']


targetms = properties['jms_targetManageServerName']



# Connect to Admin Server

connect(username, password, url)
adminServerName = cmo.adminServerName


# Delete old resources, if they exist.

def deleteIgnoringExceptions(mbean):
try: delete(mbean)
except: pass

def startTransaction():
edit()
startEdit()

def endTransaction():

save()
activate(block="true")


def createUDTopic(topicName, jndiTopicName):

cd('/JMSSystemResources/'+moduleName+'/JMSResource/'+moduleName) 
udt1 = create(topicName, "UniformDistributedTopic")
udt1.JNDIName = jndiTopicName

cd("UniformDistributedTopics/"+topicName)
cmo.setSubDeploymentName(subDeploymentName)
cd("/")


def createUDQueue(qname, qjndiname):

cd('/JMSSystemResources/'+moduleName+'/JMSResource/'+moduleName)
udq1 = create(qname, "UniformDistributedQueue")
udq1.JNDIName = qjndiname

cd("UniformDistributedQueues/"+qname)
cmo.setSubDeploymentName(subDeploymentName)
cd("/")

def createCF(cfname, cfjndiname, xaEnabled):

cd('/JMSSystemResources/'+moduleName+'/JMSResource/'+moduleName)
cf = create(cfname, "ConnectionFactory")
cf.JNDIName = cfjndiname
cf.subDeploymentName = subDeploymentName

# Set XA transactions enabled
if (xaEnabled == "true"):
cf.transactionParams.setXAConnectionFactoryEnabled(1)
cd("/")

def createJMSModule():

cd('/JMSSystemResources')
jmsModule = create(moduleName, "JMSSystemResource")

cd('/JMSSystemResources/'+moduleName)
set('Targets',jarray.array([ObjectName('com.bea:Name='+clusterName+',Type=Cluster')], ObjectName))

# Create and configure JMS Subdeployment for this JMS System Module

sd = create(subDeploymentName, "SubDeployment")

cd('SubDeployments/'+subDeploymentName)

objName = ""
for mserver in targetms.split(','):
objName = objName + "ObjectName('com.bea:Name="+moduleName+"_JMSServer_"+mserver+",Type=JMSServer'), " 

objName="set('Targets',jarray.array(["+objName[:-2]+"], ObjectName))"

# executing python command to set target implicitly
exec objName

def createJMSServer():

i=0
ds=0
for mserver in targetms.split(','):

startTransaction()

# Assumed naming conventions
jmsServerName = moduleName+"_JMSServer_"+mserver
storeName = "Store_"+storeType.split(',')[i]+"_"+mserver


# Delete existing JMS Server and its persistent store
if(properties['delete_if_exist_flag']== "true"):
cd("/JMSServers")
deleteIgnoringExceptions(jmsServerName)

cd("/"+storeType.split(',')[i]+"Stores")
deleteIgnoringExceptions(storeName)

#Create JDBC Stores or File Stores
if(storeType.split(',')[i] == "JDBC"):
cd('/')
dsName = properties['dataSourceJNDIName'].split(',')[ds]
store = cmo.createJDBCStore(storeName)

cd('/JDBCStores/'+storeName)

cmo.setDataSource(getMBean('/SystemResources/'+dsName))
set('Targets',jarray.array([ObjectName('com.bea:Name='+mserver+',Type=Server')], ObjectName))
cmo.setPrefixName("GENIE_T_LOG_"+dsName)
ds=ds+1
else:
cd('/')
fileDir = properties['optional_explicit_fileStoreDirectory']
if fileDir == "":
fileDir = cmo.rootDirectory+"\\fileStores"+storeName

store = cmo.createFileStore(storeName)
store.setDirectory(fileDir)
cd('/FileStores/'+storeName)
set('Targets',jarray.array([ObjectName('com.bea:Name='+targetms.split(',')[i]+',Type=Server')], ObjectName))

endTransaction()
#Committed the creation of filestores

startTransaction()
cd("/JMSServers")
# Create JMS server and assign the Filestore

jmsServer = create(jmsServerName, "JMSServer")
jmsServer.setPersistentStore(store)

cd(jmsServerName)
set('Targets',jarray.array([ObjectName('com.bea:Name='+mserver+',Type=Server')], ObjectName))

i=i+1
endTransaction()

# The creation flow starts from here


if(properties['delete_if_exist_flag']== "true"):


startTransaction()
cd("/JMSSystemResources")
deleteIgnoringExceptions(moduleName)
endTransaction()

# Create JMS Servers along with JDBCStores or Filestores , delete the existing if required.
createJMSServer()


startTransaction()
# Create JMS Module and its subdeployment
createJMSModule()

# Create Queues and Topics : The names are same as the JNDI name tagged to the assumed Subbdeployment
di=0
for dtype in destinationType.split(','):
dname = destinationJNDIName.split(',')[di]
if(dtype == "Queue"):
createUDQueue(dname, dname)

if(dtype == "Topic"):
createUDTopic(dname, dname)
di=di+1

# Create Connection Factory with name same as JNDI tagged to the assumed Subdeployment
ci=0
for cf in CFJNDIName.split(','):
createCF(cf,cf, properties['xa_conn_flag'].split(',')[ci])
ci=ci+1

endTransaction()
except Exception, e:
dumpStack()
print e
cancelEdit("y")
#raise

disconnect()


stopRedirect()

exit()

Code shared in the below link :

https://drive.google.com/folderview?id=0B5jwUx0GPlTOZlZnNUtTNHFQYVE&usp=sharing