Saturday 26 May 2012

Deploying OSB components onto different environments

Each OSB expert has already faced the problem of deployment. This task seems to be pretty obvious at first glance but it is quite sophisticated if we dig into the details.
There are many values in the OSB components which are different in each environment (local / development / test / ... / production server). We would like to use the same sourcecode to deploy it into the test server or production server, we want to use a CI tool so it is not possible to use constant values in the source.

The customization file could be a perfect solution for this job ... but it is not. At least it was not the best solution to me.

Let me explain it: I had to send an email in a proxy service. The receiver of the email must be different in the production, the test and the development environments (it is obvious as we wouldn't like to send emails to the business users during tests...). I set the receiver of the email in the message flow by modifying the the Transport Header. We cannot modify this value by the help of the Customization File.
Other example is to change the port number of the SMTP server (you can change the endpoint URL of the SMTP server but not the port number which is a separate property of SMTP server).
There are a lot of other examples too where the Customization File fail so I had to find an other solution to change the values in the proxy services.

Unfortunately I could find any other solution (OSB 11.1.1.3.0) how to change these values. I could work out just one solution: change the XML file of proxy service. It seems to be a sophisticated (or tough ...) solution but you can get used to it. :)
An XML file is created when you produce a proxy service. All you need to do is to find the value in the XML that you want to change and create an XPath to find it in the XML. Afterwards you can change the value with an ant task for example. Unfortunately this is not so easy either...

The first problem is that we don't want to modify the files in the source folder of our local machine. Let's imagine your workspace is in C:\work\OSB\workspace (apologize to the Linux users :) ). You are using your workspace for deploying OSB components into your local OSB domain so I don't think that you'd want to mess that folder.
Besides we need a JAR file as a result with all the environment dependent modifications and we just want to deploy it onto the given domain (see Continuous Integration).
So this is my scenario:
  1. create a deployable JAR file
  2. unzip the JAR file into a temporary folder
  3. change the values according to the given environment
  4. create the JAR files from temporary folder
I used this ANT task at the first step:

<target name="build">
  <delete failonerror="false" includeemptydirs="true" dir="${metadata.dir}"/>
  <java dir="${eclipse.home}"
        jar="${eclipse.home}/plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar"
        fork="true" failonerror="true" maxmemory="768m">
    <jvmarg line="-XX:MaxPermSize=256m"/>   
    <arg line="-data ${workspace.dir}"/>
    <arg line="-application com.bea.alsb.core.ConfigExport"/>
    <arg line="-configProject ${config.project}"/>
    <arg line="-configJar ${config.jar}"/>
    <arg line="-configSubProjects ${config.subprojects}"/>
    <arg line="-includeDependencies ${config.includeDependencies}"/>
    <sysproperty key="weblogic.home" value="${weblogic.home}"/>
    <sysproperty key="osb.home" value="${osb.home}"/>
    <sysproperty key="osgi.bundlefile.limit" value="500"/>
    <sysproperty key="harvester.home" value="${osb.home}/harvester"/>
    <sysproperty key="osgi.nl" value="en_US"/>
    <sysproperty key="sun.lang.ClassLoader.allowArraySyntax" value="true"/>
  </java>
</target>

Performing the second step wasn't very difficult:

<unzip src="${config.jar}" dest="../${env.BUILD_ENVIRONMENT}/tmp"/>

There are more ways for modifying the values unfortunately I chose an inconvenient and sophisticated one. :)

<target name="_change.values">
  <xmltask source="../${env.BUILD_ENVIRONMENT}/tmp/System/SMTP_Servers/EmailServer.SMTPServer" dest="../${env.BUILD_ENVIRONMENT}/tmp/System/SMTP_Servers/EmailServer.SMTPServer">
    <!-- change email server URL -->
    <replace path="/xml-fragment/*[local-name(.)='serverURL']/text()" withText="${EmailServer.smtp.Server_URL}"/>
    <!-- change email server port number -->
    <replace path="/xml-fragment/*[local-name(.)='portNumber']/text()" withText="${EmailServer.smtp.Port_Number}"/>
  </xmltask>
  ...

And I created a properties file and I defined the values.

EmailServer.smtp.Server_URL=XXXXXX
EmailServer.smtp.Port_Number=25

Creating a JAR file is easy too:

<jar destfile="${config.jar}" basedir="../${env.BUILD_ENVIRONMENT}/tmp"/>

Unfortunately I had to implement a 2.1 and 2.2 step as well... When the JAR file was created by the Weblogic ANT task the Configuration Project level resources (e.g. SMTP server) weren't put into the JAR. I don't know it was a problem of the ANT task or I made something badly (but of course it is less likely...:) ).
So I had to copy some folders (see below) into the JAR by the help of ANT and modify the ExportInfo file into the JAR too.


UPDATE
I uploaded my deploy framework that I used to deploy the components, please let me know if you have any issue.

10 comments:

  1. it's really cool, I didn't know about this xmltask, I have been struggling myself to do a targeted find & replace in the OSB projects.... thanks a lot my friend!

    ReplyDelete
  2. We use this construction too to update our sla settings during otap deployment, since there isn't an option to change these by use of customization.

    ReplyDelete
  3. Sorry Pierluigi and Eric for the late reply. I hope this "mistake" will be fixed later in OSB as in my opinion it is quite dangerous to modify the XML files with this xml ant task.
    Eric, may I ask what tools you use to modify the XML? I think there are simpler ways (than this xmltask) to do it.

    ReplyDelete
  4. Beware of unzipping the config.jar and then rezipping it especially in a Windows environment. The reason for this is that the file names of the resources in the jar are "mangled/shortened" such that the filenames when extracted to a non case-sensitive file system (like Windows) can end up being duplicated so that when you re-zip the jar you have essentially corrupted it.
    I wanted to use the above approach to inject service account username/passwords at deployment time and ended up having to use a custom Ant task that used Java 7 FileSystem functionality to treat a zip like a FileSystem so the resources could be modified in memory rather than "overlaying" the zip file system onto a Windows Filesystem and thereby suffering from the "duplicate filename" problems that can occur.

    ReplyDelete
  5. Hi Mallyboy, thanks for the idea. I wasn't aware of this problem but you are right!

    ReplyDelete
  6. Hi,
    It is really helpful to me.Thanks for sharing ...
    As we know we can change the business url for each enavironmnet using customization file.
    I have a scenario like,routing node of Proxy service,there is one variable called businessuri and it is having the value as business url .

    How can we change this value when we deploying the jar into different environment.

    I need to do this changes for more than 3 services.

    How can I achieve this ?

    Please help me.

    Thanks,

    ReplyDelete
    Replies
    1. This comment has been removed by a blog administrator.

      Delete
    2. Hi,

      Sorry for the late answer!
      There are two options to change the endpoint at Routing:
      - by using Routing Options -> you can change the value in the XML of the proxy service by using an XPath like this /xml-fragment/ser:router/con:flow/con:route-node/con:actions/con1:route/con1:outboundTransform/con3:routing-options/con3:uriExpr/con2:xqueryText

      - modifying the endpoint in the business service
      the XPath is /xml-fragment/ser:endpointConfig/tran:URI/env:value

      You have to choose one of the 2 choices above, define the XPath in the ant xmltask and set the new endpoint in the property file.
      Please let me know if you have other question or my answer is not clear yet.

      Delete
    3. HI,

      Thanks for your reply.
      I have few more doubts.I need to change the endpoint in business service as well in proxy routing node.
      proxy: xml-fragment/ser:router/con:flow/con:route-node/con:actions/con1:routingTable/con1:case/con1:route/con1:outboundTransform/con3:assign/con3:expr/con:xqueryText

      business: xml-fragment/ser:endpointConfig/tran:URI/env:value

      These are the path where i need to change the business end point.

      Can I change these two using xmltask.

      I have an already deployed jar for dev environment.I need to deploy the same jar in IT but with this environment url change.As per my understanding i need to unzip the jar into a temp folder and then change the values according to our environment using xmltask.Then create the jar from temp folder.

      Where we need to put this xmltask,property file..and where we use ant script.How can we run this xmltask?

      Also can you please explain the steps 2.1 & 2.2 mentioned above.

      Thanks,


      Delete
    4. Hi,
      I uploaded my deploy framework, there is some example in that how to use the xmltask.
      Please let me know if something is not clear.
      Thanks,
      V.

      Delete