Monday, March 23, 2009

Reading csv File in WLST Script

One of the comment for an earlier post was about creating domain(s) from csv file with WLST. Creating domain using WLST is a fairly simple and straight forward process. So I decided to explain the simple concept of reading a csv file and creating a domain using an example.

The main trick is to use the Jython language libraries to perform some of the required operations. In my example I shall illustrate how to read command-line arguments, open and read files using Jython. I am also using some local function definitions to create some modular script here. The following is an example of a comma seperated value file that our WLST script can read to create one or more domains:


#domainName,domainLocation,adminUser,adminPassword,adminServerAddress,adminServerPort
testDomain,/home/oracle/domains,system,weblogic,localhost,8998
anotherDomain,/home/oracle/domains,system,weblogic,localhost,7887


Comment lines start with # and each line that is not a comment line represent values for a domain such as domain name, location etc. The script to read the csv file and create the domain can be something like this:


### Script to create WebLogic Domain(s) from csv file
### Reusable Definitions
def buildDomain():
### Read Basic Template
readTemplate(WL_HOME+"/common/templates/domains/wls.jar")
cd('Servers/AdminServer')
set('ListenAddress', adminServerAddress)
set('ListenPort', int(adminServerPort))

### Create Admin User
cd('/')
cd('Security/base_domain/User')
delete('weblogic','User')
create(adminUser,'User')
cd(adminUser)
set('Password',adminPassword)
set('IsDefaultAdmin',1)

### Write Domain
setOption('OverwriteDomain', 'true')
writeDomain(domainLocation+'/'+domainName)
closeTemplate()

def printConfirmation():
### Print Confirmation
print ""
print "Created Domain With Following Values"
print "Domain Name = %s " % domainName
print "Domain Location = %s " % domainLocation
print "Admin User = %s " % adminUser
print "Admin Password = %s " % adminPassword
print "Admin Server Address = %s " % adminServerAddress
print "Admin Server port = %s " % adminServerPort

### Executable Script
### CreateDomain.py
import sys

### Define constants
WL_HOME = "/products/beaSB/wlserver_10.0"

### Read the command-line arguments
argslength = len(sys.argv)
if argslength < 2 :
print '==>Insufficient arguments'
print '==>Syntax: java weblogic.WLST CreateDomain.py csv.file'
exit()
else:
### Read the csv file
fileName = sys.argv[1]
print('Reading File \"' + fileName + '\"' )
f = open(fileName)
try:
for line in f.readlines():
### Strip the comment lines
if line.strip().startswith('#'):
continue
else:
### Split the comma seperated values
items = line.split(',')
items = [item.strip() for item in items]
if len(items) != 6:
print "==>Bad line: %s" % line
print "==>Syntax: domainName, domainLocation, adminUser, adminPassword, adminServerAddress, adminServerPort"
else:
(domainName, domainLocation, adminUser, adminPassword, adminServerAddress, adminServerPort) = items

### Call the definition buildDomain
buildDomain()

### Call the definition printConfirmation
printConfirmation()

except Exception, e:
print "==>Error Occured"
print e
exit()


The executable part of the script is something that is not marked as a definition and in this case it start with the import statement. Any command-line or program arguments passed to WLST are available through sys.argv array. The array is zero indexed and the first element of the array sys.argv[0] is the script file itself. In our script we check to make sure that atleast 2 arguments including the script filename exists.


...
### Read the command-line arguments
argslength = len(sys.argv)
if argslength < 2 :
print '==>Insufficient arguments'
print '==>Syntax: java weblogic.WLST CreateDomain.py csv.file'
exit()
else:
...


Built-in functions are then used to open and read the csv file.


...
f = open(fileName)
try:
for line in f.readlines():
...


We are Using the startswith to eliminate the comment lines and then using the split and strip string function to create a list of all the items passed from the command-line. Later after checking the number of values in each line the list is assigned to a tuple of variable names (tuple is immutable in Jython where as Lists are mutable).


(domainName, domainLocation, adminUser, adminPassword, adminServerAddress, adminServerPort) = items


Once we have all values read and stored in the respective variables then it is pretty straight forward to create a domain which in this case was built as function definition (buildDomain). Later all the values were sent to standard output for user's attention. Also any exception will be reported with the try...except block.

Monday, March 2, 2009

Check for resource/configuration existence [WLST scripting Best Practices (Part-3)]

This post is a continuation of my previous post in a series of posts about WLST scripting best practices. When you are authoring WLST scripts to create new resource/configuration in WebLogic domain then check for its existence. If the resource/configuration already exists then you might get an error similar to the following:

weblogic.descriptor.BeanAlreadyExistsException: Bean already exists

A simple approach is to use the "cd" command to navigate into that configuration MBean. If the "cd" command throws an exception then you can safely assume that the resource/configuration doesn't exists and you can continue creating.

...
### Check for the server
try:
cd('/Servers/' + mgdServerName)
print '===> Server \"' +mgdServerName+'\" already exists'
print '===> No action was performed'
exit()
except:
pass
...


The other approach is to catch the "BeanAlreadyExistsException" while creating the resource and safely exiting the script.


...
### Create the Managed Server
edit()
startEdit()
try:
create(mgdServerName, resourceType)
print '===> Created Managed Server - ' + mgdServerName
pass
except BeanAlreadyExistsException:
print '===> Server \"' +mgdServerName+'\" already exists'
print '===> No action was performed'
cancelEdit('y')
exit()
...

But with this approach you are starting an edit session and creating the server to find out it's existence. So you have to cancel the edit session once you find out that the resource that you are creating already exists if not you might get a warning message similar to the following:

You have an edit session open and you will lose all outstanding changes and your edit session will be stopped if you exit. Are you sure you would like to exit? (y/n)

So cancelling the edit session with a responce 'y' will make WLST not to prompt for user response. I shall discuss how to streamline the outputs from WLST and redirect them to an output file or log file in a later post.

WLST-BP-3 Check for the resource or configuration existence before creating them