Getting started with Continuous Integration for OSB

As a first step towards including Oracle Service Bus projects into our Continuous Integration environment, let’s look at how to script exporting some project(s) from Oracle Enterprise Pack for Eclipse (the IDE for OSB) and deploying those project(s) to an OSB server.  Later, we will include this into the Maven/Hudson environment we have been constructing in this series of posts on continuous integration.

Here is our script, right up front, then we will discuss it:

@echo Export project from eclipse
java ^
  -Dweblogic.home=c:\oracle\middleware\wlserver_10.3 ^
  -Dosb.home=c:\oracle\middleware\Oracle_OSB1 ^
  -Dosgi.bundlefile.limit=500 ^
  -Dharvester.home=c:\oracle\middleware\Oracle_OSB1\harvester ^
  -Dosgi.nl=en_US ^
  -Dsun.lang.ClassLoader.allowArraySyntax=true ^
  -jar c:\Oracle\OEPE\oepe_11gR1PS4\plugins\org.eclipse.equinox.launcher_1.1.1.R36x_v20101122_1400.jar ^
  -data c:\src\osb\notsvn ^
  -application com.bea.alsb.core.ConfigExport ^
  -configProject "OSB Configuration 1" ^
  -configJar c:\src\osb\test_sbconfig.jar ^
  -configSubProjects "OSB Project 1" ^
  -includeDependencies true

@echo Deploy 'import' to Service Bus
c:\oracle\middleware\oracle_common\common\bin\wlst import.py import.properties

First of all, if you have not seen them before, the ‘^’ is a continuation character in Windows CMD files, such as this one, so that we can spread a command over many lines in our script, but it is executed as if it were all typed in on a single line.

This script has not been made generic yet – it has a bunch of stuff hardcoded.  Let’s take a look.

First, we run java with a bunch of properties.  You will need to set weblogic.home, osb.home and harvester.home to suit your environment.  You can just include the others as they are.

Following the properties, you see we point to a JAR file, this allows us to run eclipse in headless mode.  The remainder of the parameters are passed to eclipse.  You can see we need to specify the location of the workspace to use (in data) – this can also be the Subversion trunk (or similar).  The application tells it to run the OSB exporter.

The other important parameters are configProject which names the OSB Configuration project in the workspace you want to use, configSubProjects which is a comma separated list of the OSB projects you want to export, and configJar which is the name of the JAR file you want to create.

If you want to know more about this command, take a look in the online help in your OSB IDE.  Look under the OSB help topic, then ‘Tasks,’ ‘Working with projects, folders, resources & configurations,’ ‘exporting resources,’ ‘using command line,’ and then the ANT topic.

When this command has run, we will have an OSB configuration JAR file (test_sbconfig.jar in this case) which is ready to import into (deploy to) an OSB server.

The second part is to perform the deployment (import).  We will do this using a WLST script from Oracle, import.py (see below).  This script also expects a properties file.  We need to set up some details in the properties file so the script knows what to do.

Let’s take a look at the properties file:

##################################################################
# OSB Admin Security Configuration                              #
##################################################################
adminUrl=t3://localhost:7001
importUser=weblogic
importPassword=welcome1

##################################################################
# OSB Jar to be exported, optional customization file           #
##################################################################
importJar=test_sbconfig.jar
#customizationFile=OSBCustomizationFile.xml

##################################################################
# Optional passphrase and project name                           #
##################################################################
#passphrase=osb
#project=default

You can see we have provided the URL for the Administration Server, and also the name of the OSB configuration JAR file (that we just created in the previous step).

Here is the import.py sciript that WLST will run:

from java.util import HashMap
from java.util import HashSet
from java.util import ArrayList
from java.io import FileInputStream

from com.bea.wli.sb.util import Refs
from com.bea.wli.config.customization import Customization
from com.bea.wli.sb.management.importexport import ALSBImportOperation

import sys

#=======================================================================================
# Entry function to deploy project configuration and resources
#        into a ALSB domain
#=======================================================================================

def importToALSBDomain(importConfigFile):
    try:
        SessionMBean = None
        print 'Loading Deployment config from :', importConfigFile
        exportConfigProp = loadProps(importConfigFile)
        adminUrl = exportConfigProp.get("adminUrl")
        importUser = exportConfigProp.get("importUser")
        importPassword = exportConfigProp.get("importPassword")

        importJar = exportConfigProp.get("importJar")
        customFile = exportConfigProp.get("customizationFile")

        passphrase = exportConfigProp.get("passphrase")
        project = exportConfigProp.get("project")

        connectToServer(importUser, importPassword, adminUrl)

        print 'Attempting to import :', importJar, "on ALSB Admin Server listening on :", adminUrl

        theBytes = readBinaryFile(importJar)
        print 'Read file', importJar
        sessionName = createSessionName()
        print 'Created session', sessionName
        SessionMBean = getSessionManagementMBean(sessionName)
        print 'SessionMBean started session'
        ALSBConfigurationMBean = findService(String("ALSBConfiguration.").concat(sessionName), "com.bea.wli.sb.management.configuration.ALSBConfigurationMBean")
        print "ALSBConfiguration MBean found", ALSBConfigurationMBean
        ALSBConfigurationMBean.uploadJarFile(theBytes)
        print 'Jar Uploaded'

        if project == None:
            print 'No project specified, additive deployment performed'
            alsbJarInfo = ALSBConfigurationMBean.getImportJarInfo()
            alsbImportPlan = alsbJarInfo.getDefaultImportPlan()
            alsbImportPlan.setPassphrase(passphrase)
            alsbImportPlan.setPreserveExistingEnvValues(true)
            importResult = ALSBConfigurationMBean.importUploaded(alsbImportPlan)
            SessionMBean.activateSession(sessionName, "Complete test import with customization using wlst")
        else:
            print 'ALSB project', project, 'will get overlaid'
            alsbJarInfo = ALSBConfigurationMBean.getImportJarInfo()
            alsbImportPlan = alsbJarInfo.getDefaultImportPlan()
            alsbImportPlan.setPassphrase(passphrase)
            operationMap=HashMap()
            operationMap = alsbImportPlan.getOperations()
            print
            print 'Default importPlan'
            printOpMap(operationMap)
            set = operationMap.entrySet()

            alsbImportPlan.setPreserveExistingEnvValues(true)

            #boolean
            abort = false
            #list of created ref
            createdRef = ArrayList()

            for entry in set:
                ref = entry.getKey()
                op = entry.getValue()
                #set different logic based on the resource type
                type = ref.getTypeId
                if type == Refs.SERVICE_ACCOUNT_TYPE or type == Refs.SERVICE_PROVIDER_TYPE:
                    if op.getOperation() == ALSBImportOperation.Operation.Create:
                        print 'Unable to import a service account or a service provider on a target system', ref
                        abort = true
                elif op.getOperation() == ALSBImportOperation.Operation.Create:
                    #keep the list of created resources
                    createdRef.add(ref)

            if abort == true :
                print 'This jar must be imported manually to resolve the service account and service provider dependencies'
                SessionMBean.discardSession(sessionName)
                raise

            print
            print 'Modified importPlan'
            printOpMap(operationMap)
            importResult = ALSBConfigurationMBean.importUploaded(alsbImportPlan)

            printDiagMap(importResult.getImportDiagnostics())

            if importResult.getFailed().isEmpty() == false:
                print 'One or more resources could not be imported properly'
                raise

            #customize if a customization file is specified
            #affects only the created resources
            if customFile != None :
                print 'Loading customization File', customFile
                print 'Customization applied to the created resources only', createdRef
                iStream = FileInputStream(customFile)
                customizationList = Customization.fromXML(iStream)
                filteredCustomizationList = ArrayList()
                setRef = HashSet(createdRef)

                # apply a filter to all the customizations to narrow the target to the created resources
                for customization in customizationList:
                    print customization
                    newcustomization = customization.clone(setRef)
                    filteredCustomizationList.add(newcustomization)

                ALSBConfigurationMBean.customize(filteredCustomizationList)

            SessionMBean.activateSession(sessionName, "Complete test import with customization using wlst")

        print "Deployment of : " + importJar + " successful"
    except:
        print "Unexpected error:", sys.exc_info()[0]
        if SessionMBean != None:
            SessionMBean.discardSession(sessionName)
        raise

#=======================================================================================
# Utility function to print the list of operations
#=======================================================================================
def printOpMap(map):
    set = map.entrySet()
    for entry in set:
        op = entry.getValue()
        print op.getOperation(),
        ref = entry.getKey()
        print ref
    print

#=======================================================================================
# Utility function to print the diagnostics
#=======================================================================================
def printDiagMap(map):
    set = map.entrySet()
    for entry in set:
        diag = entry.getValue().toString()
        print diag
    print

#=======================================================================================
# Utility function to load properties from a config file
#=======================================================================================

def loadProps(configPropFile):
    propInputStream = FileInputStream(configPropFile)
    configProps = Properties()
    configProps.load(propInputStream)
    return configProps

#=======================================================================================
# Connect to the Admin Server
#=======================================================================================

def connectToServer(username, password, url):
    connect(username, password, url)
    domainRuntime()

#=======================================================================================
# Utility function to read a binary file
#=======================================================================================
def readBinaryFile(fileName):
    file = open(fileName, 'rb')
    bytes = file.read()
    return bytes

#=======================================================================================
# Utility function to create an arbitrary session name
#=======================================================================================
def createSessionName():
    sessionName = String("SessionScript"+Long(System.currentTimeMillis()).toString())
    return sessionName

#=======================================================================================
# Utility function to load a session MBeans
#=======================================================================================
def getSessionManagementMBean(sessionName):
    SessionMBean = findService("SessionManagement", "com.bea.wli.sb.management.configuration.SessionManagementMBean")
    SessionMBean.createSession(sessionName)
    return SessionMBean

# IMPORT script init
try:
    # import the service bus configuration
    # argv[1] is the export config properties file
    importToALSBDomain(sys.argv[1])

except:
    print "Unexpected error: ", sys.exc_info()[0]
    dumpStack()
    raise

You need to put the original script, import.py and import.properties all in to the same directory.  Now you can run our original script and it will perform the export from eclipse and the deployment to OSB.

In a future post, we will be parameterizing this and folding it into our Hudson/Maven oriented continuous integration environment.

About Mark Nelson

Mark Nelson is an Architect ("IC6") in the Platform Architecture Team in Oracle Development. Mark's focus area is continuous delivery, configuration management and provisioning - making it simple to manage the configuration of complex environments and applications built with Oracle Database, Fusion Middleware and Fusion Applications, on-premise and in the cloud. Before joining the Platform Architecture team, Mark was a senior member of the A-Team since 2010, and worked in Sales Consulting at Oracle since 2006 and various roles at IBM since 1994.
This entry was posted in Uncategorized and tagged , . Bookmark the permalink.

5 Responses to Getting started with Continuous Integration for OSB

  1. Mark, I’m going to try and implement CI for OSB on Hudson/Jenkins, and was wondering if you were going to do a followup post covering that topic.

    • Mark Nelson says:

      Hi Rob,
      Yes I am planning to do a follow up post around the time that OSB PS6 is released…
      Mark

  2. Pingback: Building OSB projects with Maven and removing the eclipse dependency | RedStack

  3. Pingback: Building OSB projects with Maven and removing the eclipse dependency by Mark Nelson | SOA Community Blog

  4. archenroot says:

    Hi Mark,
    very good article, I am going to experiment with this topic in these days. Keep going and thank you.
    Ladislav

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s