One of the primary tasks in release management is environment promotion. From development to test or from test to production, environment promotion is a step which should be as much automated as possible.
We can use the service bus MBeans in WLST scripts to automate promotion of AquaLogic/Oracle Service Bus configurations from development environments through testing, staging, and finally to production environments.
Each environment has particularities which may need changes in configuration of the software. These are usually centralized in property files, database tables, environment variables or any other place to facilitate environment promotion.
In AquaLogic/Oracle Service Bus there is the concept of environment values:
Environment values are certain predefined fields in the configuration data whose values are very likely to change when you move your configuration from one domain to another (for example, from test to production). Environment values represent entities such as URLs, URIs, file and directory names, server names, e-mails, and such. Also, environment values can be found in alert destinations, proxy services, business services, SMTP Server and JNDI Provider resources, and UDDI Registry entries.
For these environment values, we have different standard operations
- Finding and Replacing Environment Values
- Creating Customization Files
- Executing Customization Files
However, these operations are limited to the ‘predefined fields whose values are very likely to change’… and what happens if we need to modify one of the considered ‘not very likely’? A different story is whether to consider SAP client connection parameters ‘not very likely’ to change in a environment promotion from test to production…
In order to automate these necessary changes, one option is to modify directly the exported configuration prior to importing it to the destination environment but in our case, we want to maintain the philosophy of the customization after the importing, keeping the exported package untouched. We will try to use a WLST script instead of a customization file, as the later doesn’t satisfy our needs.
The first thing we have to do for using WLST is to add several service bus jar files to the WLST classpath. For example, if we have a Windows platform we add the following at the beginning of wlst.cmd file (I’m sure *nix people will know how to proceed in their case)
For Aqualogic Service Bus 3.0:
SET ALSB_HOME=c:\bea\alsb_3.0 SET CLASSPATH=%CLASSPATH%;%ALSB_HOME%\lib\sb-kernel-api.jar SET CLASSPATH=%CLASSPATH%;%ALSB_HOME%\lib\sb-kernel-common.jar SET CLASSPATH=%CLASSPATH%;%ALSB_HOME%\lib\sb-kernel-resources.jar SET CLASSPATH=%CLASSPATH%;%ALSB_HOME%\lib\sb-kernel-impl.jar SET CLASSPATH=%CLASSPATH%;%ALSB_HOME%\..\modules\com.bea.common.configfwk_188.8.131.52.jar SET CLASSPATH=%CLASSPATH%;%ALSB_HOME%\..\modules\com.bea.alsb.statistics_184.108.40.206.jar
For Oracle Service Bus 10gR3:
SET ALSB_HOME=c:\bea\osb_10.3 SET CLASSPATH=%CLASSPATH%;%ALSB_HOME%\lib\sb-kernel-api.jar SET CLASSPATH=%CLASSPATH%;%ALSB_HOME%\lib\sb-kernel-common.jar SET CLASSPATH=%CLASSPATH%;%ALSB_HOME%\lib\sb-kernel-resources.jar SET CLASSPATH=%CLASSPATH%;%ALSB_HOME%\lib\sb-kernel-impl.jar SET CLASSPATH=%CLASSPATH%;%ALSB_HOME%\..\modules\com.bea.common.configfwk_220.127.116.11.jar SET CLASSPATH=%CLASSPATH%;%ALSB_HOME%\..\modules\com.bea.alsb.statistics_18.104.22.168.jar
In our example, we will try to change the HTTP timeout in the normalLoanProcessor business service present in ALSB/OSB examples server.
For that, we will first connect to the bus from WLST and open a session using SessionManagementMBean
from com.bea.wli.sb.management.configuration import SessionManagementMBean connect("weblogic", "weblogic", "t3://localhost:7021") domainRuntime() sessionMBean = findService(SessionManagementMBean.NAME, SessionManagementMBean.TYPE) sessionName = "mysession" sessionMBean.createSession(sessionName)
Nothing new until now. Next thing we need is a reference to the component you want to modify. We chose to use a BusinessServiceQuery like:
from com.bea.wli.sb.management.query import BusinessServiceQuery from com.bea.wli.sb.management.configuration import ALSBConfigurationMBean bsQuery = BusinessServiceQuery() bsQuery.setLocalName("normalLoanProcessor") bsQuery.setPath("MortgageBroker/BusinessServices") alsbSession = findService(ALSBConfigurationMBean.NAME + "." + sessionName, ALSBConfigurationMBean.TYPE) refs = alsbSession.getRefs(bsQuery) bsRef = refs.iterator().next()
After this we have a reference to the business service we want to modify. Now is when fun begins.
There is an undocumented service bus ServiceConfigurationMBean (not to be confused with old com.bea.p13n.management.ServiceConfigurationMBean) whose description is ‘MBean for configuring Services’.
Among the different methods, we find one with an interesting name: getServiceDefinition
It looks that we can use the getServiceDefinition method with our previous reference to the business service for obtaining exactly what its name states.
from com.bea.wli.sb.management.configuration import ServiceConfigurationMBean servConfMBean = findService(ServiceConfigurationMBean.NAME + "." + sessionName, ServiceConfigurationMBean.TYPE) serviceDefinition = servConfMBean.getServiceDefinition(bsRef)
This is the result of printing serviceDefinition variable:
NormalLoanApprovalServiceSoapBinding http://example.org 5 normal wsdl-policy-attachments http false http://localhost:7021/njws_basic_ejb/NormalSimpleBean none 0 30 true POST 0
Surprised? It’s exactly the same definition written in .BusinessService XML files. In fact, the service definition implements XMLObject.
Now it’s time to update the business service definition with our new timeout value (let’s say 5000 milliseconds) using XPath and XMLBeans. We must also take care of defining namespaces in XPath the same way that are defined in .BusinessService XML files.
nsEnv = "declare namespace env='http://www.bea.com/wli/config/env' " nsSer = "declare namespace ser='http://www.bea.com/wli/sb/services' " nsTran = "declare namespace tran='http://www.bea.com/wli/sb/transports' " nsHttp = "declare namespace http='http://www.bea.com/wli/sb/transports/http' " nsIWay = "declare namespace iway='http://www.iwaysoftware.com/alsb/transports' " confPath = "ser:endpointConfig/tran:provider-specific/http:outbound-properties/http:timeout" confValue = "5000" confElem = serviceDefinition.selectPath(nsSer + nsTran + nsHttp + confPath) confElem.setStringValue(confValue)
We are almost there. First we update the service.
And finally, we activate the session (see NOTE) like we would do in bus console.
With this approach, it could be possible to build a framework that allows to customize ALL fields as needed.
Traceback (innermost last): File "
", line 1, in ? com.bea.wli.config.deployment.server.ServerLockException: Failed to obtain WLS Edit lock; it is currently held by user weblogic. This indicates that you have either started a WLS change and forgotten to activate it, or another user is performing WLS changes which have yet to be activated. The WLS Edit lock can be released by logging into WLS console and either releasing the lock or activating the pending WLS changes. at com.bea.wli.config.deployment.server.ServerDeploymentInitiator.__serverCommit(Unknown Source) at com.bea.wli.config.deployment.server.ServerDeploymentInitiator.access$200(Unknown Source) at com.bea.wli.config.deployment.server.ServerDeploymentInitiator$1.run(Unknown Source) at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363) at weblogic.security.service.SecurityManager.runAs(Unknown Source) at com.bea.wli.config.deployment.server.ServerDeploymentInitiator.serverCommit(Unknown Source) at com.bea.wli.config.deployment.server.ServerDeploymentInitiator.execute(Unknown Source) at com.bea.wli.config.session.SessionManager.commitSessionUnlocked(SessionManager.java:420) at com.bea.wli.config.session.SessionManager.commitSession(SessionManager.java:339) at com.bea.wli.config.session.SessionManager.commitSession(SessionManager.java:297) at com.bea.wli.config.session.SessionManager.commitSession(SessionManager.java:306) at com.bea.wli.sb.management.configuration.SessionManagementMBeanImpl.activateSession(SessionManagementMBeanImpl.java:47) [...]