X

Best Practices from Oracle Development's A‑Team

Automating creation of JDBC Data Sources and DbAdapter plan updates and redeployment

Mark Nelson
Architect

Introduction

That’s a long title… anyway, as part of the desire to have a fully automated continuous integration environment for SOA and BPM, there is another bridge that we need to cross.

Main article

SOA/BPM Composites can contain dependencies on resources in the runtime environment, like JDBC Data Sources and JMS Queues for example.  This poses a challenge for us, as we need to ensure that these resources exist, are properly configured, and are available before we attempt to run our SCA Tests in our composite.

So this means we need a way to automate the creation of these resources, so that we can do this as part of our build process.

This post presents a first step in that direction – a WLST script that can automate the process for JDBC.  I say ‘first step’ for a couple of reasons:

  • It only handles JDBC, nothing else yet,
  • It is a bit delicate – I am not really happy with the error handling (which is almost non-existent, but you have to excuse me on that point, this is my very first Python program ever), and
  • I have not made it handle parameters yet, or integrated it into Maven, although this should just be ‘a small matter of programming’ as the saying goes.

It also implements a restart of the managed server, and I am not 100% sure we actually need to do that.

Anyway, here it is in all its glory – also available from Subversion on java.net (may be newer):

# Copyright 2012 Oracle Corporation. # All Rights Reserved. # # Provided on an 'as is' basis, without warranties or conditions of any kind, # either express or implied, including, without limitation, any warranties or # conditions of title, non-infringement, merchantability, or fitness for a # particular purpose. You are solely responsible for determining the # appropriateness of using and assume any risks. You may not redistribute. # # Please refer to http://redstack.wordpress.com/continous-integration for details. # # This WLST script can be used as part of a continuous integration build process # before deploying a SCA composite, to create any necessary Java EE data sources # on the WebLogic Server. # # In addition to creating the data source, this script will also update the # resource adapter and redeploy it. # # Parts of this script were adapted from Richard van den Berg's post at # https://forums.oracle.com/forums/message.jspa?messageID=10131949#10131949 import time # # These are the parameters that you need to edit before running this script # # admin server url url                  = 't3://localhost:7001' # username to connect to the admin server username             = 'weblogic' # password to connect to the admin server password             = 'welcome1' # the name for the EIS - as defined in the DB Adapter wizard in JDEV eisName              = 'eis/db/myDS' # the admin or managed server to target where the DbAdapter is deployed serverName           = 'soa_server1' nmServerName         = 'soa_server1' # the name for the data source dsName               = 'myDS' # the JNDI name for the data source jndiName             = 'jbdc/myDS' # the database url for the data source dbUrl                = 'jdbc:oracle:thin:@localhost:1521:orcl' # the database user dbUser               = 'mark' # the database password dbPassword           = 'welcome1' # the database driver to use dbDriver             = 'oracle.jdbc.xa.client.OracleXADataSource' # the host where node manager is running nmHost               = 'localhost' # the port to connect to node manager (5556 is default for plain mode) nmPort               = '5556' # the user to connect to node manager nmUser               = 'weblogic' # the password to connection to node manager nmPassword           = 'welcome1' # the name of the weblogic domain domain               = 'base_domain' # don't change these ones uniqueString         = '' appName              = 'DbAdapter' moduleOverrideName   = appName+'.rar' moduleDescriptorName = 'META-INF/weblogic-ra.xml' # # method definitions # def makeDeploymentPlanVariable(wlstPlan, name, value, xpath, origin='planbased'):   """Create a varaible in the Plan.   This method is used to create the variables that are needed in the Plan in order   to add an entry for the outbound connection pool for the new data source.   """   try:     variableAssignment = wlstPlan.createVariableAssignment(name, moduleOverrideName, moduleDescriptorName)     variableAssignment.setXpath(xpath)     variableAssignment.setOrigin(origin)     wlstPlan.createVariable(name, value)   except:     print('--> was not able to create deployment plan variables successfully') def main():   print ' Copyright 2012 Oracle Corporation. '   print ' All Rights Reserved. '   print ''   print ' Provided on an ''as is'' basis, without warranties or conditions of any kind, '   print ' either express or implied, including, without limitation, any warranties or '   print ' conditions of title, non-infringement, merchantability, or fitness for a '   print ' particular purpose. You are solely responsible for determining the '   print ' appropriateness of using and assume any risks. You may not redistribute.'   print ''   print ' Please refer to http://redstack.wordpress.com/continous-integration for details.'   print ''   print ' This WLST script can be used as part of a continuous integration build process'   print ' before deploying a SCA composite, to create any necessary Java EE data sources'   print ' on the WebLogic Server.'   print ''   print ' In addition to creating the data source, this script will also update the '   print ' resource adapter and redeploy it.'   print ''   print ' !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!!'   print ''   print ' This script will make changes to your WebLogic domain.  Make sure you know '   print ' what you are doing.  There is no support for this script.  If something bad '   print ' happens, you are on your own!  You have been warned.'   #   # generate a unique string to use in the names   #   uniqueString = str(int(time.time()))   #   # Create a JDBC Data Source.   #   try:     print('--> about to connect to weblogic')     connect(username, password, url)     print('--> about to create a data source ' + dsName)     edit()     startEdit()     cmo.createJDBCSystemResource(dsName)     cd('/JDBCSystemResources/' + dsName + '/JDBCResource/' + dsName)     cmo.setName(dsName)     cd('/JDBCSystemResources/' + dsName + '/JDBCResource/' + dsName + '/JDBCDataSourceParams/' + dsName)     set('JNDINames',jarray.array([String(jndiName)], String))     cd('/JDBCSystemResources/' + dsName + '/JDBCResource/' + dsName + '/JDBCDriverParams/' + dsName)     cmo.setUrl(dbUrl)     cmo.setDriverName(dbDriver)     cmo.setPassword(dbPassword)     cd('/JDBCSystemResources/' + dsName + '/JDBCResource/' + dsName + '/JDBCConnectionPoolParams/' + dsName)     cmo.setTestTableName('DUAL')     cd('/JDBCSystemResources/' + dsName + '/JDBCResource/' + dsName + '/JDBCDriverParams/' + dsName + '/Properties/' + dsName)     cmo.createProperty('user')     cd('/JDBCSystemResources/' + dsName + '/JDBCResource/' + dsName + '/JDBCDriverParams/' + dsName + '/Properties/' + dsName + '/Properties/user')     cmo.setValue(dbUser)     cd('/JDBCSystemResources/' + dsName + '/JDBCResource/' + dsName + '/JDBCDataSourceParams/' + dsName)     cmo.setGlobalTransactionsProtocol('TwoPhaseCommit')     cd('/JDBCSystemResources/' + dsName)     set('Targets',jarray.array([ObjectName('com.bea:Name=' + serverName + ',Type=Server')], ObjectName))     save()     print('--> activating changes')     activate()     print('--> done') # # update the deployment plan #     print('--> about to update the deployment plan for the DbAdapter')     startEdit()     planPath = get('/AppDeployments/DbAdapter/PlanPath')     appPath = get('/AppDeployments/DbAdapter/SourcePath')     print('--> Using plan ' + planPath)     plan = loadApplication(appPath, planPath)     print('--> adding variables to plan')     makeDeploymentPlanVariable(plan, 'ConnectionInstance_eis/DB/' + dsName + '_JNDIName_' + uniqueString, eisName, '/weblogic-connector/outbound-resource-adapter/connection-definition-group/[connection-factory-interface="javax.resource.cci.ConnectionFactory"]/connection-instance/[jndi-name="' + eisName + '"]/jndi-name')     makeDeploymentPlanVariable(plan, 'ConfigProperty_xADataSourceName_Value_' + uniqueString, eisName, '/weblogic-connector/outbound-resource-adapter/connection-definition-group/[connection-factory-interface="javax.resource.cci.ConnectionFactory"]/connection-instance/[jndi-name="' + eisName + '"]/connection-properties/properties/property/[name="xADataSourceName"]/value')     print('--> saving plan')     plan.save();     save();     print('--> activating changes')     activate(block='true');     cd('/AppDeployments/DbAdapter/Targets');     print('--> redeploying the DbAdapter')     redeploy(appName, planPath, targets=cmo.getTargets());     print('--> done')   except:     print('--> something went wrong, bailing out')     stopEdit('y')     raise SystemExit   #   # disconnect from the admin server   #   print('--> disconnecting from admin server now')   disconnect()   #   # Restart the managed server using the node manager.   #   try:     print('--> about to restart server ' + nmServerName)     nmConnect(nmUser, nmPassword, nmHost, nmPort, domain)     print('--> stopping server...')     nmKill(nmServerName)     print('--> starting server')     nmStart(nmServerName)     print('--> done')     nmDisconnect()   except:     print('--> was not able to restart server successfully') # #  this is the main entry point # main()

To use this script, you need to go edit those parameters at the top of the program, save it somewhere, e.g. createDS.py, and then run it with WLST, for example:

cd /your/fmwhome/wlserver_10.3/common/bin/ wlst.sh /path/to/createDS.py

Please let me know if you have any success, or comments, I would love to hear them.

I must also acknowledge the following folks from whom I borrowed code and ideas: Richard van den Berg and Michel Schildmeijer and in turn those who they borrowed from, and so on.

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha