Friday, 26 August 2016

Mount NTFS disk in Linux 7

Today I wanted to pass an old disk in a usb-case to my son. It was from an old Windows Laptop and even though I'm administrator, I wasn't able to read the documents in an other user's folder.

So I thought, let's do it from an Oracle Linux 7 VM, as root. But it turns out that Oracle linux did not support NTFS by default.

But with the trick in this link I managed to do it.

To sum up, especially for my self:

Add the EPEL-7 repository from Fedora:
# wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

# rpm -ivh epel-release-latest-7.noarch.rpm

This worked for me. Although I had to step over my issue that I add a Fedora repo to Oracle Linux.... An other option could have been (probably if under Redhat Linux or CentOS:
# yum install epel-release
...
# yum clean all
...
# yum update
...

Install the NTFS-3g package:
# yum install ntfs-3g -y

And enable NTFS support for FileManagers:
# yum install ntfsprogs -y

Then I got to the FileManager and I could browse the disk. It was mounted at '/run/media/oracle/803638DB3638D3BE'.

Wednesday, 24 August 2016

Generate Admin Channels to improve Weblogic Admin Console performance (and of FMW-Control)

At one of my customers we have quite an impressive domain configuration. It's a FMW domain with SOA, OSB, BAM, WSM, MFT in clusters of 4 nodes. The thing is that when having started all the servers, the console becomes slooooooowwwww. Not to speak of FMW Control (em).

One suggestion is to set the 'Invocation Timeout Seconds' under MyDomain->Configuration->General->Advanced to a value like 2. And 'Management Operation Timeout' under Preferences->Shared Preferences to a value like 5:

This surely makes the console responsive again. But it actually means that the console gives up right away when querying for the (health) state of the servers. So in stead of a health of 'OK', you get a 'server unreachable' message.

When having a lot of servers in the domain, they all share the same Admin Channel, and this seams to get over flooded. AdminServer does not get the responses in time. Sometimes a new request leads to a proper response, but in fact it takes a lot of time.

To reduce the load on the default channel, we created an admin channel per managed server. Since it's a lot of servers, and we need to do it on several environments, so I created a wlst-script for it.
The script createAdminChannels.py:
#############################################################################
# Create AdminChannels for WebLogic Servers
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.1, 2016-08-24
#
#############################################################################
# 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 createAdminChannel(serverName, adminListenPort):
  print(lineSeperator)
  channelName = serverName+'-AdminChannel'
  try:
    cd('/Servers/'+serverName+'/NetworkAccessPoints/'+channelName)
    print('Channel '+channelName +' for '+serverName+' already exists.')
  except WLSTException: 
    try:
      print('Create Admin Channel for server: '+serverName+', with port: '+adminListenPort)
      cd('/Servers/'+serverName)
      cmo.createNetworkAccessPoint(channelName)
      cd('/Servers/'+serverName+'/NetworkAccessPoints/'+channelName)
      cmo.setProtocol('admin')
      cmo.setListenPort(int(adminListenPort))
      cmo.setEnabled(true)
      cmo.setHttpEnabledForThisProtocol(true)
      cmo.setTunnelingEnabled(false)
      cmo.setOutboundEnabled(false)
      cmo.setTwoWaySSLEnabled(false)
      cmo.setClientCertificateEnforced(false)
      print ('Succesfully created channel: '+channelName)
    except WLSTException:
      apply(traceback.print_exception, sys.exc_info())
      message='Failed to create channel '+channelName+'!'
      print (message)
      raise Exception(message)
#
#
def main():
  try:
    print (lineSeperator)
    print ('Start Osb Cluster')
    print (lineSeperator)
    print('\nConnect to AdminServer ')
    connectToadminServer(adminUrl, adminServerName)
    print(lineSeperator)
    print('Start Edit Session')
    edit()
    startEdit()
    #
    #Create Admin Channels
    # Administrators
    print('\nCreate Admin Channels')
    serverNameList=serverNames.split(',')
    serverAdminPortList=serverAdminPorts.split(',')
    #
    idx=0
    for serverName in serverNameList:
      adminPort=serverAdminPortList[idx]
      createAdminChannel(serverName, adminPort)
      idx=idx+1
    # Activate changes
    print(lineSeperator)
    print('Activate Changes')
    save()
    activate(block='true')
    #
    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()


The shell script to call it, createAdminChannels.sh:
#!/bin/bash
#############################################################################
# Create AdminChannels
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 2.1, 2016-08-24
#
#############################################################################
#  
. fmw12c_env.sh
export PROPERTY_FILE=$1
echo
echo Create Admin Channels
wlst.sh ./createAdminChannels.py -loadProperties $PROPERTY_FILE

And the example property file, darlin-vce-db.properties:
#############################################################################
# Properties voor Creeëren SOADomain
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.0, 2016-04-15
#
#############################################################################
#
# Properties for AdminServer
adminServerName=Adminserver
adminUrl=darlin-vce-db:7001
# AdminUser
adminUser=weblogic
adminPwd=welcome1
#
serverNames=AdminServer,OsbServer1,SoaServer1
serverAdminPorts=7101,8111,8101
#

Call the script as $> createAdminChannels.sh darlin-vce-db.properties

In the property file you'll need to name every server in the property serverNames. And for each server the particular Admin Listen Port in serverAdminPorts, in the exact same order. Start with the AdminServer.


At the end of the script the changes are activated and then the AdminServer listens over https on the changed port.

Important: the servers need to be down, except for the the AdminServer.

Unfortunately the infrastructure database was apparently down. So I haven't been able to start SOA, BAM, etc. to see if it is performant now. But I have high hopes...

Update wlst.sh
When you update the AdminServer as above, it will by default use the DemoTrust keystore. And probably the listenaddress might not necessarily match the url that is used in the connect-URL.

So by default you might run into errors when trying to connect to the AdminServer using wlst.
First you need to adapt the Admin URL to something like 'tls://darlin-vce-db:7101'. Explicitly prefix with 'tls://' and adapt the port to the new admin-listen-port.

Then the wlst script need to be adapted. The following parameters need to be added to the wlst command:
  • -Dweblogic.security.SSL.ignoreHostnameVerification=true
  • -Dweblogic.security.TrustKeyStore=DemoTrust
To do so, find out where the wlst.sh/cmd script is located. Under linux you can perform:
[oracle@darlin-vce-db bin]$ which wlst.sh
/u01/app/oracle/FMW12210/oracle_common/common/bin/wlst.sh

Of course after setting the weblogic environment (see one of my earlier blogs describing the fmw12c_env.sh script).

Edit the wlst.sh file and go to the bottom of the file, and add the properties to the JVM_ARGS variable:
...
JVM_ARGS="${WLST_PROPERTIES} ${JVM_D64} ${UTILS_MEM_ARGS} ${CONFIG_JVM_ARGS} -Dweblogic.security.SSL.ignoreHostnameVerification=true -Dweblogic.security.TrustKeyStore=DemoTrust"
if [ -d "${JAVA_HOME}" ]; then
 eval '"${JAVA_HOME}/bin/java"' ${JVM_ARGS} weblogic.WLST '"$@"'
else
 exit 1
fi
But setting the CONFIG_JVM_ARGS in a script like fmw12c_env.sh might be a better idea:
...
export CONFIG_JVM_ARGS=-Dweblogic.security.SSL.ignoreHostnameVerification=true -Dweblogic.security.TrustKeyStore=DemoTrust
...



Unable to login with a SQL Authenticator

For a project, we are migrating Forms to ADF.
There is also a number of reports which are not to be migrated yet.
Therefore, we need to keep the users in the database.
As we do not want to maintain two user stores, we thought it to be a good idea to create an authenticator in WebLogic to authenticate to the database.
There are loads of blog posts / support notes on how to configure a SQL Authenticator, so I won't repeat this procedure.
Take a look at Oracle Support Document 1342157.1 or a post from Edwin Biemond


However, we noticed a flaw in these (old) references.


In WebLogic 12c, when we create a SQL Authenticaotr, there is a filed named Identity Domain.
From the Oracle documentation, we learn:
All Authentication providers included in WebLogic Server support identity domains. If the identity domain attribute is set on an Authentication provider, that Authentication provider can authenticate only users who are defined in that identity domain.
...
An identity domain is a logical namespace for users and groups, typically representing a discrete set of users and groups in the physical datastore. Identity domains are used to identify the users associated with particular partitions.


As we do not use partitions in our domain, there is no use for an Identity domain.
But we did not know that when we setup the authenticator (and who reads the entire manual right??)


So following the previously mentioned resources, we created the SQL authenticator and entered the domain name in the Identity Domain field.
This resulted in a not working authenticator.
Symptoms:
  • When a user tried to login using database credentials, the autentication faild Always
  • No error message in the log
  • No activity in the datase (no query was executed to check the credentials)
To further analyse the issue, we added som Java options to the Admin server, using the setDomainEnv script:
JAVA_OPTIONS="${JAVA_OPTIONS} -Dweblogic.kernel.debug=true -Dweblogic.log.StdoutSeverity=Debug -Dweblogic.log.LogSeverity=Debug -Dweblogic.StdoutDebugEnabled=true -Dweblogic.log.LoggerSeverity=Debug -Dweblogic.debug.DebugSecurityAtn=true" 
 export JAVA_OPTIONS 

This gave us more insight in the issue. The log file now revealled:
####<23-aug-2016 15:13:02 uur CEST> <Debug> <SecurityAtn> <BSCC6112> <DefaultServer> <[ACTIVE] ExecuteThread: '5' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <d489addb-c960-41f1-babb-f912aec329bc-00000036> <1471957982959> <[severity-value: 128] [rid: 0] [partition-id: 0] [partition-name: DOMAIN] > <BEA-000000> <weblogic.security.providers.authentication.shared.DBMSAtnLoginModuleImpl.login exception: 
java.security.PrivilegedActionException: javax.security.auth.login.LoginException: javax.security.auth.callback.UnsupportedCallbackException: Unrecognized Callback: class weblogic.security.auth.callback.IdentityDomainUserCallback 
weblogic.security.auth.callback.IdentityDomainUserCallback@31789514
 at java.security.AccessController.doPrivileged(Native Method)
 at com.bea.common.security.internal.service.LoginModuleWrapper.login(LoginModuleWrapper.java:114)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:497)
 at javax.security.auth.login.LoginContext.invoke(LoginContext.java:755)
...


Unfortunately, we still had no clue.
As you have read from the beginning of the post, you might think that setting the Identity Domain field to DOMAIN might solve the issue (the log states partition-name: DOMAIN) but no, that's no solution either.

The trick is to leave the Identity Domain filed blank. After that the authenticator worked like a charm.

Thursday, 14 July 2016

Set connection retry frequency on DataSource in WebLogic 12c.

I have encountered several times in WebLogic 12c that when the ConnectionPool of a DataSource in WebLogic could not be initialized because due to a connection error or invalid username or password, the server could not be started.

I can't remember having encounterd this problem in 11g, and this week I struggled with it with one of my customers. The perception of the DBA there was that in 11g the server did start up, but the DataSource would go in Suspended-state. Half a year ago, one of the admins just removed a datasource because it made the 12c WebLogic server unstartable. "Taking a short turn", we would say in Dutch.

Now, having a database that is down is a reality at my customers. At least in development and test environments. Also at some of my customers it is a reality to have databases refreshed with an earlier clone. Causing for instance database passwords becoming invalid. It's quite inconvenient not being able to start the servers. Especially when the AdminServer can't be started because of it. And with SOASuite and OSB this is a reality since some of the consoles and composers are targeted to the AdminServer.

This week I found there were 2 options to get the server started:
  • Temporarily untarget the datasource
  • Set the initial and minimum connections to 0. 
The first was acceptable for one of my customers because they have just one cluster to which the problematic datasources was targeted to. Untargeting would leave all the other settings. And retargetting doesn't raise questions because there's only one target option.

But in a complex domain with several clusters it might not be too obvious to which cluster(s) or server(s) the datasource should be retargeted.

Changing the initial/minimum connections is not ideal either. Because you need to remember what the preferred settings were. These are important when using them for web applications or services used by web applications where performance is key.

But today I stumbled upon a third option: 'Connection Creation Retry Frequency' which can be found under DataSource -> Configuration -> Connection Pool -> Advanced:

Set this to 300 to have a retry every 5 minutes. It is described as:
The number of seconds between attempts to establish connections to the database.

If you do not set this value, data source creation fails if the database is unavailable. If set and if the database is unavailable when the data source is created, WebLogic Server will attempt to create connections in the pool again after the number of seconds you specify, and will continue to attempt to create the connections until it succeeds.

When set to 0, connection retry is disabled.'

Learning all the time...



Start and stop a WebLogic (SOA/OSB) Domain

So let's start the day with a blog. In the past few months I created scripts to install FMW products and build a WebLogic domain for it. For most of my findings I did a blog already:
And then I did not list the blogs about the scripts to setup and patch the QuickStarts. Nice  to mention is that this week 12.2.1.1 is released. So I can adapt my scripts with the new software (I'm not going to post that, you should be able to figure that out yourself, maybe I'll provide the changed snippets when I come to it).

But the important missing part in this series are the start and stop of the domain. So let me provide and describe my scripts.

Oracle does provide scripts to start and stop your NodeManager and WebLogic servers. When you configure the NodeManager and Servers correctly you can use those to add the NodeManager to the init.d services on Linux or to your Windows Services. Then the NodeManager would start the AdminServer and other Servers automatically.

However, on my demo/training/development systems I'd like to be able to start/stop the parts myself.  So here we go.

Settings

I'm working with Linux and create shell scripts to kick-off the wlst scripts that I use to start the particular components. Therefor I use a settings script called fmw12c_env.sh to call the setWLSEnv.sh from the FMW home. I take it that you're able to translate them to Windows Command file if applicable. I provided it a couple of time already. But for completeness here it is:
#!/bin/bash
echo set Fusion MiddleWare 12cR2 environment
export FMW_HOME=/u01/app/oracle/FMW12210
export NODEMGR_HOME=/u01/app/work/domains/osb_domain/nodemanager

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

Then the wlst scrips need a property file fmw.properties:
#############################################################################
# Set SOABPM Domain properties
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.0, 2016-06-27
#
#############################################################################
#
#Per domain nodemanager...
#############################################################################
# Set SOABPM Domain properties
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.0, 2016-06-27
#
#############################################################################
#
#Per domain nodemanager...
#nmHome=/u01/app/work/domains/osb_domain/nodemanager
nmHome=/u01/app/work/domains/soabpm_domain/nodemanager
#nmHome=/u01/app/work/domains/soabpm12c_dev/nodemanager
nmHost=darlin-vce-db
nmPort=5555
nmType=plain
#
#Domain
#wlsDomainName=osb_domain
#wlsDomainName=soabpm12c_dev
wlsDomainName=soabpm_domain
wlsDomainsHome=/u01/app/work/domains
#
#AdminServer
adminServerName=AdminServer
#adminServerName=OsbAdmin
adminUrl=darlin-vce-db:7001
adminUser=weblogic
adminPwd=welcome1
usrCfgFile=wlsCfgFile
usrKeyFile=wlsKeyFile
#Clusters
osbClr=OsbCluster
soaClr=SoaCluster

Create User Config and Key files

In the property file above you'll see the adminUser and adminPwd (password). On a production environment you probably don't want to have those in plain sight. WebLogic provides a means to encrypt those in to a user config and a key file. When you generate those with the default names to your home folder you even can connect to the AdminServer without providing the username/password. In my scripts I use named files as defined in the usrCfgFile and usrKeyFile properties. But first we need to generate those and for that we need to connect to the AdminServer using the adminUser and adminPwd properties.

I created the script createUserConfigFiles.py to generate those files:
#############################################################################
# Stop AdminServer 
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 2.1, 2016-06-27
#
#############################################################################
# Modify these values as necessary
import sys, traceback
scriptName = 'stopAdmin.py'
#
#
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:
    print(lineSeperator)
    print('Create user config files')
    print(lineSeperator)
    print('\nConnect to the AdminServer: '+adminServerName)
    connect(adminUser, adminPwd, adminUrl)
    #
    print('\nStore Config files')
    storeUserConfig(usrCfgFile,usrKeyFile)
    #   
    print('\nExiting...')
  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)
#
main();

After connecting to the AdminServer it is the storeUserConfig(usrCfgFile,usrKeyFile) that creates the files. If you don't supply the parameters it will create the default files in your home folder (for instance /home/oracle), then you can connect just by issueing connect('localhost:7001'). For more on this, read this blog.

To call the script above you can use the script createUserConfigFiles.sh or the contents of it:
#!/bin/bash
#############################################################################
# Create user config files using wlst.sh
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 2.1, 2016-06-27
#
#############################################################################
#  
. fmw12c_env.sh
echo
echo Create User Config files
wlst.sh ./createUserConfigFiles.py -loadProperties fmw.properties

After having greated the files you can (and should!) remove the adminUser and adminPwd properties from the fmw.properties file.

Start the NodeManager

 In de domain home/bin folder (for instance /u01/app/work/domains/soabpm_domain/bin) you'll find scripts to start and stop the NodeManager: startNodeManager.sh and stopNodeManager.sh. These are fine to use in the service configurations in Linux or Windows.

However, running them from the shell/command line will cause your session to be taken for the NodeManager. Stopping the session will cause the NodeManager to be stopped. Not so handy if you want to start the NodeManager in an overall script that starts the complete domain.

But you can start the NodeManager from wlst as well. And then it spawns the NodeManager into a seperate process in  the background.
The script startNodeManager.py is quite simple:
#############################################################################
# Start nodemanager
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 2.1, 2016-06-27
#
#############################################################################
# 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:7101"
  print "adminUser=weblogic"
  print "adminPwd=welcome1"
# 
# 
def startNM(nmHost, nmPort, nmHome, nmType):
  print(lineSeperator)
  print ('Start NodeManager')
  startNodeManager(verbose='true', NodeManagerHome=nmHome, ListenPort=nmPort, ListenAddress=nmHost);
  print('Finished starting NodeManager')
#
def main():
  try:
    startNM(nmHost, nmPort, nmHome,  nmType);
  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)
#
main()

It's mainly about the startNodeManager(verbose='true', NodeManagerHome=nmHome, ListenPort=nmPort, ListenAddress=nmHost) statement in the  startNM() function, which is quite self explaining, I think.  No username password is required to start the NodeManager, but it does need to know what it's home and listenPort and Address should be.

As with all the scripts I  declare a scripName variable with the assignment of the 0-th argument: sys.argv[0]. This is used in the usage() function that is called in case of a NameError exception. This exception is raised when certain variable or function references are made but not found. Normally this would mean that a certain property is not set in the property file.

To run it from the shell you can use the startNodeManager.sh script:

#!/bin/bash
#############################################################################
# Start nodemanager using wlst
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 2.1, 2016-06-27
#
#############################################################################
#  
. fmw12c_env.sh
echo
echo Start NodeManager
wlst.sh ./startNodeManager.py -loadProperties fmw.properties
For every python script in the procession of this blog I have an accompanying shell script like this. So I won't provide those for the other scripts.

Stopping the NodeManager is a little more complicated:
#############################################################################
# Stop nodemanager
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 2.1, 2016-06-27
#
#############################################################################
# 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:7101"
  print "adminUser=weblogic"
  print "adminPwd=welcome1"
# 
#
def connectToNM(nmHost, nmPort, nmHome, wlsDomainName, wlsDomainHome, nmType):
  try:
    print(lineSeperator)
    print('Try to connect to the Node Manager')
    try:
      nmConnect(userConfigFile=usrCfgFile, userKeyFile=usrKeyFile, host=nmHost, port=nmPort, domainName=wlsDomainName, domainDir=wlsDomainHome, nmType=nmType)
    except NameError, e:
      print('Apparently user config properties usrCfgFile and usrKeyFile not set.')
      print('Try to connect to the NodeManager adminUser and adminPwd properties')
      nmConnect(username=adminUser, password=adminPwd, host=nmHost, port=nmPort, domainName=wlsDomainName, domainDir=wlsDomainHome, nmType=nmType)
    print('Connected to the Node Mananger')
  except WLSTException:
    message='Apparently NodeManager not Started!'
    print (message)
    raise Exception(message)
# 
# 
def stopNM(nmHost, nmPort, nmHome, wlsDomainName, wlsDomainHome, nmType):
  try:
    print(lineSeperator)
    print ('Try to connect to the Node Manager')
    connectToNM(nmHost, nmPort, nmHome, wlsDomainName, wlsDomainHome, nmType);
    print ('Connected to the Node Mananger')
    print ('Stop the NodeManager')
    stopNodeManager();
    print('Finished stapping NodeManager')
  except WLSTException:
    print ('Apparently NodeManager not Started!')
#
def main():
  try:
    wlsDomainHome = wlsDomainsHome+'/'+wlsDomainName
    stopNM(nmHost, nmPort, nmHome, wlsDomainName, wlsDomainHome, nmType);
  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)
#
main()

You first need to connect to the NodeManager. This is done in connectToNM() that illustrates the use of the user config and key files with the adminUser/adminPwd properties as a fall back. First it tries to connect using the userConfigFile/userKeyFile combination. If that leads to a NameError, then you probably did not provide those, so it retries it on with the adminUser/adminPwd properties.
This construct is reused when trying to connect to the AdminServer to start the rest of the domain.
When it is connected the nodeManager can be stopped, simply with the stopNodeManager() command.

Start/Stop the AdminServer

The startAdmin.py provided below is used to Start the Admin Server. Again, there are  startWeblogic.sh and stopWeblogic.sh scripts in the bin folder of the domain. But those will start the server in the foreground (although you can move them to the background of course). But mainly the servers aren't under control of the NodeManager, what has it's advantages. So the startAdmin.py script:
#############################################################################
# Start AdminServer via NodeManager and try to connect to it.
# Result of this script should be that you are connect to the AdminServer.
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 2.1, 2016-06-27
#
#############################################################################
# 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:7101"
  print "adminUser=weblogic"
  print "adminPwd=welcome1"
# 
#
def connectToNM(nmHost, nmPort, nmHome, wlsDomainName, wlsDomainHome, nmType):
  try:
    print(lineSeperator)
    print('Try to connect to the Node Manager')
    try:
      nmConnect(userConfigFile=usrCfgFile, userKeyFile=usrKeyFile, host=nmHost, port=nmPort, domainName=wlsDomainName, domainDir=wlsDomainHome, nmType=nmType)
    except NameError, e:
      print('Apparently user config properties usrCfgFile and usrKeyFile not set.')
      print('Try to connect to the NodeManager adminUser and adminPwd properties')
      nmConnect(username=adminUser, password=adminPwd, host=nmHost, port=nmPort, domainName=wlsDomainName, domainDir=wlsDomainHome, nmType=nmType)
    print('Connected to the Node Mananger')
  except WLSTException:
    message='Apparently NodeManager not Started!'
    print (message)
    raise Exception(message)
    #print 'Start Nodemanager'
    #startNodeManager(verbose='true', NodeManagerHome=nmHome, ListenPort=nmPort, ListenAddress=nmHost);
    #print 'Retry to connect to the Node Manager';
    #nmConnect(username=adminUser, password=adminPwd, host=nmHost, port=nmPort, domainName=wlsDomainName, domainDir=wlsDomainHome, nmType=nmType);
#
#
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:
    print('Apparently AdminServer not Started!')
    print('Start AdminServer')
    nmStart(adminServerName)
    print('Retry 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)
#
#
def main():
  try:
    wlsDomainHome = wlsDomainsHome+'/'+wlsDomainName
    print(lineSeperator)
    print('Start '+adminServerName+' for domain in : '+wlsDomainHome)
    print(lineSeperator)
    print ('Connect to the Node Manager')
    connectToNM(nmHost, nmPort, nmHome, wlsDomainName, wlsDomainHome, nmType)
    print ('Connect to the AdminServer: '+adminServerName)
    connectToadminServer(adminUrl, adminServerName)
  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)
#
main();

The script first uses connectToNM(nmHost, nmPort, nmHome, wlsDomainName, wlsDomainHome, nmType) to connect to the NodeManager. Just in the same way as in the stopNodeManager.py script.
Then it tries to connect to the AdminServer using connectToadminServer(adminUrl, adminServerName). Now, the connect to the NodeManager might be a little over done. But in the connectToadminServer() function it tries to connect to the AdminServer the same way as to the NodeManager: first with the userConfigFile, userKeyFile combination. But when those properties aren't set, it uses the username password combination. If a connection to the AdminServer fails, the function concludes that it isn't started yet. But since it is still connected to the nodemanager it can start the AdminServer using nmStart(adminServerName). So it is important that in the adminServerName property in the fmw.properties the correct name of the AdminServer is given.

To stop the admin server I have the stopAdmin.py script:
#############################################################################
# Stop AdminServer 
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 2.1, 2016-06-27
#
#############################################################################
# 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:7101"
  print "adminUser=weblogic"
  print "adminPwd=welcome1"
#
#
def connectToadminServer( adminUrl, adminServerName):
  try:
    print(lineSeperator)
    print('Try to connect to the AdminServer using user config')
    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 main():
  try:
    wlsDomainHome = wlsDomainsHome+'/'+wlsDomainName
    print(lineSeperator)
    print('Stop '+adminServerName+' for domain in : '+wlsDomainHome)
    print(lineSeperator)
    print('\nConnect to the AdminServer: '+adminServerName)
    connectToadminServer(adminUrl, adminServerName)
    #
    print('\nShutdown the AdminServer: '+adminServerName)
    shutdown(force='true')
    #
    print('\nFinished stopping AdminServer: '+adminServerName)
  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)
#
main();

This one does a connect to the AdminServer (in the same two layer approach), and when connected it performs a shutdown(force='true'). This is equivalant to the 'Force Shutdown Now' option in the console. Since no server or cluster name is provided the AdminServer is shutdown.

Start&Stop Domain

In my create domain scripts I create clusters for every component. Even when I have only one managed server (for instance in a development environment) I added the servers to a cluster. This makes it easier to expand the domain with multiple nodes. And it makes the management the same for every environment.

So to start and stop the domain I work per cluster. The nice thing then is that when connected you can just issue a start cluster command and the AdminServer uses the different nodeManagers on the hosts to start the servers simultaneously. This reduces the startup time significantly compared to starting the servers of a cluster one by one.

 Now, it might be that one of the servers couldn't be started right away. And this fails the start cluster command. So I added a little code to try to start the different servers one by one. I think it is somewhat over done in most cases, but it does illustrate some functions to figure out the servers to start and to determine their state. So here is my startDomain.py script:
#############################################################################
# Start SOA and OSB domain
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.1, 2016-06-27
#
#############################################################################
# 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 connectToNM(nmHost, nmPort, nmHome, wlsDomainName, wlsDomainHome, nmType):
  try:
    print(lineSeperator)
    print('Try to connect to the Node Manager')
    try:
      nmConnect(userConfigFile=usrCfgFile, userKeyFile=usrKeyFile, host=nmHost, port=nmPort, domainName=wlsDomainName, domainDir=wlsDomainHome, nmType=nmType)
    except NameError, e:
      print('Apparently user config properties usrCfgFile and usrKeyFile not set.')
      print('Try to connect to the NodeManager adminUser and adminPwd properties')
      nmConnect(username=adminUser, password=adminPwd, host=nmHost, port=nmPort, domainName=wlsDomainName, domainDir=wlsDomainHome, nmType=nmType)
    print('Connected to the Node Mananger')
  except WLSTException:
    message='Apparently NodeManager not Started!'
    print (message)
    raise Exception(message)
    #print 'Start Nodemanager'
    #startNodeManager(verbose='true', NodeManagerHome=nmHome, ListenPort=nmPort, ListenAddress=nmHost);
    #print 'Retry to connect to the Node Manager';
    #nmConnect(username=adminUser, password=adminPwd, host=nmHost, port=nmPort, domainName=wlsDomainName, domainDir=wlsDomainHome, nmType=nmType);
#
#
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:
    print('Apparently AdminServer not Started!')
    print('Start AdminServer')
    nmStart(adminServerName)
    print('Retry 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)
#
# Get the Servers of Cluster 
def getClusterServers(clustername):
  #Cluster config to be fetched from ServerConfig
  print(lineSeperator)
  print('\nGet Servers from cluster '+clustername)
  serverConfig()
  cluster = getMBean("/Clusters/" + clustername)
  if cluster is None:
    errorMsg= "Cluster " + clustername + " does not appear to exist!"
    print errorMsg
    raise(Exception(errorMsg))
  print "Found cluster "+ clustername+ "."
  servers = cluster.getServers()
  return servers
#
#
def serverStatus(serverName):
  serverRuntime=getMBean('/ServerRuntimes/'+serverName)
  if serverRuntime is None:
    print("Server Runtime for  " + serverName + " not found, server apparently SHUTDOWN")
    serverState="SHUTDOWN"
  else:
    print "Found Server Runtime for "+ serverName+ "."
    serverState = serverRuntime.getState()
  return serverState
#
#
def startClusterServersOneByOne(clusterName):
  print(lineSeperator)
  print ('Start servers for cluster: '+clusterName)
  servers=getClusterServers(clusterName)
  # Need to go to domainRuntime to get to the serverRuntimes.
  domainRuntime()
  #
  for server in servers:
    print(lineSeperator)
    serverName = server.getName()
    print('ServerName: '+serverName)
    serverState = serverStatus(serverName)
    print('Server '+serverName+': '+serverState)
    if serverState=="SHUTDOWN":
      print ('Server '+serverName+' is not running so start it.')
      start(serverName)
    elif serverState=="RUNNING":
      print ('Server '+serverName+' is already running')
    else:
      print ('Server '+serverName+' in state '+serverState+', not startable!')
  #
  print ('\nFinished starting servers.')
#
#
def startClusterServers(clusterName):
  print(lineSeperator)
  print ('Start servers for cluster: '+clusterName)
  #
  try:
    start(clusterName,'Cluster')
  except WLSTException:
    print "Apparently Cluster in incompatible state!", sys.exc_info()[0], sys.exc_info()[1]
    startClusterServersOneByOne(clusterName)
  state(clusterName,'Cluster')
  #
  print ('\nFinished starting servers.')
#
#
def main():
  try:
    wlsDomainHome = wlsDomainsHome+'/'+wlsDomainName
    print (lineSeperator)
    print ('Start Osb Cluster')
    print('\nConnect to AdminServer ')
    print (lineSeperator)
    print ('Connect to the Node Manager')
    connectToNM(nmHost, nmPort, nmHome, wlsDomainName, wlsDomainHome, nmType)
    print ('Connect to the AdminServer: '+adminServerName)
    connectToadminServer(adminUrl, adminServerName)
    #
    print('Start servers for cluster: '+osbClr)
    startClusterServers(osbClr)
    #
    print('Start servers for cluster: '+soaClr)
    startClusterServers(soaClr)
    #
    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()

It first connects to the AdminServer in the familiar way. If that fails it tries to start it. So far it is copied from the startAdmin.py script. Then it calls the startClusterServers(clusterName) function for each cluster. You need to add each cluster here by hand. I could loop over the clusternames, but you might need to have them started in a certain order. This function first issues the start(clusterName,'Cluster') command. Providing the 'Cluster' parameter as a start type, a complete cluster can be started. If that fails, then apparently one or more servers failed to start. If so it tries to start the servers one by one in the startClusterServersOneByOne(clusterName) function. It gets the servers attached to the cluster using getClusterServers(clustername) function. This is done using the getServers() method of the cluster. This needs to be done in the serverConfig() state. After that for each server the status is fetched by querying the serverRuntime of the server in the serverStatus() function. ServerRuntimes are available in the DomainRuntime() state, so it is needed to switch the state using that function. If the ServerRuntime is not avaiable, the state is considered to be 'SHUTDOWN'. If the server is down a start(serverName) is issued. Lastly in the startClusterServers() function the state(clusterName,'Cluster') is called to print the state of the servers in the cluster.

To Stop the domain I created the stopDomain.py which mainly works in reverse:
#############################################################################
# Stop OSB Domain
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.1, 2016-06-27
#
#############################################################################
# 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)
#
# Get the Servers of Cluster 
def getClusterServers(clustername):
  #Cluster config to be fetched from ServerConfig
  print(lineSeperator)
  print('\nGet Servers from cluster '+clustername)
  serverConfig()
  cluster = getMBean("/Clusters/" + clustername)
  if cluster is None:
    errorMsg= "Cluster " + clustername + " does not appear to exist!"
    print errorMsg
    raise(Exception(errorMsg))
  print "Found cluster "+ clustername+ "."
  servers = cluster.getServers()
  return servers
#
#
def serverStatus(serverName):
  serverRuntime=getMBean('/ServerRuntimes/'+serverName)
  if serverRuntime is None:
    print("Server Runtime for  " + serverName + " not found, server apparently SHUTDOWN")
    serverState="SHUTDOWN"
  else:
    print "Found Server Runtime for "+ serverName+ "."
    serverState = serverRuntime.getState()
  return serverState
#
#
def stopClusterServers(clusterName):
  print(lineSeperator)
  print ('Stop servers for cluster: '+clusterName)
  #
  try:
    shutdown(clusterName,'Cluster')
  except WLSTException:
    print "Apparently Cluster in incompatible state!", sys.exc_info()[0], sys.exc_info()[1]
    state(clusterName,'Cluster')
    print ('Try to stop servers for cluster: '+clusterName+', one by one')
    servers=getClusterServers(clusterName)
    # Need to go to domainRuntime to get to the serverRuntimes.
    domainRuntime()
    #
    for server in servers:
      print(lineSeperator)
      serverName = server.getName()
      print('ServerName: '+serverName)
      serverState = serverStatus(serverName)
      print('Server '+serverName+': '+serverState)
      if serverState=="RUNNING":
        print ('Server '+serverName+' is running so shut it down.')
        shutdown(name=serverName, force='true')
      elif serverState=="SHUTDOWN":
        print ('Server '+serverName+' is already down.')
      else:
        print ('Server '+serverName+' in state '+serverState+', not stoppable!')
  #
  print ('\nFinished stopping servers.')
#
#
def main():
  try:
    wlsDomainHome = wlsDomainsHome+'/'+wlsDomainName
    print (lineSeperator)
    print ('Stop Osb Domain')
    print (lineSeperator)
    print('\nConnect to the AdminServer: '+adminServerName)
    connectToadminServer(adminUrl, adminServerName)
    print(lineSeperator)
    print('First stop servers from cluster '+osbClr)
    stopClusterServers(osbClr)
    #
    print(lineSeperator)
    print('\nShutdown the AdminServer: '+adminServerName)
    shutdown(force='true')
    print ('\nFinished stopping servers.')
    #
    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()

In the sameway as in starting the servers this script first tries to shutdown the cluster as a whole. The AdminServer takes advantage of the NodeManager to simulaneously stop the servers. The NodeManager first tries to connect to the particular server to hand over a suicide pill. But if it can't reach the server directly it releases it from suffering by doing an explicit OS-Level kill process...
After the shutdown of the servers the AdminServer is shut down.

Conclusion

This concludes this article on starting and stopping your domain. I hope it was enlighting and entertaining. One improvements  would be to reuse the scripts on starting and stopping the AdminServer in the starting and stopping of the Domain. You see that there is some code-overlap. But the way I call them with an explicit property file prevents doing a execfile(). But the properties loaded aren't passed to the execfile() apparently. And it needs a path to the other file. So that's why I for now combined the code into one script.

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.