Wednesday 24 November 2010

changing import binding endpoint of a SCA module

One of the requirements of application deployment modules was to change import bindings when we deploy in different environment. Like if a BPM process is calling external services then the endpoint of these services need to change for every environment. Here is how you can change binding endpoint using wsadmin and jython:

#This will get you list of all SCA modules in the connected environment
scaModList=AdminTask.listSCAModules().split(System.getProperty('line.separator'))
#Now iterate through the SCA modules to get to he module you are interested in
for scaMod in scaModList:
        scaModNames=scaMod.split(':')
        scaImports = []
       #This will get you list of all imports for the module
        scaImports=AdminTask.listSCAImports("[-moduleName " +scaModNames[0] + "]").split(System.getProperty('line.separator'))
#Now iterate through all imports  to get to the import you are interested in
for scaImport in scaImports:
  #Now get the actual binding
   binding=AdminTask.showSCAImportBinding("[-moduleName " +scaModNames[0] + " -import " +scaImport + "]") 
# Check if binding is actually webservices binding
if binding.find ("WsImportBinding")!=-1:
 bindingAtr=binding.split(',')
# Check if the binding is the one you want to change
if bindingAtr[0].find("yourBinding Name"):
 #change the binding
AdminTask.modifySCAImportWSBinding("[-moduleName " +scaModNames[0] +" -import " +  scaImport + " -endpoint " + YourNewBindingEndPoint+ " ]")

Again its just an example and you probably want to check lot many exception situations like index is correct for all split output etc. The idea is to list all the commands you need to change the binding endpoint and you can probably build your application logic around it

Use java XML Dom parser in wsadmin jython

With my Application deployment module I had to read lot many xml files for different elements/attributes and I was first tag based parsing as I thought DOM will be very costly to use. But I soon realise that I need to work on many xml files and tag based parsing will mean a really stupid looking code. So I used Java dom parser in my jython and its really easy with jython wsadmin and java. I am not posting my complete class I am using to parse different xml files but if you want to do it, here is how you can get started:

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

dbf = DocumentBuilderFactory.newInstance()
db = dbf.newDocumentBuilder()
dom = db.parse("\usr\xml\app.xml")
docEle = dom.getDocumentElement()
 attr= docEle.getAttribute("name")
print attr

Here I am printing attribute of root element of the xml I have read. You can look at java docs for complete set of methods available with dom parser

Use Log4J in wsadmin and Jython

We all love Log4j and I was really surprised to find how easy it is to use it from within your jython script and wsadmin. The log4j related classes are loaded with wsadmin (as part of its own classpath ) so you need no jars to be configured. Just use the following line of code to import the classes you need and start logging:

from org.apache.log4j import Logger
from org.apache.log4j import PropertyConfigurator
# change the path to your properties file
PropertyConfigurator.configure("log4j.properties") 
logger = Logger.getLogger("YourClassName")
logger.info("statement")

You can do everything you are used doing with log4j and this is just a simple example. An example property file will look like:

#Author Abhijeet Kumar
#Version 1.0
#FileName:log4j.properties
#Root Loggers
log4j.rootLogger=debug, stdout, R
#------------------------------------------------------------------------------
#
#  The following properties configure the console (stdout) appender.
#  See http://logging.apache.org/log4j/docs/api/index.html for details.
#
#------------------------------------------------------------------------------
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n
# Pattern to output the caller's file name and line number.
#------------------------------------------------------------------------------
#
#  The following properties configure the Rolling File appender.
#  See http://logging.apache.org/log4j/docs/api/index.html for details.
#
#------------------------------------------------------------------------------
log4j.appender.R = org.apache.log4j.RollingFileAppender
log4j.appender.R.File = /usr/logs/ApplicationDeployment.log
log4j.appender.R.MaxFileSize = 1000KB
log4j.appender.R.Append = true
log4j.appender.R.layout = org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %m%n

Get Display Name of your EAR file in Jython to deploy on Websphere Application Server

As part of my current project to automate deployment of Websphere Process Server modules and Websphere Application server I decided to concatenate the target cluster name (We are running a multiple cluster topology) and build version with Application name delivered by developers in the archive. This is to make operational guys aware of the target by just looking at the display name of the application.

We all know we can pass the a new name while deploying using AdminApp.install to override the name specified in archive. What was little tricky is to get the current name specified in the application. I wrote this method to get an archive's display name

import zipfile
def getAppNameFromArchive(filepath):
 # This is little crude way of reading
 # a xml but it works and less costly then
 # using a DOM parser just to get a single key
 start_string = "<display-name>"
 end_string = "</display-name>"
 if (filepath.endswith(".jar")) | (filepath.endswith(".ear")):
  # read the zipfile
  zf = zipfile.ZipFile(filepath, "r")
  #Get the list of files in the zipfile
  nl=zf.namelist()
  for name in nl:
   #Check if application.xml is present in the archive
   #The loop will run for as may files in archive but I
   # am sure there will be only one application.xml or
   #you can even change it to include META-INF//application.xml
   if (name.lower().find(("application.xml")) != -1):
    appxml = zf.read(name)
    start_index = appxml.find(start_string) + len(start_string)
    end_index = appxml.find(end_string)
    appname = appxml[start_index:end_index]
   
   #endif
  #endfor
 #endif
 return appname
#enddef

I know closing tags are not required in Jython but its just my style of coding so forgive me for that. I can now use the appname and concatenate whatever I need to and pass it to to AdminApp.install as appOptions.