Thursday, July 12, 2012

Modifying Endpoint Bindings Using XML Property File in BPM 7.5


In my  previous post, Deployment Script for BPM 7.5 on a Linux machine, I mentioned that I would post another blog about modifying endpoint bindings of your SCA imports. During that time we used a properties file to specify deployment specific information such as installation directory, applications to install, list of federated nodes,  etc. When I was working with WPS 6.2 in my previous project, I used the same properties file to specify the SCA import bindings to modify. To tell you the truth, the property was not very readable and it got large to read at some point. I specified the import bindings this way:

# modify_ws_binding="<module_name>::<import_name> <endpoint_binding>,<import_name> <endpoint_binding>,<import_name> <endpoint_binding>;;

Realizing that problem, I had the idea to use XML as "response" file for modifying the endpoint bindings via wsadmin. The structure goes something like:

<?xml version="1.0" encoding="UTF-8"?>
<deployment>
 <module name="ModuleName">
  <import name="ImportName1" type="WS">
   <property name="endpoint" value="http://localhost:9800/setWhatever" />
  </import>
  <import name="ImportName2" type="WS">
   <property name="endpoint" value="http://localhost:9800/setWhatever" />
  </import>  
  <import name="ImportName3" type="HTTP" level="methodName">
   <property name="endpointURL" value="http://localhost:9800/setWhatever" />
   <property name="endpointHttpMethod" value="POST" />
   <property name="httpProxyPort" value="80" />
  </import>
  <import name="ImportName3" type="HTTP" level="methodName1">
   <property name="endpointURL" value="http://localhost:9800/getWhatever" />
   <property name="endpointHttpMethod" value="POST" />
   <property name="httpProxyPort" value="80" />
  </import>
 </module>
 <module name="ModuleName1">
  <import name="ImportName1" type="WS">
   <property name="endpoint" value="http://localhost:9800/setWhatever" />
  </import>
  <import name="ImportName2" type="WS">
   <property name="endpoint" value="http://localhost:9800/setWhatever" />
  </import>  
  <import name="ImportName3" type="HTTP" level="ImportName3">
   <property name="endpointURL" value="http://localhost:9800/setWhatever" />
   <property name="endpointHttpMethod" value="POST" />
   <property name="httpProxyPort" value="80" />
  </import>
 </module>
</deployment>

The root element is the deployment element. I used this term because I have hopes of creating a deployment script using XML. Now, the deployment element has a an array of children named module. Each module tag has an attribute name where you specify the SCA module name. module has an array of children named import. Each import element has an attribute name  which specifies the name of the Import binding and an attribute type which specifies the type of SCA import binding (for now, the script only supports web services and http bindings).  The attribute level is an attribute for HTTP bindings. If you want to specify values on the import level, you specify the name of the import. Otherwise, specify the method name. Lastly, the import element has multiple property elements. Each property element has an attribute name which specifies the name of the parameter and an attribute value which specifies the value of the parameter. Visit the infocenter to get a list of parameters and values you can set for methods modifySCAImportHttpBinding and modifySCAImportWSBinding.

After writing the xml file, I wrote the code for reading it. I don't want to explain in detail the code, but, in general, what it does is, it parses the xml file. From the root element, it traverses down to the properties element and executes modifySCAImportHttpBinding  or modifySCAImportWSBinding using the values specified in the xml file. Lastly, it saves the configuration. In a network deployment, you might want to add the synchronize nodes code block that I used in my previous post.

Here's the code:

import javax.xml.parsers.DocumentBuilderFactory as DocumentBuilderFactory
import javax.xml.parsers.DocumentBuilder as DocumentBuilder
import sys

dbf = DocumentBuilderFactory.newInstance()
db = dbf.newDocumentBuilder()
dom = db.parse(sys.argv[0])

deployment = dom.getDocumentElement()
modules = deployment.getElementsByTagName('module') 

m=0
while m<modules.getLength():
 module = modules.item(m)
 moduleName = module.getAttribute('name')
 scaImports = module.getElementsByTagName('import')
 i=0
 while i<scaImports.getLength():
  scaImport = scaImports.item(i)
  scaImportType = scaImport.getAttribute('type')
  scaImportName = scaImport.getAttribute('name')
  properties = scaImport.getElementsByTagName('property')
  p=0
  props = ''
  levelBegin = '<' + scaImport.getAttribute('level') + '>'
  levelEnd = '</' + scaImport.getAttribute('level') + '>'
  if (scaImportType == 'WS'):
   while p<properties.getLength():
    property = properties.item(p)
    props += ' -' + property.getAttribute('name') + ' ' + property.getAttribute('value')
    p+=1
   #endWhile
   try:
    print 'AdminTask.modifySCAImportWSBinding(\'[-moduleName ' + moduleName + ' -import ' + scaImportName + props + ']\')'
    AdminTask.modifySCAImportWSBinding('[-moduleName ' + moduleName + ' -import ' + scaImportName + props + ']')
   except :
    print "Unexpected error:", sys.exc_info()[0]
  elif (scaImportType == 'HTTP'):
   while p<properties.getLength():
    property = properties.item(p)
    props += ' -' + property.getAttribute('name') + ' ' + levelBegin + property.getAttribute('value') + levelEnd
    p+=1
   #endWhile
   try:
    print 'AdminTask.modifySCAImportHttpBinding(\'[-moduleName ' + moduleName + ' -import ' + scaImportName + props + ']\')'
    AdminTask.modifySCAImportHttpBinding('[-moduleName ' + moduleName + ' -import ' + scaImportName + props + ']')
   except :
    print "Unexpected error:", sys.exc_info()[0]
  i+=1
 m+=1
else:
 print 'Processing Complete...'

print 'Saving...'
AdminConfig.save()

We then execute this using wsadmin:

wsadmin -lang jython -f script_path\modify_ws_bindings.py xml_path\properties.xml

Note that there are not much error checking done with this code. If you encounter any error don't forget to write a comment. 

References:
Changing an import binding using commands


No comments: