Wednesday, 13 July 2016

Create WebLogic users for ServiceBus 12c - Part 2

Last week I wrote a blog about how to create WebLogic users for ServiceBus 12c. However, I did not now how to assign a particular Application Specific Role to the weblogic user, for particular ServiceBus privileges. I did find out what particular Roles there were (see the blog). But how to assign them I found out just today.

So here it is:
#
#
def grantOSBAppRoleToWlsGroup(osbAppRole, wlsGroup):
    #
    # Grant OSB AppRole
    # http://docs.oracle.com/cd/E23943_01/web.1111/e13813/custom_infra_security.htm#WLSTC1398
    # grantAppRole(appStripe, appRoleName,principalClass, principalName)
    # appStripe: Specifies an application stripe.
    # appRoleName: Specifies a role name.
    # principalClass: Specifies the fully qualified name of a class.
    # principalName: Specifies the principal name.
    #grantAppRole("Service_Bus_Console","Monitor","oracle.security.jps.service.policystore.ApplicationRole","SBMonitor")
    #grantAppRole("Service_Bus_Console","Tester","weblogic.security.principal.WLSUserImpl","weblogic")
    try:
      print('Grant OSB Role: '+osbAppRole+' to WebLogic Group: '+wlsGroup)
      grantAppRole("Service_Bus_Console",osbAppRole,"weblogic.security.principal.WLSGroupImpl",wlsGroup)
      print('Grant Succeeded')
    except:
      print('Failed to grant role '+ osbAppRole+' to '+wlsGroup+'.')
      print('Check if role not already granted.') 

Add this to the createUsers.py script in my previous article.
Then add the following call to add a role to a group:
    #
    # Grant AppRole
    grantOSBAppRoleToWlsGroup(grpOsbDevOSBAppRole, grpOsbDevName)

This needs the following property in the property file:
# Possible App Roles: MiddlewareAdministrator, Developer, Composer, Deployer, Tester, Monitor, MiddlewareOperator, ApplicationOperator, APICurator
grpOsbDevOSBAppRole=Developer

In the comments I provided the possible values that are described in the docs (see again my previous article).

A description of the grantAppRole can be found here in the 11g docs.

The possible parameters of the function are:


Argument
Definition
appStripeSpecifies an application stripe. For SB12c it is: 'Service_Bus_Console'. You can get it from the pop-list in the EM, WebLogic Domain Menu->Security->Application Roles->Application Stripes Pull Down. (See here).
appRoleNameSpecifies a role name. For SB12c this is one of: MiddlewareAdministrator, Developer, Composer, Deployer, Tester, Monitor, MiddlewareOperator, ApplicationOperator, APICurator
principalClass Specifies the fully qualified name of a class. Unclear from the docs what to use. But I found (actually on a BI-EE blog):
  • For WebLogic users: weblogic.security.principal.WLSUserImpl
  • For WebLogic groups: weblogic.security.principal.WLSGroupImpl
  • Apparently for Application Roles: oracle.security.jps.service.policystore.ApplicationRole
principalNameSpecifies the principal name.


With this you can enhance the createUsers script to create actual ServiceBus users. For SOASuite or other components you can get the Application Specific Roles by querying the Application Stripe in EM.

Monday, 11 July 2016

Reset your Datasources

In most SOASuite and Oracle ServiceBus projects the Database Adapter is used. And often it is used to invoke PL/Sql functions and procedures. Actually, it's my favorite interaction method with the database, since the re-entrancy of the database adapter wizard is best there. To do a re-entrant update of a select or DML operation when for instance a column is added, is simply put often quite problematic.

But the thing is with Pl/Sql that when you update a pl/sql package the package state is altered and when calling it from another session you'll get a 'ORA-04068: existing state of packages has been discarded' error. And this is will occur for every connection in the pool of your datasource.

The solution is to reset the datasource. This can be done easily in the WebLogic Administration Console (http://adminserver:port/console). But nowadays you can do it as easily in Enterprise Manager Fusion Middleware Control. This can be quite convenient for developers since often you have EM already open because of your SOASuite tests.

To do this open the Weblogic Domain menu and select the option 'JDBC DataSources':
 Select the DataSource you want to reset, for the example I choose the 'EDNDataSource', but probably you'd not do this for one, but for a custom DataSource:

 Click the Control tab, select the DataSource in the table and click Reset:

Reset will drive WebLogic to recreate all the connections in the DataSource. This prevents popping up the message multiple times.

The functionality in Configuring, Monitoring and Controlling the Datasource  is similar as in the WebLogic Admin console. Only the layout is a little different.

Thursday, 7 July 2016

Create Weblogic users for ServiceBus

At one of my customers there was the question of creating users that needed to log on to EM (Fusion MiddleWare Control) and Service bus console to be able  to deploy SB en WLS Artefacts (queues, datasources etc.) on the Dev and Test environment. And to be able to do some monitoring on Acceptance. Further more they still used weblogic as the only, shared, administrator user. For the latter Oracle recommends to create at least one other user, to prevent you from an accidental admin-lockout. So I'd create named admin-users for each administrator.

Since there were several users to provision on several systems, it would be convenient to have a script to create the users and the particular groups.

As for the Roles there we need to differentiate to WebLogic default roles and and groups, and Service Bus roles.

To be able to log on to the EM, WLS Console and/or Servicebus the user at least needs the WLS Monitor role, which is provided using the Monitors group. But to be able to start and stop servers (that the developers need/want on dev and at this customer also test) you need the Operators group. To be able to create WLS Artefacts, the user need to be in the Deployers group. More on that you can read in chapter '6 Users, Groups, And Security Roles' in the document 'Securing Resources Using Roles and Policies for Oracle WebLogic Server' (12.2.1).

The Servicebus Application Specific Roles are described in the paragraph '11.1.3 Roles' within chapter '11.1 Understanding Oracle Service Bus Application Security' of the document 'Administering Oracle Service Bus'. How to add those to weblogic users and groups is quite clearly described in paragraph '19.1.3.3 Adding a Product-Specific Administration Role to the Enterprise Deployment Administration Group' of the 'Enterprise Deployment Guide for Oracle SOA Suite' (12.2.1), so I'm not going to copy that.

In the following script first administrator-users are created and added to the administrators group.
For every user group that is created (Administrators, OSB Developers  and OSB Testers), the property file (example is provided later) contains three comma seperated lists for the usernames, passwors and the user descriptions. So you can provide as many as you want, provided that the order in the passwords and description lists match the order in the user list. Of course if you have many users, you should consider implementing an LDAP Directory with WebLogic.
For each list of users the script loops over the list and fetches based on an incremented idx-variable the accompanying password and description. It creates the user and adds it as a member to the particular group.

After the administrator-users, the OSB Developers group is created, and for the Dev environment it is added to the WebLogic groups Operators and Deployers. It is done in a loop, based on a list of WebLogic groups this group should be a member of. In EM the group is added to the OSB Application Specific role 'Developer'. I haven't searched for a wls example to do that, but it is a environment specific small activity so I kept that manual.
After the OSB Developers group, the OSB Developer users are created.

Lastly in the same way the OSB Tester group and users are created. The Tester group is only added to the Weblogic Monitors group, and in EM added to the OSB Application Specific role 'Tester'.

So here's the createUsers.py script:
#############################################################################
# Create WebLogic Users and groups
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.1, 2016-07-06
#
#############################################################################
# Modify these values as necessary
import sys, traceback
scriptName = sys.argv[0]
#
#
lineSeperator='__________________________________________________________________________________'
#
#
def usage():
  print 'Call script as: '
  print 'Windows: wlst.cmd '+scriptName+' -loadProperties localhost.properties'
  print 'Linux: wlst.sh '+scriptName+' -loadProperties environment.properties'
  print 'Property file should contain the following properties: '
  print "adminUrl=localhost:7001"
  print "adminUser=weblogic"
  print "adminPwd=welcome1"
#
#
def connectToadminServer(adminUrl, adminServerName):
  try:
    print(lineSeperator)
    print('Try to connect to the AdminServer')
    try:
      connect(userConfigFile=usrCfgFile, userKeyFile=usrKeyFile, url=adminUrl)
    except NameError, e:
      print('Apparently user config properties usrCfgFile and usrKeyFile not set.')
      print('Try to connect to the AdminServer adminUser and adminPwd properties')
      connect(adminUser, adminPwd, adminUrl)
  except WLSTException:
    message='Apparently AdminServer not Started!'
    print (message)
    raise Exception(message)
#
#
def getRealm(name=None):
  cd('/')
  if name == None:
    realm = cmo.getSecurityConfiguration().getDefaultRealm()
  else:
    realm = cmo.getSecurityConfiguration().lookupRealm(name)
  return realm
#
#
def getAuthenticator(realm, name=None):
  if name == None:
    authenticator = realm.lookupAuthenticationProvider('DefaultAuthenticator')
  else:
    authenticator = realm.lookupAuthenticationProvider(name)
  return authenticator  
#
#
def createUser(authenticator, userName, password, description):
  print ("Creating user " + userName)
  if authenticator.userExists(userName):
    print ("User "+userName+" already exists.")
  else:
    print ("User "+userName+" does not exist.")
    authenticator.createUser(userName, password, description)
    print("User "+userName+" created with password "+password+".")
#
#
def createGroup(authenticator, groupName, description):
  print ("Creating group " + groupName)
  if authenticator.groupExists(groupName):
    print ("Group "+groupName+" already exists.")
  else:
    print ("Group "+groupName+" does not exist.")
    authenticator.createGroup(groupName, description)
    print("Group "+groupName+" created.")
#
#
def addMember2Group(authenticator, groupName, memberName):
  print ("Adding member "+memberName+" to group " + groupName)
  if authenticator.isMember(groupName,memberName,true) == 0:
    print ("Member "+memberName+" not yet member of the group "+groupName+".")
    authenticator.addMemberToGroup(groupName, memberName)
    print ("Member "+memberName+" added to the group "+groupName+".")
  else:
    print ("Member "+memberName+" already member of the group "+groupName+".")
#
#
def main():
  try:
    print (lineSeperator)
    print ('Start Osb Cluster')
    print (lineSeperator)
    print('\nConnect to AdminServer ')
    connectToadminServer(adminUrl, adminServerName)
    #
    #Create Users
    # Get Realm and Authenticator
    realm = getRealm()
    authenticator = getAuthenticator(realm)
    # Administrators
    print('\nCreate Administrator users')
    administratorList=administrators.split(',')
    administratorDescrList=administratorsDesc.split(',')
    administratorPasswordList=administratorPasswords.split(',')
    #
    idx=0
    for administrator in administratorList:
      administratorDesc=administratorDescrList[idx]
      administratorPassword=administratorPasswordList[idx]
      print(str(idx)+': Process administrator user '+administrator+' with description '+administratorDesc)
      createUser(authenticator, administrator, administratorPassword, administratorDesc)
      addMember2Group(authenticator, 'administrators', administrator)
      idx=idx+1
    #
    # OSB Developers
    print('\nCreate group '+grpOsbDevName)
    createGroup(authenticator, grpOsbDevName, grpOsbDevDesc)
    grpOsbDevWlsGrpList=grpOsbDevWlsGrps.split(',')
    idx=0
    for wlsGroup in grpOsbDevWlsGrpList:
      print(str(idx)+': Add '+grpOsbDevName+' to '+wlsGroup)
      addMember2Group(authenticator, wlsGroup, grpOsbDevName)
      idx=idx+1      
    #
    osbDeveloperList=osbDevelopers.split(',')
    osbDeveloperDescrList=osbDeveloperDescriptions.split(',')
    osbDeveloperPasswordList=osbDeveloperPasswords.split(',')
    #
    print('Create OSB Developer users')
    idx=0
    for osbDeveloper in osbDeveloperList:
      osbDeveloperDesc=osbDeveloperDescrList[idx]
      osbDeveloperPassword=osbDeveloperPasswordList[idx]
      print(str(idx)+': Process OSB Developer user '+osbDeveloper+' with description '+osbDeveloperDesc)
      createUser(authenticator, osbDeveloper, osbDeveloperPassword, osbDeveloperDesc)
      addMember2Group(authenticator, grpOsbDevName, osbDeveloper)
      idx=idx+1
    #
    # OSB Testers
    print('\nCreate group '+grpOsbTestName)
    createGroup(authenticator, grpOsbTestName, grpOsbTestDesc)
    grpOsbTestWlsGrpList=grpOsbTestWlsGrps.split(',')
    idx=0
    for wlsGroup in grpOsbTestWlsGrpList:
      print(str(idx)+': Add '+grpOsbTestName+' to '+wlsGroup)
      addMember2Group(authenticator, wlsGroup, grpOsbTestName)
      idx=idx+1
    #
    osbTesterList=osbTesters.split(',')
    osbTesterDescrList=osbTesterDescriptions.split(',')
    osbTesterPasswordList=osbTesterPasswords.split(',')
    #
    print('Create OSB Tester users')
    idx=0
    for osbTester in osbTesterList:
      osbTesterDesc=osbTesterDescrList[idx]
      osbTesterPassword=osbTesterPasswordList[idx]
      print(str(idx)+': Process OSB Tester user '+osbTester+' with description '+osbTesterDesc)
      createUser(authenticator, osbTester, osbTesterPassword, osbTesterDesc)
      addMember2Group(authenticator, grpOsbTestName, osbTester)
      idx=idx+1
    #
    print('\nExiting...')
    exit()
  except NameError, e:
    print('Apparently properties not set.')
    print "Please check the property: ", sys.exc_info()[0], sys.exc_info()[1]
    usage()
  except:
    apply(traceback.print_exception, sys.exc_info())
    exit(exitcode=1)
#call main()
main()
exit()

And here an example of the property file:
#############################################################################
# Properties for Creating WLS Users
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.0, 2016-07-06
#
#############################################################################
#
# Properties for AdminServer
adminServerName=Adminserver
adminUrl=lxoosb301:7001
# AdminUser
adminUser=weblogic
adminPwd=wlsadmin_O3
#
defaultPassword=welkom123
#
grpOsbDevName=OSBDevelopers
grpOsbDevDesc=OSB Developers
grpOsbDevWlsGrps=Deployers,Operators
#
osbDevelopers=sjaak,maarten
osbDeveloperDescriptions=Sjaak with a Lastname - OSB Developer,Maarten from another father - OSB Developer
osbDeveloperPasswords=sjaak123,maarten456
#
grpOsbTestName=OSBTesters
grpOsbTestDesc=OSB Testers
grpOsbTestWlsGrps=Monitors
#
osbTesters=wim
osbTesterDescriptions=Wim You know - OSBTester
osbTesterPasswords=wimrt789
#
administrators=hans,martien
administratorsDesc=Hans the Admin,Martien van den Akker (extern)
administratorPasswords=hans123,martien456

As you can see the descriptions may have spaces and dashes and other characters in it. But certainly no comma's (','), since that breaks the list. Often the description is used to provide a full name.
Also it contains a references to the admin server and the admin username/passsword. So you need to adapt this part of the property file for each environment.
In a later past I'll show how to create user key files to use encrypted administrator passwords. So after creating the users, remove this file from your system.
To start it you can use the following shell script, or get the running wlst command from:
#!/bin/bash
#############################################################################
# Create users
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 2.1, 2016-07-06
#
#############################################################################
#  
. fmw12c_env.sh
echo
echo Create Users
wlst.sh ./createUsers.py -loadProperties fmw.properties

Rename the fmw.properties reference to the file you named the property file created based on the property file example above.

That (as my other scripts) needs a fmw12c_env.sh script like:
#!/bin/bash
echo set Fusion MiddleWare 12cR2 environment
export FMW_HOME=/ontw/u01/app/oracle/product/fmw12c2
#
echo call setWLSEnv.sh
. $FMW_HOME/wlserver/server/bin/setWLSEnv.sh
export PATH=$FMW_HOME/oracle_common/common/bin:$WL_HOME/common/bin/:$WL_HOME/server/bin:$PATH


Wednesday, 6 July 2016

OSB 12c Logging part 2

Two weeks ago, I wrote about how to set the log level voor SB Pipelines (12c) to be able to see the logging of the Log activity in the WebLogic Server logs.

Today I encountered that for a developer at my customer the complete oracle.osb.logging.pipeline logger was missing in the log-configuration. So setting the level from EM (Fusion Middleware Control) following the article above is a little hard.

I could not find why in that case the logger was missing. But I did find a simple solution.
In the paragraph '7.1.4 ODL Log Configuration' of the Administering Oracle Service Bus documentation, I found that  you can change the logging via the EM, wlst and the logging.xml file. This file can be found in ${osb.domain.home}/config/fmwconfig/servers/${osbserver.name}, eg. 'c:\Data\JDeveloper\SOA\system12.2.1.0.42.151011.0031\DefaultDomain\config\fmwconfig\servers\DefaultServer\'.

Go to the end of the file:
   ...
  <logger name='com.sun.xml.ws' level='WARNING' useParentHandlers='true'/>
 </loggers>
</logging_configuration>

Copy the last logger and rename it to create an entry for the oracle.osb.logging.pipeline logger:
   ...
  <logger name='com.sun.xml.ws' level='WARNING' useParentHandlers='true'/>
  <logger name='oracle.osb.logging.pipeline' level='TRACE:16' />
 </loggers>
</logging_configuration>

Set the level and remove the useParentHandlers attribute.
Restart your server and then you should find the option in the EM OSB Log Configuration. If you have multiple OSB servers you'd probably need to update this change for every osb server, since the logging.xml resides in a server specific sub-folder. I haven't tried it to add it for one server and change it to see if it is automatically added to the other server. Would be a nice experiment.

Monday, 4 July 2016

SOA Server (12c) not startable from script-created domain.

If you're a regular reader of this blog, you've noticed that I've been busy with creating soasuite/osb installations with weblogic domains in a scripted way.

I also optimized my start and stop scripts, that I'll post soon. All this work keeps me from writing on my BPEL book, so for those who are interested in my next episode, I hope you're patient.

But to get to that, it would be nice to have a running SOA Server in my automatically created domain. And unfortunately, that doesn't get up in running mode. Somewhere in the process it fails to start services and switches over to ADMIN mode.

I did some investigation and ran in to the following exception in the server log:

####<Jul 4, 2016 3:30:49 AM EDT> <Error> <Deployer> <darlin-vce-db.darwin-it.local> <SoaServer1> <[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <f2c434e6-7b67-4a8c-9e2f-8b886152cced-0000000a> <1467617449212> <[severity-value: 8] [rid: 0] [partition-id: 0] [partition-name: DOMAIN] > <BEA-149205> <Failed to initialize the application "OracleBPMBACServerApp" due to error weblogic.management.DeploymentException: Could not find OSGi framework with name bac-svnserver-osgi-framework
weblogic.management.DeploymentException: Could not find OSGi framework with name bac-svnserver-osgi-framework
 at weblogic.osgi.internal.OSGiAppDeploymentExtension.deployBundlesIntoFramework(OSGiAppDeploymentExtension.java:126)
 at weblogic.osgi.internal.OSGiAppDeploymentExtension.prepare(OSGiAppDeploymentExtension.java:245)
 at weblogic.application.internal.flow.AppDeploymentExtensionFlow.prepare(AppDeploymentExtensionFlow.java:25)
 at weblogic.application.internal.BaseDeployment$1.next(BaseDeployment.java:730)
 at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45)
 at weblogic.application.internal.BaseDeployment.prepare(BaseDeployment.java:242)
 at weblogic.application.internal.EarDeployment.prepare(EarDeployment.java:67)
...

Apparently there was a problem with the OSGi Framework with the name 'bac-svnserver-osgi-framework' that couldn't be found.

OSGi in a domain with both OSB and BPM was a problem in 12cR1. Several blogs are written about that (like this and this one). However, the problem in those blogs is solved soon after the release of 12cR1. In my case something different is happening.

I took a look and it turns out that the 'bac-svnserver-osgi-framework' was not targetted to the SOAServer, although it was targetted to the AdminServer. To check that, navigate to Services->OSGi Frameworks in the Domain Structure:

Here you see the result of my retargetting. If it does not show the SoaCluster or SOA Server, then click on 'bac-svnserver-osgi-framework' and click on the Targets  tab:

At least check the SoaCluster or, if no cluster the SoaServer1. I unchecked the AdminServer because in the earlier posts unchecking the AdminServer was one proposed solution to resolve the OSB-BPM SharedDomain URL issue. But I'm not sure it's needed.

Click Save and activate the changes and, in my case at least, the SoaServer should be startable.


Friday, 1 July 2016

Rename your Weblogic 12c AdminServer

At one of my customers we create Service Bus Weblogic Domains using a script, driven by a property file. But in one of the environments we encountered that the AdminServer was accidently called 'Adminserver', with a lower-case 's'. Now this is a very minor issue, but the administrator would like to have it fixed, since it is an anomaly regarding with other environments.

This week I got to implement my start-stop scripts (which I will publish later) and so bumbed into this naming fault again.

Renaming it turns out to be walk in the park. So let me show you how I did it. Most of the steps could easily be done in a WLST script, but I trust this is not something you would do on a regular basis, so we do it just in off-line commandline mode.

Before doing anything from the steps below, first shutdown the complete domain, all the weblogic servers, including the AdminServer. And I should advice: backup your domain. This can easily be done by zipping the domain folder.

Then set the fmw environment, that is most conveniently done using a script. The one I always create on a new environment is fmw12c_env.sh:

#!/bin/bash
echo set Fusion MiddleWare 12cR2 environment
export FMW_HOME=/u01/app/oracle/fmw12c2

export SOA_HOME=$FMW_HOME/soa
export OSB_HOME=$FMW_HOME/osb
export MFT_HOME=$FMW_HOME/mft
#
echo call setWLSEnv.sh
. $FMW_HOME/wlserver/server/bin/setWLSEnv.sh
export PATH=$FMW_HOME/oracle_common/common/bin:$WL_HOME/common/bin/:$WL_HOME/server/bin:$PATH

Under Linux you should run this as:
$ . ./fm12c_env.sh

It is important to add the dot in front of the command, to have the settings exported to the calling session. I trust that if you're on windows, you'd be able to create a .bat/.cmd file out of this.

The script put's wlst.sh/.cmd in the path. Start it, which brings you to a prompt like:
wls:/offline> 

In the offline mode, read the domain first with:
wls:/offline> readDomain('/u01/app/work/domains/osb_domain')
Where '/u01/app/work/domains/osb_domain' is the path to the domain.
Navigate to the Servers node:
wls:/offline/osbo3_domain>cd ('/Servers')
wls:/offline/osbo3_domain/Server>ls()
drw-   Adminserver
drw-   osb_server1
Then navigate to the Adminserver (you could have done that immediately, but you might want to check on your servers first):
wls:/offline/osbo3_domain/Server>cd ('Adminserver')

For the wlst novice: you might have discovered by now that we navigate through (cd()) and introspect (ls())the MBean-hierarchy using filesystem-related commands. The current folder is actually the current MBean at hand, also called the 'Current Managed Object', in short 'cmo'.
So now we're at it, change its name, for instance:
wls:/offline/osbo3_domain/Server/Adminserver>cmo.setName('AdminServer')
To have this change effect you need to write/save/update the domain:
wls:/offline/osbo3_domain/Server/Adminserver>updateDomain()

After that you can quit wlst using the 'exit()' command.

There is still one little issue to solve, before being able to start the AdminServer and the rest of the domain.

In most cases the nodemanager uses the startWebLogic.sh command to start the domain. This one calls the setDomainEnv.sh/.cmd script.

When no Servername is provided as the start parameter, the AdminServer is assumed to be started.
This is evaluated in the setDomainEnv.sh/.cmd in the following lines:
if [ "${SERVER_NAME}" = "" ] ; then
        SERVER_NAME="Adminserver"
        export SERVER_NAME
fi

So edit the file, locate the lines and change the line 'SERVER_NAME="Adminserver"' to 'SERVER_NAME="AdminServer"' (or the name you used in change the server to).

In this same file, setDomainEnv.sh/.cmd, you might want to disable the start of the Derby Java Database server.
Locate the lines
# Set DERBY_FLAG, if derby is available.

if [ "${DERBY_FLAG}" = "" ] ; then
        if [ -f ${WL_HOME}/common/derby/lib/derby.jar ] ; then
                DERBY_FLAG="true"
                export DERBY_FLAG
        fi
fi
And add the following lines just before the 'if':
DERBY_FLAG="false"
export DERBY_FLAG

To be able to start the renamed AdminServer you also might want to move the folder named 'security' from the ${DomainHome}/servers/Adminserver folder (the server folder with the previous name) to the corresponding folder with a new name. This allows the renamed server to reuse the boot.properties file. And remove the old folder, or rename the server folder to the new name.

This concludes the renaming-steps. Now you're good to go to startup the domain again.


Friday, 24 June 2016

A couple of notes of the automatic generation of a SOA Suite/OSB domain

Earlier you could have enjoyed my article on the automatic generation of a SOA/OSB domain. Earlier this week I encountered some issues with a domain created at a customer this way.

I got the change to dive into that this week and luckily not only I learned a lot again, but I found the problem as well. I adapted my scripts. I won't repost them completely, I've created a github account, and try to place them there in the near future.

But I'll cover the changes, especially those that caused the problems.

Enrollment


When you create a domain using the config.sh/.cmd wizard, and choose to configure the nodemanager, you'll be asked for the nodemanager user and password. You'll get a per domain nodemanager for free and the domain is enrolled for the nodemanager for you. You might need to adapt the nodemanager.properties in <domain_home>/nodemanager and set the property SecureListener to false. The default is true, while in the Machine definition in the domain the nodemanager/machine is configured to SSL. If you disable the SecureListener, you need to set the property in the wls-console under Machines to Plain instead of SSL. And adapt the listener-port.

The docs on configuring the nodemanager for 12.2.1 can be found here. One of the biggest changes between 11g and 12cR1 is that in 12cR2 you get a per domain nodemanager, with a nodemanager home in the domain home, instead of a nodemanager home in the FMW_HOME, the home of the binaries. Also in the bin folder of the domain you'll find scripts to start and stop the nodemanager.

So for a domain configured in the config-wizard, you need little to do to get the nodemanager working.

But using the scripts in my previous article, you'll find that although a nodemanager password file is created, something is missed for a proper startup of your servers using the nodemanager. You'll find that although the nodemanager starts, connecting to it using nmConnect(), fails with: a message like:
WLSTException: Error occured while performing nmConnect : Cannot connect to Node Manager. : Access to domain 'osb_domain' for user 'weblogic' denied.

You can go to the Domain->security settings in the weblogic console, and change the nodemanager password, but apparently this is not enough. You'll need to explicitly enroll the domain against the nodemanager. To do so:
  • Start the AdminServer, using the startWebLogic.sh/.cmd script in the domain home.
  • Start wlst.sh/.cmd
  • Connect to the AdminServer using:  connect(adminUser, adminPwd, adminURL)
  • Perform an NodeManager Enroll using: nmEnroll(soaDomainHome, nodeManagerHome)
  •  Stop the AdminServer
  • (Re)Start the nodemanager
  • In wlst: Connect to the nodemanager using nmConnect(....)
  • Perform nmStart('AdminServer')
The following enrollDomain.py script might help:
#############################################################################
# Create a SOA/BPM/OSB domain
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.1, 2016-06-23
#
#############################################################################
# Modify these values as necessary
import sys, traceback
scriptName = 'enrollDomain.py'
#
#Home Folders
soaDomainHome   = domainsHome+'/'+soaDomainName
nodeManagerHome = soaDomainHome+'/'+'nodemanager'
#
#
lineSeperator='__________________________________________________________________________________'
#
#
def usage():
  print 'Call script as: '
  print 'Windows: wlst.cmd '+scriptName+' -loadProperties localhost.properties'
  print 'Linux: wlst.sh '+scriptName+' -loadProperties environment.properties'
  print 'Property file should contain the following properties: '
  print "adminUrl=localhost:7101"
  print "adminUser=weblogic"
  print "adminPwd=welcome1"
#
#
def main():
  try:
    #
    # Section 1: Base Domain + Admin Server
    print (lineSeperator)
    print ('Enroll '+soaDomainName+' for NodeManager')
    print('\nConnect to AdminServer ')
    print (lineSeperator)
    adminURL=adminListenAddress+':'+adminListenPort
    connect(adminUser, adminPwd, adminURL)
    #
    print('\nPerform nmEnroll')
    print (lineSeperator)
    #
    nmEnroll(soaDomainHome, nodeManagerHome)
    #
    print ('\nFinished')
    #
    print('\nExiting...')
    exit()
  except NameError, e:
    print 'Apparently properties not set.'
    print "Please check the property: ", sys.exc_info()[0], sys.exc_info()[1]
    usage()
  except:
    apply(traceback.print_exception, sys.exc_info())
    stopEdit('y')
    exit(exitcode=1)
#call main()
main()
exit()

It can be called with a shell script (enrollDomain.sh) like:
#!/bin/bash
. fmw12c_env.sh
echo
echo Enroll domain
wlst.sh enrollDomain.py -loadProperties darlin-vce-db-osb.properties

I also adapted the function 'createUnixMachine' in the createSoaBpmDomain.py script:
#
# Create a Unix Machine
def createUnixMachine(serverMachine,serverAddress, serverPort, nmType):
  print('\nCreate machine '+serverMachine+' with type UnixMachine')
  print (lineSeperator)
  cd('/')
  create(serverMachine,'UnixMachine')
  cd('UnixMachine/'+serverMachine)
  create(serverMachine,'NodeManager')
  cd('NodeManager/'+serverMachine)
  set('ListenAddress',serverAddress)
  set('ListenPort',int(serverPort))
  set('NMType',nmType)
This allows for the non-default setting of the nodemanager to another listen port and nodemanager type, based on the following properties in the property file:
#
# Server Settings
nmType=Plain
server1Machine=darlin-vce-db
server1Address=darlin-vce-db
server1Port=5555
server2Enabled=false
server2Machine=darlin-vce-db
server2Address=darlin-vce-db2
server2Port=5555
An example of the property file can be found in the earlier article: automatic generation of a SOA/OSB domain.

Logging

In the example property file in my scripts you can set a location for the logging:
# Logs
logsHome=/u01/app/work/logs

If this is a absolute path, 'nothing is on the hand'. Your domain should start correclty. But if you choose to use a relative path, like 'logs', then starting the AdminServer might succeed (in my case) but starting the managed servers fail with a 'No such file or directory' message:
wls:/nm/osb_domain> nmStart('Adminserver')
 
Starting server Adminserver ...
 
Traceback (innermost last):
 
  File "<console", line 1, in ?
 
  File "<iostream", line 188, in nmStart
 
  File "<iostream>", line 553, in raiseWLSTException
 
WLSTException: Error occurred while performing nmStart : Error Starting server Adminserver : Received error message from Node Manager Server: [Server start command for WebLogic server 'Adminserver' failed due to: [No such file or directory]. Please check Node Manager log and/or server 'Adminserver' log for detailed information.]. Please check Node Manager log for details.
 
Use dumpStack() to view the full stacktrace :
 
wls:/nm/osb_domain

Now it turns out that this is caused by the JavaArgs that are generated and set in the script. I found that if you set JavaArgs you need to set redirects for weblogic.Stdout and weblogic.Stderr, like:
'-XX:PermSize=256m -XX:MaxPermSize=512m -Xms1024m -Xmx1532m -Dweblogic.Stdout='+logsHome+'AdminServer.out -Dweblogic.Stderr='+logsHome+'AdminServer_err.out'

Where logFolder should be an absolute path. This has to do with the context in which the nodemanager is starting the server. From that context the relative reference apparently does not evaluate to the proper location.
You can however, leave the Java args empty. So I changed my scripts to not use the getServerJavaArgs function, anymore, but get them from the property file. I replaced the xxxJavaArgsBase  with xxxJavaArgs variables. And left them empty.

The configurator doesn't set the JavaArgs, it leaves them over to the setDomain.sh/.cmd and setStartupEnv.sh/.cmd. If you do so, you can use a relative path, and the servers will start properly.