Restarting EDN delivery after a DB failover

At a client  production environment, the SOA DB auto-failover caused delivery of EDN events to stop working. When the DB came back online, all SOA composites started working. The components which were raising the EDN events were all working, but the ones receiving the event weren’t. No new instances were getting created for those components. The EDN data sources were all in running state.   The MW support team was resorting to a full SOA server restart  to fix the issue.

Found that the below workaround will restart the event delivery without going for a full restart.

  1. Goto soainfra –> Administration –> System MBean Browser  –> Application Defined MBeans –> Oracle.as.soainfra.config –>EDNConfig –> edn
  2. Check the value of ‘Paused’ attribute. There are some known cases where an error during deployment will lead to this attribute having a value ‘True’ which will stop the delivery of events. So in that case , just update it to ‘False’ . In our case where there was a DB failover, this value was still ‘False’. So apply the below two steps to restart the event delivery.
  3. Change value of ‘Paused’ attribute to ‘True’ and click Apply.
  4. Now change the value of ‘Paused’ attributed to ‘False’ again and click Apply. This will restart the event delivery.

edn

Note if there was a prolonged outage this would lead to all the queued up events to deliver at once which may cause significant load on the servers. So it is advisable to do this at a quiet period if the business criticality of the stopped components allows that.

 

Posted in EDN, SOA | Leave a comment

Expiring a Human Task that forgot to expire (workaround)

In BPM/SOA  11g, there are some known product issues which causes a Human Task with an expiry set to not to expire and remain running forever. There are some patches available to prevent this from occurring . This issue used to occur (as per my observation) when:

a) SOA server hosting the task runtime was not running when the task expired.

b) A redeployment of the composite containing the task was done at the same revision as the existing deployed composite.

The permanent fix is to get the patch applied. In case, this was not done and ended up with a number of human tasks in production that forgot to expire, then the below workaround can be done to expire the tasks.

1- Get the task number from the audit trail of the task in EM console.

task

2. Query wftask table in the SOAINFRA DB schema of the SOA runtime.

Select taskid from wftask where tasknumber=4032649;

3. Once the task number is obtained, use a SOAP testing tool like SOAP UI (or in case if you have OSB wrapper built,use the OSB test console) to invoke the out of the box TaskService.This runs at this relative URL on the SOA server:

integration/services/TaskService/TaskServicePort.

e.g. http://localhost:8001/integration/services/TaskService/TaskServicePort, where the soa server runs on port 8001.

4. The first operation to be invoked is suspendTimers. Sample request payload below.

    <tas1:suspendTimers     xmlns:com="http://xmlns.oracle.com/bpel/workflow/common" xmlns:task="http://xmlns.oracle.com/bpel/workflow/task" xmlns:tas="http://xmlns.oracle.com/bpel/workflow/TaskEvidenceService" xmlns:tas1="http://xmlns.oracle.com/bpel/workflow/taskService">

    <com:workflowContext>
    
    <com:credential>
    <com:login>weblogic</com:login>
    <com:password>redacted</com:password>
    </com:credential>
    </com:workflowContext>
    <tas1:taskId>9158fd0b-2570-489f-9da8-502ba3462355</tas1:taskId>
    </tas1:suspendTimers>
  • login and password should be for an user who has SOAAdmin role.
  • taskId is obtained from querying wftask table in step 2.

5. After running suspendTimers, run the resumeTimers operation. The payload is similar as above.

    <tas1:resumeTimers     xmlns:com="http://xmlns.oracle.com/bpel/workflow/common" xmlns:task="http://xmlns.oracle.com/bpel/workflow/task" xmlns:tas="http://xmlns.oracle.com/bpel/workflow/TaskEvidenceService" xmlns:tas1="http://xmlns.oracle.com/bpel/workflow/taskService">

    <com:workflowContext>
    
    <com:credential>
    <com:login>weblogic</com:login>
    <com:password>redacted</com:password>
    </com:credential>
    </com:workflowContext>
    <tas1:taskId>9158fd0b-2570-489f-9da8-502ba3462355</tas1:taskId>
    </tas1:resumeTimers>

This will wake up the task and the task will expire and the BPM process will move to the next activity in the process.

Posted in BPM, HumanTasks, SOA | Leave a comment

2012 in review

The WordPress.com stats helper monkeys prepared a 2012 annual report for this blog.

Here’s an excerpt:

4,329 films were submitted to the 2012 Cannes Film Festival. This blog had 15,000 views in 2012. If each view were a film, this blog would power 3 Film Festivals

Click here to see the complete report.

Posted in Uncategorized | Leave a comment

Opatch java.lang.UnsatisfiedLinkError: no oraInstaller in java.library.path wrong ELF class: ELFCLASS64

I got this error when trying to deploy an interim patch for soa installation using opatch on Solaris.

oracle@xxxxxxx:[/u01/app/oracle/product/11.1.1.5/ofm1/fms/soa/patch_top/13683187]# opatch apply
Invoking OPatch 11.1.0.8.3
java.lang.UnsatisfiedLinkError: /u01/app/oracle/product/11.1.1.5/ofm1/fms/soa/oui/lib/solaris/liboraInstaller.so: ld.so.1: java: fatal: /u01/app/oracle/product/11.1.1.5/ofm1/fms/soa/oui/lib/solaris/liboraInstaller.so: wrong ELF class: ELFCLASS64
        at java.lang.ClassLoader$NativeLibrary.load(Native Method)
        at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1751)
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1647)
        at java.lang.Runtime.load0(Runtime.java:769)
        at java.lang.System.load(System.java:968)
        at oracle.sysman.oii.oiip.osd.unix.OiipuUnixOps.loadNativeLib(OiipuUnixOps.java:402)
        at oracle.sysman.oii.oiip.osd.unix.OiipuUnixOps.(OiipuUnixOps.java:125)
        at oracle.sysman.oii.oiip.oiipg.OiipgEnvironment.ssgetUidux(OiipgEnvironment.java:528)
        at oracle.sysman.oii.oiix.OiixEnvironmentOps.ssgetUidux(OiixEnvironmentOps.java:159)
        at oracle.opatch.OUIReplacer.isRootAccess(OUIReplacer.java:740)
        at oracle.opatch.OPatch.main(OPatch.java:445)
Exception in thread "main" java.lang.UnsatisfiedLinkError: no oraInstaller in java.library.path
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1682)
        at java.lang.Runtime.loadLibrary0(Runtime.java:822)
        at java.lang.System.loadLibrary(System.java:993)
        at oracle.sysman.oii.oiip.osd.unix.OiipuUnixOps.loadNativeLib(OiipuUnixOps.java:420)
        at oracle.sysman.oii.oiip.osd.unix.OiipuUnixOps.(OiipuUnixOps.java:125)
        at oracle.sysman.oii.oiip.oiipg.OiipgEnvironment.ssgetUidux(OiipgEnvironment.java:528)
        at oracle.sysman.oii.oiix.OiixEnvironmentOps.ssgetUidux(OiixEnvironmentOps.java:159)
        at oracle.opatch.OUIReplacer.isRootAccess(OUIReplacer.java:740)
        at oracle.opatch.OPatch.main(OPatch.java:445)

OPatch failed with error code 1

Oracle support has one article related to this, but think the solution there is not applicable to all instances.
The above error indicates that the opatch has encountered a 64 bit library while it was expecting a 32 bit, that means opatch was started as a 32 bit jvm. The java installation in the solaris box had both 32 bit and 64 bit jvms. So by default OPatch was starting as a 32 bit jvm , while the soa installation/ora installer on the ORACLE_HOME was 64 bits. The fix for this is to update the opatch script to add the “-d64” flag so that opatch starts as a 64 bit jvm.

$JAVA -d64 $JAVA_VM_OPTION $JRE_MEMORY_OPTIONS -cp $BASE/ocm/lib/emocmutl.jar:$BASE/ocm/lib/emocmclnt.jar:$CP/OraInstaller.jar:$CP/OraPrereq.jar:$CP/share.jar:$CP/srvm.jar:$CP/orai18n-mapping.jar:$CP/xmlparserv2.jar:$BASE/jlib/opatch.jar:$BASE/jlib/opatchutil.jar:$BASE/jlib/opatchprereq.jar:$BASE/jlib/opatchactions.jar:$BASE/jlib/opatchext.jar:$BASE/jlib/opatchfmw.jar:$WEBLOGIC_CLASSPATH -DOPatch.ORACLE_HOME=$OH -DOPatch.DEBUG=$DEBUGVAL -DOPatch.RUNNING_DIR=$BASE -DOPatch.MW_HOME=$MWH -DOPatch.WL_HOME=$WL_HOME -DOPatch.COMMON_COMPONENTS_HOME=$COMMON_COMPONENTS_HOME ${oracleOcmService} ${_bootClassPath} oracle/opatch/OPatch $@ 
Posted in OPatch | Tagged | 1 Comment

Weblogic SQL Authenticator and salted hash passwords.

Last 2 weeks I have been wrestling with a problem on how to make weblogic sql authenticator work correctly for user authentication when user password field is in salted hash format generated externally. I have discussed this problem in OTN as well. Posts here and here.
Though I have not a found a solution yet for our situation other than discard SQL authenticator altogether , I would like to share my learnings here.

Problem
We are migrating a legacy application to weblogic. The legacy application maintains the user id store in its internal database. The passwords are stored in salted hash format. We are planning to migrate the user id store to an oracle database and setup sql authenticator to do the authentication.

From testing so far we are not able to authenticate the users using the salted hash passwords migrated from the legacy app. The legacy app admin says the salt is
stored within the hash (??) .

So the expected steps are:

1. SQL authenticator read the salted hash from the password field in the table.
2. SQL authenticator extracts the salt from the salted hash
3. gets the plain text password from the login
4. Generates a salted hash for the plain text password using the salt obtained in step (2)
5. Compares the generated salted hash with the salted hash field in the database.

However from our testing weblogic fails to authenticate and works only if the user is created via admin console and hence use the weblogic native salted hash formats.

Cause
Actually the issue was the algorithm used by the external system was slightly different than what weblogic has implemented to parse the salted hash passswords. Had to decompile the classes , especially com\bea\security\utils\authentication\PasswordHashUtility.class to confirm this.

SQL authenticator expects the salted hash to be generated in this format : {SSHA}+plain text salt+base64Encode(sha-1{salt+plain text password})

Legacy app was generating the salted hash in the format : {SSHA}+base64Encode(sha-1{plain text password+salt}+plaintextSalt)

Legacy is conforming to RFC 3112 section 3.2 http://tools.ietf.org/html/rfc3112. Not a clue what spec weblogic has implemented.

Conclusion
Its possible to use salted hash passwords generated by weblogic to be verified by external systems using non weblogic api’s and also weblogic to verify correctly salted hashes generated by external systems. The key here is to know the format of the salted hash password used by weblogic .

It is : {SSHA}+plain text salt+base64Encode(sha-1{salt+plain text password})

Note the random salt value is always stored within salted hash field, so the verifier can always extract the salt value from it.

As per this if an external user creation utility can generate salted hash in the above format it can be verified by weblogic sql authenticator.

The other way round when weblogic generates a salted hash , e.g. I got this value when using sql authenticator to change the password to a value ‘welcome1’ {SSHA}T+4MyqBh0+e8Y3k1eekNmTjePeayFXY=.

The string without the {SSHA} prefix is 32 chars . SHA-1 generates 160 bits or 20 byte hash. Base64 encoding 20 bytes increases the size to 28 bytes.
So the last 28 chars are the hash value , the first 4 after the {SSHA} prefix should be the salt
so salt is : T+4M

so if an user enters the password in an external system, the system can generate the same salted hash using non weblogic api’s
e.g. run the below php code http://writecodeonline.com/php4/

$password="welcome1";
$salt="T+4M";
$sha_hashed = sha1($salt.$password); 
$packed = pack("H*",$sha_hashed); 
 
$encoded = base64_encode($packed); 
echo "{SSHA}".$salt.$encoded;
 

It generates the same salted hash value as what sql authenticator has stored in the db table and hence the password verification will work.

{SSHA}T+4MyqBh0+e8Y3k1eekNmTjePeayFXY=

Posted in Security | Tagged , , | 7 Comments

WLST – Modular Scripts to create/destroy WLS resources

This post shows how to create modular WLST scripts to create weblogic resources.

The principal followed was to keep the actual resource names and attribute values for the resources separated from the jython script used to create those resources. Each resource type had an associated properties file where the names and attribute values are defined and these are loaded by the script.

Also the script checks for the presence of an existing resource type of the same name before creating a new resource. So this prevents the master build script which invokes these scripts to not to fail if some resources are already present. Also this allows of incrementally creating new resources e.g. to create a new data source , just add the new data source details to the properties file and rerun the create DataSource script. This leaves the other existing datasources as is and just creates the new datasource.

Create DataSource

# ##########################################################################
# Creates Data Sources
# Usage : CreateDataSources.py <Name of Properties file >
# #########################################################################
import sys
#read properties file

if len(sys.argv) != 2:
	print "Invalid Arguements :: Usage CreateDataSources.py <DataSource Properties file>"
	exit()
try:
	print "Load properties file"
	properties=sys.argv[1]
	file=open(properties,'r')
	print "Read properties file"
	exec file
	print "Execute properties file"
	file.close
except:
	exit()
#Connect

connect(USER,PASSWORD,ADMIN_URL)
edit()
dsCount=0
successCount=0
for dataSource in DATASOURCE_ARRAY:
	startEdit()
	jdbcSystemResource=getMBean("/JDBCSystemResources/"+dataSource['NAME'])
	if jdbcSystemResource is None:
		jdbcSystemResource=create(dataSource['NAME'],"JDBCSystemResource")
	
		if (dataSource['TARGET_TYPE']=="SERVER"):
			targetMB=getMBean("/Servers/"+dataSource['TARGET'])
		if (dataSource['TARGET_TYPE']=="CLUSTER"):
			targetMB=getMBean("/Clusters/"+dataSource['TARGET'])

		if targetMB is None:
			print "@@@ Invalid DataSource Target '"+dataSource['TARGET']+"'"
			exit()
	
		jdbcSystemResource.addTarget(targetMB)
		jdbcResource=jdbcSystemResource.getJDBCResource()
		jdbcResource.setName(dataSource['NAME'])
		jdbcResource.JDBCDataSourceParams.setJNDINames(jarray.array([String(dataSource['JNDI_NAME'])], String))
		jdbcResource.JDBCDriverParams.setUrl(dataSource['URL'])
		jdbcResource.JDBCDriverParams.setDriverName(dataSource['DRIVER_NAME'])
		property=jdbcResource.JDBCDriverParams.getProperties().createProperty("USER")
		property.setValue(dataSource['USER'])
		jdbcResource.JDBCDriverParams.setPassword(dataSource['PASSWORD'])
		jdbcResource.JDBCConnectionPoolParams.setTestConnectionsOnReserve(true)
		jdbcResource.JDBCConnectionPoolParams.setTestTableName("SQL SELECT 1 FROM DUAL\r\n\r\n")
		
	else:
		if (dataSource['TARGET_TYPE']=="SERVER"):
			targetMB=getMBean("/Servers/"+dataSource['TARGET'])
		if (dataSource['TARGET_TYPE']=="CLUSTER"):
			targetMB=getMBean("/Clusters/"+dataSource['TARGET'])
		if targetMB is None:
			print "@@@ Invalid DataSource Target '"+dataSource['TARGET']+"'"
			exit()	
		if getMBean("/JDBCSystemResources/"+dataSource['NAME']+"/Targets/"+dataSource['TARGET']) is None:	
			jdbcSystemResource.addTarget(targetMB)
	try:
		activate()
		successCount=successCount+1
	except:			
		undo(defaultAnswer='y')
	dsCount=dsCount+1		
		
print str(successCount)+" DataSources out of "+str(dsCount)+"had successful connection during testing"
		
exit(defaultAnswer='y')

Create Foreign JNDI Providers

# ##########################################################################
# Creates Foreign JNDI Links
# Usage : CreateForeignJNDIProviders.py <Name of Properties file >
# #########################################################################
import sys
#read properties file

if len(sys.argv) != 2:
	print "Invalid Arguements :: Usage ForeignJNDIProviders.py <ForeignJNDI Properties file>"
	exit()
try:
	print "Load properties file"
	properties=sys.argv[1]
	file=open(properties,'r')
	print "Read properties file"
	exec file
	print "Execute properties file"
	file.close
except:
	exit()
#Connect

connect(USER,PASSWORD,ADMIN_URL)
edit()
startEdit()

for foreignJNDI in FOREIGN_JNDI_ARRAY:
	if (foreignJNDI['TARGET_TYPE']=="SERVER"):
		targetMB=getMBean("/Servers/"+foreignJNDI['TARGET'])
	if (foreignJNDI['TARGET_TYPE']=="CLUSTER"):
		targetMB=getMBean("/Clusters/"+foreignJNDI['TARGET'])
	if targetMB is None:
		print "@@@ Invalid Foreign JNDI Provider Target '"+foreignJNDI['TARGET']+"'"
		exit()
	if getMBean("/ForeignJNDIProviders/"+foreignJNDI['NAME']) is None:		
		foreignJNDIInstance=create(foreignJNDI['NAME'],"ForeignJNDIProvider")
		foreignJNDIInstance.addTarget(targetMB)
		foreignJNDIInstance.setInitialContextFactory(foreignJNDI['INITIAL_CONTEXT_FACTORY'])
		foreignJNDIInstance.setProviderURL(foreignJNDI['PROVIDER_URL'])
		foreignJNDIInstance.setUser(foreignJNDI['USER'])
		foreignJNDIInstance.setPassword(foreignJNDI['PASSWORD'])
	
		for foreignLink in foreignJNDI['LINKS_ARRAY']:
			foreignLinkInstance=foreignJNDIInstance.createForeignJNDILink(foreignLink['NAME'])
			foreignLinkInstance.setLocalJNDIName(foreignLink['LOCAL_JNDI'])
			foreignLinkInstance.setRemoteJNDIName(foreignLink['REMOTE_JNDI'])
	
		
activate()
exit()

Create JMS Modules including foreign JMS Servers

# ##########################################################################
# Creates a JMS Module and associated objects
# Usage : CreateJMSModule.py <Name of Properties file >
# #########################################################################
import sys
#read properties file

if len(sys.argv) != 2:
	print "Invalid Arguements :: Usage CreateJMSModule.py <JMS Module Properties file>"
	exit()
try:
	print "Load properties file"
	jms_properties=sys.argv[1]
	file=open(jms_properties,'r')
	print "Read properties file"
	exec file
	print "Execute properties file"
	file.close
except:
	exit()
#Connect

connect(USER,PASSWORD,ADMIN_URL)
edit()
startEdit()

if (JMS_MODULE_TARGET_TYPE=="SERVER"):
	defTargetMB=getMBean("/Servers/"+JMS_MODULE_TARGET)
if (JMS_MODULE_TARGET_TYPE=="CLUSTER"):
	defTargetMB=getMBean("/Clusters/"+JMS_MODULE_TARGET)
if (JMS_MODULE_TARGET_TYPE=="JMS"):
	defTargetMB=getMBean("/JMSServers/"+JMS_MODULE_TARGET)

if defTargetMB is None:
	print "@@@ Invalid JMS Module Target '"+JMS_MODULE_TARGET+"'"
	exit()

# Create Module
if getMBean("/JMSSystemResources/"+JMS_MODULE_NAME) is None:
	jmsModule = create(JMS_MODULE_NAME, "JMSSystemResource")
	jmsModule.addTarget(defTargetMB)
else:
	jmsModule=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME)
jmsResource = jmsModule.getJMSResource()

# Create JMS sub deployment 

for subDeployment in JMS_SUB_DEPLOYMENT_ARRAY :
	jmsSubDeployment=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/SubDeployments/"+subDeployment["JMS_SUB_DEPLOYMENT_NAME"])
	if jmsSubDeployment is None:
		jmsSubDeployment=jmsModule.createSubDeployment(subDeployment["JMS_SUB_DEPLOYMENT_NAME"])
	
		if (subDeployment['JMS_SUB_DEPLOYMENT_TARGET_TYPE']=="SERVER"):
			sdTargetMB=getMBean("/Servers/"+subDeployment['JMS_SUB_DEPLOYMENT_TARGET'])
		if (subDeployment['JMS_SUB_DEPLOYMENT_TARGET_TYPE']=="CLUSTER"):
			sdTargetMB=getMBean("/Clusters/"+subDeployment['JMS_SUB_DEPLOYMENT_TARGET'])
		if (subDeployment['JMS_SUB_DEPLOYMENT_TARGET_TYPE']=="JMS"):
			sdTargetMB=getMBean("/JMSServers/"+subDeployment['JMS_SUB_DEPLOYMENT_TARGET'])	 
		if sdTargetMB is None:
			print "@@@ Invalid JMS Sub Deployment Target '"+subDeployment['JMS_SUB_DEPLOYMENT_TARGET']+"'"
			exit()
		jmsSubDeployment.addTarget(sdTargetMB)
	
# Create & Target CF
	for name,jndiName in subDeployment['XA_CONNECTION_FACTORY_ARRAY'].items():
		newConnectionFactory=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ConnectionFactories/"+name)
		if newConnectionFactory is None:
			newConnectionFactory = jmsResource.createConnectionFactory(name)
		newConnectionFactory.setJNDIName(jndiName)
		newConnectionFactory.setSubDeploymentName(subDeployment['JMS_SUB_DEPLOYMENT_NAME'])
		newConnectionFactory.transactionParams.setXAConnectionFactoryEnabled(true)

	for name,jndiName in subDeployment['CONNECTION_FACTORY_ARRAY'].items():
		newConnectionFactory=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ConnectionFactories/"+name)
		if newConnectionFactory  is None:
			newConnectionFactory = jmsResource.createConnectionFactory(name)
		newConnectionFactory.setJNDIName(jndiName)
		newConnectionFactory.setSubDeploymentName(subDeployment['JMS_SUB_DEPLOYMENT_NAME'])
		newConnectionFactory.transactionParams.setXAConnectionFactoryEnabled(false)
		
# Create & Target Queues
	for name,jndiName in subDeployment['QUEUE_ARRAY'].items():
		newQueue=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/Queues/"+name)
		if newQueue is None:
			newQueue = jmsResource.createQueue(name)
		newQueue.setJNDIName(jndiName)
		newQueue.setSubDeploymentName(subDeployment['JMS_SUB_DEPLOYMENT_NAME'])

# Create & Target Topics
	for name,jndiName in subDeployment['TOPIC_ARRAY'].items():
		newTopic=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/Topics/"+name)
		if newTopic is None:
			newTopic = jmsResource.createTopic(name)
		newTopic.setJNDIName(jndiName)
		newTopic.setSubDeploymentName(subDeployment['JMS_SUB_DEPLOYMENT_NAME'])

# Create & Target ForeignJMS
	for foreignServer in subDeployment['FOREIGN_JMS_SERVER_ARRAY']:
		foreignJMS=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ForeignServers/"+foreignServer['FOREIGN_JMS_SERVER_NAME'])
		if foreignJMS is None:
			foreignJMS =jmsResource.createForeignServer(foreignServer['FOREIGN_JMS_SERVER_NAME'])
		foreignJMS.setSubDeploymentName(subDeployment['JMS_SUB_DEPLOYMENT_NAME'])
		foreignJMS.setInitialContextFactory(foreignServer['FOREIGN_JMS_SERVER_INITIAL_CONTEXT_FACTORY'])
		foreignJMS.setConnectionURL(foreignServer['FOREIGN_JMS_SERVER_PROVIDER_URL'])  
		foreignJMS.unSet('JNDIPropertiesCredentialEncrypted')
		jndiProperty=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ForeignServers/"+foreignServer['FOREIGN_JMS_SERVER_NAME']+"/JNDIProperties/"+foreignServer['FOREIGN_JMS_SERVER_JNDI_PROPERTY_KEY'])
		if jndiProperty is None:
			jndiProperty=foreignJMS.createJNDIProperty(foreignServer['FOREIGN_JMS_SERVER_JNDI_PROPERTY_KEY'])
		jndiProperty.setValue(foreignServer['FOREIGN_JMS_SERVER_JNDI_PROPERTY_VALUE'])		
	# Create ForeignJMS Connection Factory
		for foreignCF in foreignServer['FOREIGN_JMS_CF_ARRAY']:
			foreignJMSConnectionFactory=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ForeignServers/"+foreignServer['FOREIGN_JMS_SERVER_NAME']+"/ForeignConnectionFactories/"+foreignCF['NAME'])
			if foreignJMSConnectionFactory is None:
				foreignJMSConnectionFactory = foreignJMS.createForeignConnectionFactory(foreignCF['NAME']);
			foreignJMSConnectionFactory.setLocalJNDIName(foreignCF['LOCAL_JNDI'])
			foreignJMSConnectionFactory.setRemoteJNDIName(foreignCF['REMOTE_JNDI'])
	
	# Create ForeignJMS Destinations
		for foreignDest in foreignServer['FOREIGN_JMS_DEST_ARRAY']:
			foreignJMSDest=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ForeignServers/"+foreignServer['FOREIGN_JMS_SERVER_NAME']+"/ForeignDestinations/"+foreignDest['NAME'])
			if foreignJMSDest is None :
				foreignJMSDest = foreignJMS.createForeignDestination(foreignDest['NAME']);
			foreignJMSDest.setLocalJNDIName(foreignDest['LOCAL_JNDI'])
			foreignJMSDest.setRemoteJNDIName(foreignDest['REMOTE_JNDI'])
	
activate()
exit()

Create MessageBridges

# ##########################################################################
# Creates Message Bridges
# Usage : CreateMessageBridges.py <Name of Properties file >
# #########################################################################
import sys
#read properties file

if len(sys.argv) != 2:
	print "Invalid Arguements :: Usage CreateMessageBridges.py <Message Bridge Properties file>"
	exit()
try:
	print "Load properties file"
	properties=sys.argv[1]
	file=open(properties,'r')
	print "Read properties file"
	exec file
	print "Execute properties file"
	file.close
except:
	exit()
#Connect

connect(USER,PASSWORD,ADMIN_URL)
edit()
startEdit()
for msgBridge in MSGBRIDGE_ARRAY:
	 
	destinations = (msgBridge['SOURCE_DEST'],msgBridge['TARGET_DEST'])
	
	for dest in destinations :
		if getMBean("/JMSBridgeDestinations/"+dest['NAME']) is None:
			jmsBridgeDestination=create(dest['NAME'],"JMSBridgeDestination")
			jmsBridgeDestination.setAdapterJNDIName(dest['ADAPTER_JNDI'])
			jmsBridgeDestination.setInitialContextFactory(dest['INITIAL_CONTEXT_FACTORY'])
			jmsBridgeDestination.setConnectionFactoryJNDIName(dest['CONNECTION_FACTORY'])
			jmsBridgeDestination.setDestinationJNDIName(dest['DESTINATION'])
			jmsBridgeDestination.setDestinationType(dest['DESTINATION_TYPE'])
	if getMBean("/MessagingBridges/"+msgBridge['NAME']) is None:
		messagingBridgeInstance=create(msgBridge['NAME'],"MessagingBridge")
	
		if (msgBridge['TARGET_TYPE']=="SERVER"):
			targetMB=getMBean("/Servers/"+msgBridge['TARGET'])
		if (msgBridge['TARGET_TYPE']=="CLUSTER"):
			targetMB=getMBean("/Clusters/"+msgBridge['TARGET'])

		if targetMB is None:
			print "@@@ Invalid Message Bridge Target '"+msgBridge['TARGET']+"'"
			exit()
	
		messagingBridgeInstance.addTarget(targetMB)
		messagingBridgeInstance.setSourceDestination(getMBean("/JMSBridgeDestinations/"+msgBridge['SOURCE_DEST']['NAME']))
		messagingBridgeInstance.setTargetDestination(getMBean("/JMSBridgeDestinations/"+msgBridge['TARGET_DEST']['NAME']))
		messagingBridgeInstance.setStarted(true)
		messagingBridgeInstance.setQualityOfService(msgBridge['QOS'])
		messagingBridgeInstance.setAsyncEnabled(false)
		messagingBridgeInstance.setPreserveMsgProperty(true)
		messagingBridgeInstance.setReconnectDelayMaximum(5)
		messagingBridgeInstance.setTransactionTimeout(10)
	
	
activate()

exit()

Create Work Managers

# ##########################################################################
# Creates Work Managers & Thread Constraints
# Usage : CreateWorkManagers.py <Name of Properties file >
# #########################################################################
import sys
#read properties file

if len(sys.argv) != 2:
	print "Invalid Arguements :: Usage CreateWorkManagers.py <WorkManagers Properties file>"
	exit()
try:
	print "Load properties file"
	properties=sys.argv[1]
	file=open(properties,'r')
	print "Read properties file"
	exec file
	print "Execute properties file"
	file.close
except:
	exit()
#Connect

connect(USER,PASSWORD,ADMIN_URL)
edit()
startEdit()
wmMBean=getMBean("/SelfTuning/"+DOMAIN)
if wmMBean is None:
		print "@@@ Invalid DOMAIN Name '"+DOMAIN+"'"
		exit()

for maxThreadsConst in MAX_THREADS_CONSTRAINT_ARRAY :
	if (maxThreadsConst['TARGET_TYPE']=="SERVER"):
		targetMB=getMBean("/Servers/"+maxThreadsConst['TARGET'])
	if (maxThreadsConst['TARGET_TYPE']=="CLUSTER"):
		targetMB=getMBean("/Clusters/"+maxThreadsConst['TARGET'])
	if targetMB is None:
		print "@@@ Invalid MAX THREADS CONSTRAINT Target '"+maxThreadsConst['TARGET']+"'"
		exit()
	if getMBean("/SelfTuning/"+DOMAIN+"/MaxThreadsConstraints/"+maxThreadsConst['NAME']) is None:		
		maxThreadConstInstance=wmMBean.createMaxThreadsConstraint(maxThreadsConst['NAME'])
		maxThreadConstInstance.addTarget(targetMB)
		maxThreadConstInstance.setCount(maxThreadsConst['COUNT'])

for workManager in WORK_MANAGER_ARRAY :
	if (workManager['TARGET_TYPE']=="SERVER"):
		targetMB=getMBean("/Servers/"+workManager['TARGET'])
	if (workManager['TARGET_TYPE']=="CLUSTER"):
		targetMB=getMBean("/Clusters/"+workManager['TARGET'])
	if targetMB is None:
		print "@@@ Invalid Work Manager Target '"+workManager['TARGET']+"'"
		exit()
	if getMBean("/SelfTuning/"+DOMAIN+"/WorkManagers/"+workManager['NAME']) is None:		
		workManagerInstance=wmMBean.createWorkManager(workManager['NAME'])
		workManagerInstance.addTarget(targetMB)
		workManagerInstance.setMaxThreadsConstraint(wmMBean.lookupMaxThreadsConstraint(workManager['MAX_THREADS_CONSTRAINT']))
	
activate()
exit()

Delete Datasources

# ##########################################################################
# Deletes Data Sources
# Usage : DeleteDataSources.py <Name of Properties file >
# #########################################################################
import sys
#read properties file

if len(sys.argv) != 2:
	print "Invalid Arguements :: Usage DeleteDataSources.py <DataSource Properties file>"
	exit()
try:
	print "Load properties file"
	properties=sys.argv[1]
	file=open(properties,'r')
	print "Read properties file"
	exec file
	print "Execute properties file"
	file.close
except:
	exit()
#Connect
connect(USER,PASSWORD,ADMIN_URL)
edit()
startEdit()

jdbcSysResourceMBean=getMBean("/JDBCSystemResources/") 
for dataSource in DATASOURCE_ARRAY:
	dataSourceMBean=getMBean("/JDBCSystemResources/"+dataSource['NAME'])
	if dataSourceMBean != None:
		if (dataSource['TARGET_TYPE']=="SERVER"):
			targetMB=getMBean("/Servers/"+dataSource['TARGET'])
		if (dataSource['TARGET_TYPE']=="CLUSTER"):
			targetMB=getMBean("/Clusters/"+dataSource['TARGET'])
		if targetMB != None:	
			dataSourceMBean.removeTarget(targetMB)
		if len(dataSourceMBean.getTargets()) ==0: #No Targets 
			jdbcSysResourceMBean.destroyJDBCSystemResource(dataSourceMBean)

activate()		
exit()

Delete ForeignJNDIProviders

# ##########################################################################
# Delete Foreign JNDI Links
# Usage : DeleteForeignJNDIProviders.py <Name of Properties file >
# #########################################################################
import sys
#read properties file

if len(sys.argv) != 2:
	print "Invalid Arguements :: Usage ForeignJNDIProviders.py <ForeignJNDI Properties file>"
	exit()
try:
	print "Load properties file"
	properties=sys.argv[1]
	file=open(properties,'r')
	print "Read properties file"
	exec file
	print "Execute properties file"
	file.close
except:
	exit()
#Connect

connect(USER,PASSWORD,ADMIN_URL)
edit()
startEdit()
forJNDIProviderMBean=getMBean("/ForeignJNDIProviders/")
for foreignJNDI in FOREIGN_JNDI_ARRAY:
	jndiProviderInstance=getMBean("/ForeignJNDIProviders/"+foreignJNDI['NAME'])
	if jndiProviderInstance != None: 
		forJNDIProviderMBean.destroyForeignJNDIProvider(jndiProviderInstance)
		
activate()
exit()

Delete JMS Module

# ##########################################################################
# Deletes a JMS Module and associated objects
# Usage : DeleteJMSModule.py <Name of Properties file >
# #########################################################################
import sys
#read properties file

if len(sys.argv) != 2:
	print "Invalid Arguements :: Usage DeleteJMSModule.py <JMS Module Properties file>"
	exit()
try:
	print "Load properties file"
	jms_properties=sys.argv[1]
	file=open(jms_properties,'r')
	print "Read properties file"
	exec file
	print "Execute properties file"
	file.close
except:
	exit()
#Connect

connect(USER,PASSWORD,ADMIN_URL)
edit()
startEdit()
moduleMBean=getMBean("/JMSSystemResources/")
sdMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/SubDeployments/")
cfMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ConnectionFactories/")
queueMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/Queues/")
topicMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/Topics/")
foreignServerMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ForeignServers/")

for subDeployment in JMS_SUB_DEPLOYMENT_ARRAY :
	
	for name,jndiName in subDeployment['XA_CONNECTION_FACTORY_ARRAY'].items():
		cfInstanceMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ConnectionFactories/"+name)
		if cfInstanceMBean != None:
			cfMBean.destroyConnectionFactory(cfInstanceMBean)	
	
	for name,jndiName in subDeployment['CONNECTION_FACTORY_ARRAY'].items():
		cfInstanceMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ConnectionFactories/"+name)
		if cfInstanceMBean != None:
			cfMBean.destroyConnectionFactory(cfInstanceMBean)	
		
	
	for name,jndiName in subDeployment['QUEUE_ARRAY'].items():
		qInstanceMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/Queues/"+name)
		if qInstanceMBean != None:
			queueMBean.destroyQueue(qInstanceMBean)
	
	for name,jndiName in subDeployment['TOPIC_ARRAY'].items():
		tInstanceMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/Topics/"+name)
		if tInstanceMBean != None:
			topicMBean.destroyTopic(tInstanceMBean)
	
	for foreignServer in subDeployment['FOREIGN_JMS_SERVER_ARRAY']:
		foreignCFMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ForeignServers/"+foreignServer['FOREIGN_JMS_SERVER_NAME']+"/ForeignConnectionFactories/")
		foreignJMSDestMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ForeignServers/"+foreignServer['FOREIGN_JMS_SERVER_NAME']+"/ForeignDestinations/")
		foreignPropertiesMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ForeignServers/"+foreignServer['FOREIGN_JMS_SERVER_NAME']+"/JNDIProperties/")
		foreignPropertiesInstanceMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ForeignServers/"+foreignServer['FOREIGN_JMS_SERVER_NAME']+"/JNDIProperties/"+foreignServer['FOREIGN_JMS_SERVER_JNDI_PROPERTY_KEY'])
		
		if foreignPropertiesInstanceMBean != None :
			foreignPropertiesMBean.destroyJNDIProperty(foreignPropertiesInstanceMBean)
		
		for  foreignCF in foreignServer['FOREIGN_JMS_CF_ARRAY']:
			foreignCFInstanceMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ForeignServers/"+foreignServer['FOREIGN_JMS_SERVER_NAME']+"/ForeignConnectionFactories/"+foreignCF['NAME'])	
			if foreignCFInstanceMBean != None :
				foreignCFMBean.destroyForeignConnectionFactory(foreignCFInstanceMBean)
		for foreignDest in foreignServer['FOREIGN_JMS_DEST_ARRAY']:
			foreignJMSDestInstanceMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ForeignServers/"+foreignServer['FOREIGN_JMS_SERVER_NAME']+"/ForeignDestinations/"+foreignDest['NAME'])
			if foreignJMSDestInstanceMBean != None :
				foreignJMSDestMBean.destroyForeignDestination(foreignJMSDestInstanceMBean)
		
		foreignServerInstanceMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/JMSResource/"+JMS_MODULE_NAME+"/ForeignServers/"+foreignServer['FOREIGN_JMS_SERVER_NAME'])
		if foreignServerInstanceMBean != None:
			foreignServerMBean.destroyForeignServer(foreignServerInstanceMBean)
	
	sdInstanceMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME+"/SubDeployments/"+subDeployment['JMS_SUB_DEPLOYMENT_NAME'])
	if sdInstanceMBean != None:
		sdMBean.destroySubDeployment(sdInstanceMBean)
	
moduleInstanceMBean=getMBean("/JMSSystemResources/"+JMS_MODULE_NAME)
if moduleInstanceMBean != None:
	moduleMBean.destroyJMSSystemResource(moduleInstanceMBean)
	
activate()
exit()

Delete MessageBridges

# ##########################################################################
# Creates Message Bridges
# Usage : DeleteMessageBridges.py <Name of Properties file >
# #########################################################################
import sys
#read properties file

if len(sys.argv) != 2:
	print "Invalid Arguements :: Usage DeleteMessageBridges.py <Message Bridge Properties file>"
	exit()
try:
	print "Load properties file"
	properties=sys.argv[1]
	file=open(properties,'r')
	print "Read properties file"
	exec file
	print "Execute properties file"
	file.close
except:
	exit()
#Connect

connect(USER,PASSWORD,ADMIN_URL)
edit()
startEdit()
bdgDestMBean=getMBean("/JMSBridgeDestinations/")
bdgMBean=getMBean("/MessagingBridges/")
for msgBridge in MSGBRIDGE_ARRAY:
	 
	destinations = (msgBridge['SOURCE_DEST'],msgBridge['TARGET_DEST'])
	
	bdgInstanceMBean=getMBean("/MessagingBridges/"+msgBridge['NAME'])
	if bdgInstanceMBean != None:
		bdgMBean.destroyMessagingBridge(bdgInstanceMBean)
		
	for dest in destinations :
		destMBean=getMBean("/JMSBridgeDestinations/"+dest['NAME'])
		if destMBean != None: 
			bdgDestMBean.destroyJMSBridgeDestination(destMBean)
		
activate()
exit()

Delete Work Managers

# ###################################################################################################################
# Deletes Work Managers & Thread Constraints
# Usage :	DeleteWorkManagers.py  	WorkManagers Properties file
#			
# ####################################################################################################################

import sys
#read properties file

if len(sys.argv) != 2:
	print "Invalid Arguements :: Usage DeleteWorkManagers.py <WorkManagers Properties file>"
	exit()
try:
	print "Load properties file"
	properties=sys.argv[1]
	file=open(properties,'r')
	print "Read properties file"
	exec file
	print "Execute properties file"
	file.close
except:
	exit()
	
#Connect

connect(USER,PASSWORD,ADMIN_URL)
edit()
startEdit()
stMBean=getMBean("/SelfTuning/"+DOMAIN)
for workManager in WORK_MANAGER_ARRAY:
	wmMBean=getMBean("/SelfTuning/"+DOMAIN+"/WorkManagers/"+workManager['NAME'])
	if wmMBean != None: 
		stMBean.destroyWorkManager(wmMBean)
for mtConstraint in MAX_THREADS_CONSTRAINT_ARRAY:
	
	mtcMBean=getMBean("/SelfTuning/"+DOMAIN+"/MaxThreadsConstraints/"+mtConstraint['NAME'])
	if mtcMBean != None:
		print "destroying max threads constraints...."
		stMBean.destroyMaxThreadsConstraint(mtcMBean)
		print "destroyed max threads constraint"

activate()
exit()

Sample Resource Type Properties

DataSource

USER="weblogic"
PASSWORD="weblogic1"
ADMIN_URL="t3://devserver:7001"

#SOA DataSource				   
SOADataSource={
					"NAME":"soa_ds",
					"JNDI_NAME":"soa_ds_jndi",
					"TARGET":"soa_server1",
					"TARGET_TYPE":"SERVER",
					"URL":"jdbc:oracle:thin:@oradevdbx01:1521:oradev",
					"DRIVER_NAME":"oracle.jdbc.xa.client.OracleXADataSource",
					"USER":"soa_user",
					"PASSWORD":"soa_pass"
				   }

#OSB DataSource				   
OSBDataSource={
					"NAME":"osb_ds",
					"JNDI_NAME":"osb_ds_jndi",
					"TARGET":"osb_server1",
					"TARGET_TYPE":"SERVER",
					"URL":"jdbc:oracle:thin:@oradevdbx01:1521:oradev",
					"DRIVER_NAME":"oracle.jdbc.xa.client.OracleXADataSource",
					"USER":"osb_user",
					"PASSWORD":"osb_pass"
				   }	


  
				   
#################  E  N D 	of 	D A T A  S O U R C E	C O N F I G U R A T I O N ################################ 
DATASOURCE_ARRAY=(SOADataSource,OSBDataSource)

JMSModule

USER="weblogic"
PASSWORD="weblogic1"
ADMIN_URL="t3://devserver:7001"

JMS_MODULE_NAME="IJmsModule"
JMS_MODULE_TARGET="osb_server1"
JMS_MODULE_TARGET_TYPE="SERVER"

# REPEAT BELOW SECTION FOR EACH SUBDEPLOYMENT 

###################################
# Sub Deployment : ISubDeployment
###################################

IXAConnFactoryArray ={"IWlsConnectionFactory":"jndi/cf/IWlsConnectionFactory"}

IQueueArray={
			   "LOG_ALERT":"jndi/queues/LOG_ALERT",
			   "POST_UINSTATUS":"jndi/queues/POST_UINSTATUS"			   
			  }
			  
IConnFactory1 ={
					"NAME":"BdgIConnectionFactory",
					"LOCAL_JNDI":"jndi/cf/BdgIConnectionFactory",
					"REMOTE_JNDI":"XAQueueConnectionFactory"
				   }
IConnFactoryArray=(IConnFactory1,)

IDest1 = {
				"NAME":"BdgIUINStatusForeignDestination",
				"LOCAL_JNDI":"jndi/queues/BdgIUINStatusForeignDestination",
				"REMOTE_JNDI":"Queues/POST_UIN_STATUS_UPDATEQ"
			 }
IDestArray=(IDest1,)
			  
IForeignServer={
					"FOREIGN_JMS_SERVER_NAME":"BdgIForeignServer",
                    "FOREIGN_JMS_SERVER_INITIAL_CONTEXT_FACTORY":"oracle.jms.AQjmsInitialContextFactory",
					"FOREIGN_JMS_SERVER_PROVIDER_URL":"",
					"FOREIGN_JMS_SERVER_JNDI_PROPERTY_KEY":"datasource",
					"FOREIGN_JMS_SERVER_JNDI_PROPERTY_VALUE":"bdg_ds_Iaq_jndi",
					"FOREIGN_JMS_CF_ARRAY":IConnFactoryArray,
					"FOREIGN_JMS_DEST_ARRAY":IDestArray					  
					 }			 


osbSubDeploymentForeignServerArray=(IForeignServer,)

ISubDeployment={
					  "JMS_SUB_DEPLOYMENT_NAME":"ISubDeployment",
					  "JMS_SUB_DEPLOYMENT_TARGET":"I_jmss_Server",
					  "JMS_SUB_DEPLOYMENT_TARGET_TYPE":"JMS",
                      "XA_CONNECTION_FACTORY_ARRAY":IXAConnFactoryArray,
					  "CONNECTION_FACTORY_ARRAY":{},
					  "QUEUE_ARRAY":IQueueArray,
					  "TOPIC_ARRAY":{},
					  "FOREIGN_JMS_SERVER_ARRAY":IForeignServer
					 }

#################  E  N D 	of 	S U B	D E P L O Y M E N T		C O N F I G U R A T I O N ################################ 

JMS_SUB_DEPLOYMENT_ARRAY=(ISubDeployment,)

ForeignJNDIProviders

USER="weblogic"
PASSWORD="weblogic1"
ADMIN_URL="t3://devserver:7001"

#SoaForeignJNDIProvider

SoaLocalConnectionFactoryLink={"NAME":"SoaLocalConnectionFactoryLink",
						       "LOCAL_JNDI":"jndi/local/cf/IWlsConnectionFactory",
							   "REMOTE_JNDI":"jndi/cf/IWlsConnectionFactory"
							   }


							   

SoaForeignJNDIProviderLinks =(SoaLocalConnectionFactoryLink,)

							  	
SoaForeignJNDIProvider={
	          "NAME":"SoaForeignJNDIProvider",
			  "TARGET":"soa_server1",
			  "TARGET_TYPE":"SERVER",
			  "INITIAL_CONTEXT_FACTORY":"weblogic.jndi.WLInitialContextFactory",
			  "PROVIDER_URL":"t3://osbhost:7101",	
			  "USER":"osb_wls_user",
			  "PASSWORD":"osb_wls_pass",
			  "LINKS_ARRAY":SoaForeignJNDIProviderLinks
			 } 



#################  E  N D 	of 	F O R E I G N  J N D I 	C O N F I G U R A T I O N ################################ 
FOREIGN_JNDI_ARRAY=(SoaForeignJNDIProvider,)

MessageBridge

USER="weblogic"
PASSWORD="weblogic1"
ADMIN_URL="t3://devserver:7001"



BdgPostAStatusBridgeSrc={
					"NAME":"BdgPostAStatusPosAQDestination",
					"ADAPTER_JNDI":"eis.jms.WLSConnectionFactoryJNDIXA",
					"INITIAL_CONTEXT_FACTORY":"weblogic.jndi.WLInitialContextFactory",
					"CONNECTION_FACTORY":"jndi/cf/BdgPosAUConnectionFactory",
					"DESTINATION":"jndi/queues/BdgPostAStatusForeignDestination",				
					"DESTINATION_TYPE":"Queue"					
				   }
				   
BdgPostAStatusBridgeTrg={
					"NAME":"BdgPostAStatusWLSDestination",
					"ADAPTER_JNDI":"eis.jms.WLSConnectionFactoryJNDIXA",
					"INITIAL_CONTEXT_FACTORY":"weblogic.jndi.WLInitialContextFactory",
					"CONNECTION_FACTORY":"jndi/cf/BdgCIWlsConnectionFactory",
					"DESTINATION":"jndi/queues/Bdg_POS_UINSTATUS",				
					"DESTINATION_TYPE":"Queue"					
				   }
				   

BdgPostAStatusBridge={
					"NAME":"BdgPostAStatusBridge",
					"TARGET":"bdg_server1",
					"TARGET_TYPE":"SERVER",
					"SOURCE_DEST":BdgPostAStatusBridgeSrc,
					"TARGET_DEST":BdgPostAStatusBridgeTrg,
					"QOS":"Exactly-once"					
				   }
				   
BdgPostNStatusBridgeSrc={
					"NAME":"BdgPostNStatusPosAQDestination",
					"ADAPTER_JNDI":"eis.jms.WLSConnectionFactoryJNDIXA",
					"INITIAL_CONTEXT_FACTORY":"weblogic.jndi.WLInitialContextFactory",
					"CONNECTION_FACTORY":"jndi/cf/BdgPosNZConnectionFactory",
					"DESTINATION":"jndi/queues/BdgPostNStatusForeignDestination",				
					"DESTINATION_TYPE":"Queue"					
				   }
				   
BdgPostNStatusBridgeTrg={
					"NAME":"BdgPostNStatusWLSDestination",
					"ADAPTER_JNDI":"eis.jms.WLSConnectionFactoryJNDIXA",
					"INITIAL_CONTEXT_FACTORY":"weblogic.jndi.WLInitialContextFactory",
					"CONNECTION_FACTORY":"jndi/cf/BdgCIWlsConnectionFactory",
					"DESTINATION":"jndi/queues/Bdg_POS_UINSTATUS",				
					"DESTINATION_TYPE":"Queue"					
				   }

BdgPostNStatusBridge={
					"NAME":"BdgPostNStatusBridge",
					"TARGET":"bdg_server1",
					"TARGET_TYPE":"SERVER",
					"SOURCE_DEST":BdgPostNStatusBridgeSrc,
					"TARGET_DEST":BdgPostNStatusBridgeTrg,
					"QOS":"Exactly-once"					
				   }  
#################  E  N D 	of 	M E S S A G E   B R I D G E 	C O N F I G U R A T I O N ################################ 
MSGBRIDGE_ARRAY=(BdgPostAStatusBridge,BdgPostNStatusBridge)


WorkManagers

USER="weblogic"
PASSWORD="weblogic1"
ADMIN_URL="t3://devserver:7001"


#ISingletonMaxThreadConstraint
ISingleton={
	          "NAME":"ISingleton",
			  "TARGET":"osb_server1",
			  "TARGET_TYPE":"SERVER",
			  "COUNT":1
			 } 

#ISStatusJmsLocalProducerWorkManager
ISStatusJmsLocalProducer={
									"NAME":"ISStatusJmsLocalProducer",
									"TARGET":"osb_server1",
									"TARGET_TYPE":"SERVER",
									"MAX_THREADS_CONSTRAINT":"ISingleton"
								}
#ISStatusJmsRemoteConsumerWorkManager
ISStatusJmsRemoteConsumer={
									"NAME":"ISStatusJmsRemoteConsumer",
									"TARGET":"osb_server1",
									"TARGET_TYPE":"SERVER",
									"MAX_THREADS_CONSTRAINT":"ISingleton"
								}
#R_W_JMS_Local_Producer_WorkManager
R_W_JMS_Local_Producer_WorkManager={
									"NAME":"R_W_JMS_Local_Producer_WorkManager",
									"TARGET":"osb_server1",
									"TARGET_TYPE":"SERVER",
									"MAX_THREADS_CONSTRAINT":"ISingleton"
								}
				
#################  E  N D 	of 	W O R K   M A N A G E R 	C O N F I G U R A T I O N ################################ 
MAX_THREADS_CONSTRAINT_ARRAY=(ISingleton,)
WORK_MANAGER_ARRAY=(ISStatusJmsLocalProducer,ISStatusJmsRemoteConsumer,R_W_JMS_Local_Producer_WorkManager)


Posted in Weblogic, WLST | Tagged , | 15 Comments

Implementing in-memory,clustered, stateful counter in OSB using Coherence

This post shows how to leverage Coherence to implement an in memory ,clustered , stateful counter in OSB. The counter is clustered means all managed servers in the cluster share the same counter and the sequence is mantained across all managed server instances.

Code below uses basic Coherence Java API to maintain a coherence cache for the counter . We will convert that code to a custom xpath function so that it can be easily accessed within OSB – i.e. from message pipeline as well as within Xquery transformations.

import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;
public class DocumentSequencer {
	   private static final NamedCache seq_cache = CacheFactory.getCache("repl-" + 
	            "DocumentSequencer");
	   public static void main(String [] args)
	   {
		   for (int i=1;i<11;i++)
			   System.out.println(getNextSequenceFromDocSequencer());
	   }
	   
	   public static long getNextSequenceFromDocSequencer()
	   {
		   String key = "Document";
		   long nextSeq;
		   seq_cache.lock("monitor",-1);
		   Object obj = seq_cache.get(key);
		   if (obj==null)
		   {
			   nextSeq=1;
			   seq_cache.put(key, new Long(nextSeq));
			   
		   }
		   else 
		   {
			   nextSeq = (Long)obj+1;
			   seq_cache.put(key, new Long(nextSeq));
		   }
		   seq_cache.unlock("monitor");
		   return nextSeq;
	   }


}

The key method here is public static long getNextSequenceFromDocSequencer(). It returns the next value from the sequencer. The code uses basic coherence api functions. The lock() and unlock() call is used to synchronize the update of counter by the threads in the different jvm instances in the cluster.

To test this in OEPE , place coherence.jar from $COHERENCE_HOME/lib folder in build path of the project. The cache named “repl-DocumentSequencer” which we use here matches the wild card cache configuration “repl-*” in coherence-cache-config.xml in coherence.jar. This is a replicated cache meaning the data we put into the cache will be replicated across all instances in the cluster. Thus the data will be available until all instances in the cluster are shutdown at the same time.

Convert the above compiled class to DocumentSequencer.jar and place it on on $OSB_HOME/config/xpath-functions folder.
XML descriptor for this function looks as below:

<?xml version="1.0" encoding="UTF-8"?>
<xpf:xpathFunctions xmlns:xpf="http://www.bea.com/wli/sb/xpath/config">
    <xpf:category id="%OSB_FUNCTIONS%">
        <xpf:function>
            <xpf:name>getNextSequenceFromDocSequencer</xpf:name>
            <xpf:comment>Gets next value from clustered counter</xpf:comment>
            <xpf:namespaceURI>http://www.bea.com/xquery/xquery-functions</xpf:namespaceURI>
            <xpf:className>DocumentSequencer</xpf:className>
            <xpf:method>long getNextSequenceFromDocSequencer()</xpf:method>
            <xpf:isDeterministic>false</xpf:isDeterministic>
            <xpf:scope>Pipeline</xpf:scope>
            <xpf:scope>SplitJoin</xpf:scope>
        </xpf:function>  		
    </xpf:category>
</xpf:xpathFunctions>

Place this as DocumentSequencer.xml in the same folder and restart the servers.

For testing this a simple HTTP Messaging Proxy with GET method is used in which a replace action returns the next counter value.

Invoke each managed server url for the service in a browser. In my configuration osb managed server 1 runs on 8002 and osb managed server 2 runs on port 8003.

As can be seen the counter sequence is maintained across the cluster . Now restart one server and test again. The next value from the sequence will be returned. This shows the state is maintained acrosss restarts of individual cluster nodes.

Posted in Coherence, OSB | Tagged , , | 2 Comments

Accessing Domain Value Maps in OSB using Custom XPath

As all know, current version of OSB doesn’t support DVM out of the box. So if you want to do lookups for a large amount of data then doing it in a Xquery or doing database lookups becomes bit complicated to handle. Instead, we can do similar functionality to BPEL’s dvm and dvm lookups in OSB. Basically, we put the dvm xml file in an OSB server classpath and then write a custom xpath function which can lookup data from these files. The custom xpath function uses XMLBeans api to parse the dvm xml and return the requested column of data.

The xpath method we are going to implement has the following signature :

String lookupDVM(String dvmName,String keyColumnName,String keyValue,String targetColumnName,String defaultValue)

dvmName : Name of the dvm file to query
keyColumnName : Name of the column in the dvm containg the key
keyValue : lookup key
targetColumn: Column in the dvm whose value to be retrieved
defaultValue : default value to return from dvm if no matches are found.

sample State.dvm


<?xml version="1.0" encoding="UTF-8"?>
<dvm name="State" xmlns="http://xmlns.oracle.com/dvm">

	<description>Maintain LOV Mappings for State </description>

	<columns>
		<column name="Code"/>
		<column name="Value"/>		
	</columns>

	<rows>
		<row>
			<cell>NSW</cell>
			<cell>New South Wales</cell>			
		</row>
		<row>
			<cell>VIC</cell>
			<cell>Victoria</cell>			
		</row>
		<row>
			<cell>TAS</cell>
			<cell>Tasmania</cell>			
		</row>
		<row>
			<cell>WA</cell>
			<cell>West Australia</cell>			
		</row>
		<row>
			<cell>QLD</cell>
			<cell>Queensland</cell>			
		</row>
		<row>
			<cell>SA</cell>
			<cell>South Australia</cell>			
		</row>		
	</rows>
	
</dvm>

Place this dvm file in server classpath. I placed this in $DOMAIN_HOME for the testing.

Java Code for the custom xpath function

import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;

import java.io.IOException;
import java.util.HashMap;
public class OSB_DVM {
	private static HashMap  dvmCollection = new HashMap();
	/* Driver Method */
	public static void main(String [] args)throws Exception
	{
		System.out.println(lookupDVM("State","Code","NSW","Value","default"));
	}
	/* Lookup DVM from DVMCollection */
	public static XmlObject getDVM(String dvmName)throws Exception
	{
		XmlObject dvm=(XmlObject)dvmCollection.get(dvmName);
		if (dvm==null)
		{
			dvm=loadDVM(dvmName);
			if (dvm!=null && validateDVM(dvm,dvmName))
				dvmCollection.put(dvmName, dvm);
			else throw new Exception ("Cannot find DVM "+dvmName+" on disk");
		}

		return dvm;
	}
	/* Load DVM from disk */
	public static XmlObject loadDVM(String dvmName)
	{
	 String xmlFilePath = dvmName+".dvm";
	 XmlObject dvm=null;
	 try
	 {
	 dvm=XmlObject.Factory.parse(Thread.currentThread().getContextClassLoader().getResource(xmlFilePath));
	 }
	 catch(IOException ex)
	 {

	 ex.printStackTrace();
	 }
	 catch(XmlException ex)
	 {
	 ex.printStackTrace();
	 }
	 return dvm;
	}

	public static boolean validateDVM(XmlObject dvm, String dvmName) throws Exception
	{
		String path="declare namespace xq='http://xmlns.oracle.com/dvm';" +
	    "./xq:dvm/xq:columns/xq:column";
		XmlObject [] columns = dvm.selectPath(path);
		if (columns.length == 0)
			throw new Exception("Invalid DVM -"+dvmName+" column defintions Not found");
		path="declare namespace xq='http://xmlns.oracle.com/dvm';" +
	    "./@name";
		for (int i=0;i<columns.length;i++)
		{

			XmlObject [] columnNames=columns[i].selectPath(path);

			if (columnNames.length !=1)
			throw new Exception("Invalid DVM - "+dvmName+" Zero or Multiple name Attributes found for column definitions");
		}
		return true;
	}

	public static String lookupDVM(String dvmName,String keyColumnName,String keyValue,String targetColumnName,String defaultValue)throws Exception
	{
		XmlObject dvm = getDVM(dvmName);
		String path="declare namespace xq='http://xmlns.oracle.com/dvm';" +
	    "./xq:dvm/xq:columns/xq:column";

		XmlObject [] columns = dvm.selectPath(path);

		int keyColumnIndex=-1;
		int targetColumnIndex=-1;
		path="declare namespace xq='http://xmlns.oracle.com/dvm';" +
	    "./@name";
		for (int i=0;i<columns.length;i++)
		{
			String columnName = columns[i].selectPath(path)[0].newCursor().getTextValue();
			if (columnName.equals(keyColumnName))
					keyColumnIndex=i+1;
			else if (columnName.equals(targetColumnName))
				    targetColumnIndex=i+1;

		}
		if (keyColumnIndex == -1 || targetColumnIndex ==-1 )
			throw new Exception("Invalid Column Names "+keyColumnName+" "+targetColumnName);
		String returnValue=null;
		path="declare namespace xq='http://xmlns.oracle.com/dvm';" +
	    "./xq:dvm/xq:rows/xq:row[xq:cell["+keyColumnIndex+"]='"+keyValue+"']/xq:cell["+targetColumnIndex+"]";

		XmlObject [] cells = dvm.selectPath(path);
		if ( cells.length == 0)
			returnValue=defaultValue;
		else
		returnValue = cells[0].newCursor().getTextValue();

		return returnValue;

	}

}

Since this code uses xpath based on predicates, you will need extra jars in your project build path if you are testing in OEPE. This is true even if you enable Apache XMLBeans facet for the project. The following jars will be required for testing in OEPE

  • xbean_xpath : From XML Beans project
  • saxon9 : From Saxon Project
  • saxon9-dom : From Saxon project
  • Compile this code and create a jar file called osb_dvm.jar.
    Place the jar in OSB_HOME/config/xpath-functions. Also create the osb_dvm.properties and osb_dvm.xml required for the custom xpath file in this same directory.

    osb_dvm.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <xpf:xpathFunctions xmlns:xpf="http://www.bea.com/wli/sb/xpath/config">
        <xpf:category id="%OSB_FUNCTIONS%">
            <xpf:function>
                <xpf:name>lookupDVM</xpf:name>
                <xpf:comment>looks up a DVM in filesystem and returns transformed value</xpf:comment>
                <xpf:namespaceURI>http://www.bea.com/xquery/xquery-functions</xpf:namespaceURI>
                <xpf:className>OSB_DVM</xpf:className>
                <xpf:method>java.lang.String lookupDVM(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String)</xpf:method>
                <xpf:isDeterministic>false</xpf:isDeterministic>
                <xpf:scope>Pipeline</xpf:scope>
                <xpf:scope>SplitJoin</xpf:scope>
            </xpf:function>       
            
        </xpf:category>
    </xpf:xpathFunctions>
              
    
    

    osb_dvm.properties

    %OSB_FUNCTIONS%=Service Bus Functions
    

    Restart the server.
    I created a dummy proxy service with an ASSIGN action to test the custom xpath function.

    Now add new dvm called Country.dvm to DOMAIN_HOME

    <?xml version="1.0" encoding="UTF-8"?>
    
    <dvm name="State" xmlns="http://xmlns.oracle.com/dvm">
    
    	<description>Maintain LOV Mappings for Countries </description>
    
    	<columns>
    		<column name="Code"/>
    		<column name="Value"/>		
    	</columns>
    
    	<rows>
    		<row>
    			<cell>AU</cell>
    			<cell>Australia</cell>			
    		</row>
    		
    	</rows>
    	
    </dvm>
    

    Now test using fn-bea:lookupDVM(“Country”,”Value”,”Australia”,”Code”,”default”);
    You can see result AU being returned.

    Thus this is an extensible framework whereyou can create any new dvm’s ( and in the same oracle format, so you can use JDeveloper to create or reuse from a soa application), and make OSB to perform lookups by just placing these dvm files in the classpath. No code change or server restart will be required.
    For performance reason I am caching the dvm in memory once loaded, so if a loaded dvm changes then you might need a restart. To prevent restart you can have another method , which loads the dvm from filesystem and updates the cache

    /* Refreshes changed dvm from file system and updates cache                                 */
    	public static boolean refreshDVM(String dvmName) throws Exception
    	{
    		XmlObject dvm = loadDVM(dvmName);
    		dvmCollection.put(dvmName,dvm);
    		return true;
    		
    	}
    

    Add refreshDVM also to the list of exposed xpath functions in osb-dvm.xml Then you can use a utility proxy service which accepts the dvm name in the request and perform a refreshDVM() call for that dvm. This will load the new version into the cache.

    Posted in Domain Value Maps, OSB | Tagged , , , | 4 Comments

    Using xalan:evaluate to ‘parameterize’ XPATH

    This is in reference to this OTN post.The poster there had the below XML:

    
    <?xml version="1.0" encoding="ISO-8859-1"?>
     <catalog>
     <cd>
     <title>Empire Burlesque</title>
     <artist>Bob Dylan</artist>
     <country>USA</country>
     <company>Columbia</company>
     <price>10.90</price>
     <year>1985</year>
     </cd>
     </catalog>
    
    

    And he wanted to extract the value of /catalog/cd/title. The problem is that this xpath needs to be parameterized and not hardcoded, which means it requires dynamic XPATH evaluation. This can be done in OSB using a XSLT transformation leveraging  xalan:evaluate.

    First lets create the xslt for doing this:

    
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xalan="http://xml.apache.org/xalan">
    
    <xsl:param name="xpath"/>
    
    <xsl:template match="/">
    <XalanResult> <xsl:value-of select="xalan:evaluate($xpath)"/></XalanResult>
    
    </xsl:template>
    
    </xsl:stylesheet>
    
    

    Register this as a XSLT resource in OSB. Next create a proxy service to test this XSLT.
    We will use a ASSIGN action to test this. This action just assigns the result of XSLT to the xalanEvaluationResult variable.

    We configure it to pass content of $body as source input. The second parameter is the string representation of the Xpath we want to apply on the source XML.
    Click the test button to test this.

    For $body we pass the xml in that post.

    The test result shows XSLT function applying the ‘parameterised’ xpath on the source xml and returning the result.

    Posted in OSB, XSLT | Tagged , , | 1 Comment

    Mapping Network drives in Weblogic (Windows)

    In situations where you need to talk to a remote file system from OSB running in Windows machines, you need to map the remote file system to a local drive letter. This scenario caters for two requirements.

    1. When you have your OSB cluster spanning multiple servers and all servers need access to a common file (for read only purpose), it is better to have this file sit in a file share accessible by all machines. An example is when using OSB to connect to MQ as foreign JMS, the .bindings file containing the remote JNDI tree for MQ objects can be placed in a file share.

    2. In File integrations where you need OSB to read from or write to an external file system.

    OSB’s file transport doesn’t support UNC format names for accessing files. Hence mapping to a drive letter is mandatory. This can be done in at-least in 3 ways:

    1. If OSB servers are started locally from windows user session.
    Map network drive and assign drive letter in windows explorer


    Use File endpoint URI starting with the drive letter. Example, Use K :\< file-name> to access files within my_directory

    2. IF OSB servers are started as windows service or started by node managers which runs as windows service (typical in SIT or Prod environments) then the Weblogic process will be running in a different user session. In this case you can follow one of the below approach for mapping

    a) Do the mapping in setDomainEnv for the domain
    E.g. add the below line in setDomainEnv.cmd script in $DOMAIN_HOME/bin directory
    NET USE K: \\10.11.2.32\my_directory /user:atheek Dec@2011

    K: – is the mapped drive letter

    \\10.11.2.32\my_directory  – is the root of remote file system

    atheek – name of user authorized to connect to remote file system.

    Dec@2011 – password for user atheek
    then you can use K:\file to access files within my_directory

    Limitation with this method is that password is in clear text. If you don’t want outsiders to see the password, make sure to secure the file system containing DOMAIN_HOME

    This setting works only for 1 domain as it is set on the setDomainEnv for the domain. Example, to map a filesystem used only in a specific File integration

    Instead if you want to have the mapping across all servers belonging to different domains  running on the same machine, then set the mapping details in node manager service.

    b) Do the mapping in Node Manager Service.

    Node Managers are usually configured as Windows service. This makes the node managers to start automatically when the machine starts. Since the WebLogic server processes are started by Node Manager, they are child processes to the Node Manager process. Hence if we do the drive mapping in Node Manager it will be available to all child Weblogic server processes started by it.

    The drive mapping is configured in the script used to install the node manager service. The location for this script is $MIDDLEWARE_HOME/wlserver_10.3/server/bin/installNodeManagerSvc.cmd.

    Edit this script to add the following:

    -localname:”K:” -remotename:”\\10.11.2.32\my_directory″ -remoteuser:”atheek” -remotepassword:”Dec@2011”

    Run this modified script which will create the windows service for node manager.


    Now access windows registry key for this service. This key is HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/services/Oracle WebLogic NodeManager (C_Oracle_Middleware_wlserver_10.3)/parameters

    As seen above the password is in encrypted form. Any weblogic servers started by this nodemanager can access the remote file system using the mapped drive K: The limitation with this method is that it allows only one file system to be mapped.

    Posted in Weblogic | Tagged , , | 4 Comments