I have always believed it is important to find out the bigger picture early on in a problem investigation. For example, if a managed server is exhibiting problematic behaviour, as well as I looking at the logs, I like to know the context - for example:
- Is the server part of a cluster?
- How many servers / clusters are in the Weblogic Domain?
- Is the domain spread across multiple machines?
- Are System Resources such JDBC and JMS in play?
Weblogic Server scripting ( WLST ) has been around for many years. Consequently there are a large number of examples to be found in blogs, websites and forums. The vast majority assume you can run the script in online mode. What if, however, a WLST online connection cannot be established? Ok, sure we can manually peruse the DOMAIN_HOME/config/config.xml. It is not a friendly a solution partly because some of the configuration is held in other xml files referenced by the config.xml. There has to be another way, I thought, after all WebLogic Server holds domain configuration in MBeans. This got me thinking about WLST.
WLST's readDomain Function
We can use WLST's readDomain function, in offline mode, to load the domain MBean configuration hierarchy / tree. It is as simple this:
Example: Unix Machine:
Now you are ready to navigate the "tree" using "cd" and "ls" style syntax
-rw- Active false
-rw- AdminServerName AdminServer
-rw- AdministrationMBeanAuditingEnabled false
-rw- AdministrationPort 9002
-rw- AcceptBacklog 300
-rw- AdminReconnectIntervalSeconds 10
-rw- AdministrationPort 0
-rw- AdministrationPortEnabled false
-rw- AdministrationProtocol null
-rw- JavaCompilerPostClassPath null
-rw- JavaCompilerPreClassPath null
-rw- JavaStandardTrustKeyStorePassPhraseEncrypted null
-rw- JdbcLoginTimeoutSeconds 0
-rw- KeyStores null
-rw- ListenAddress 127.0.0.1
-rw- ListenDelaySecs 0
-rw- ListenPort 7021
-rw- ListenPortEnabled true
wls:/offline/MyDomain/Server/MyManagedServer/foo = get('ListenPort')
Sample Script and Output
To write a script, which automates the capture and print out of
attributes useful to a summary, is challenging because the functions to
traverse and search the MBean tree are limited compared to online mode. You are pretty much stuck with the cd(), ls() and get(). However, with a bit of coding creativity with IF and FOR loop syntax you can programmatically explore the tree and return output in a nice format - in my sample I have chosen HTML tables.
To view sample output, go here
Screenshot below shows snipper of sample output.
Download Sample Script
You can grab the sample script by clicking here
Instructions to Run:
1. Edit the environment variables in the start wrapper script startWLSofflineCollection.sh (Unix) or startWLSofflineCollection.cmd (MS Windows) to suit your system
Example - startWLSofflineCollection.sh
DOMAIN_HOME=/oracle/middleware/user_projects/domains/MyDomain; export DOMAIN_HOME
WLST_OUTPUT_PATH=/temp/wlst/; export WLST_OUTPUT_PATH
WLST_OUTPUT_FILE=WLST_MBean_Config_Summary.html; export WLST_OUTPUT_FILE
Note: The WLST_OUTPUT_PATH directory value must have a trailing slash. If there is no trailing slash script will error and not continue.
2. Then run the wrapper script. It should launch WLST and run the script. The script will collect MBean values and render them in a HTML file.
(Once the script has invoked the WLST shell, the execution of the python script should not take longer than 5 to 10 seconds.)
This is a sample script. I have tested it against WebLogic Server 10.3.6 domains on MS Windows and Unix. I cannot guarantee that the script will run error free or produce the expected output on your system. That said, a number of colleagues have also run the script and with their feedback I have ironed out a few problems. If you have any feedback add a comment to the blog. I will endeavour to fix any problems with my WLST code.
I found the following blogs particularly useful.
Java / Oracle SOA blog
WLST By Examples
Some Pitfalls (which required coding around)
Checking whether Configuration MBean Hierarchy Exists
If a service or functionality, such as Clusters, JDBC, JMS, Filestore are not configured, the related MBean hierarchy will not be visible when listing at domain level. Example: If Cluster, JDBC, JMS and Filestore have not been configured, the ls() will show:
A programmatic attempt to cd to a directory not listed will return an error e.g.
Error: cd() failed. Do dumpStack() to see details.
To work-around, the script contains a custom findMBean function. The function places the contents of the ls() in an array using the returnmap parameter. We can then loop through the array and check whether a given string - the MBean directory name exists e.g.
# get a listing of everything in the current directory
mydirs = ls(returnMap='true');
v_compile_pattern = java.util.regex.Pattern.compile(v_pattern);
found = 'Nope not here';
for mydir in mydirs:
x = java.lang.String(mydir);
v_matched = v_compile_pattern.matcher(x);
found = 'true';
AnyMachine v Machines
In WebLogic Server 10.3, if a domain has one or more machines configured (i.e nodemanager related machines) the ls() at domain level will show
A cd ('AnyMachine'), however, will fail. The correct cd syntax is
Identifying Target Information
Features such as JDBC System Resources, Clusters may or may not have targets. An attempt to cd to an MBean directory or get an MBean attribute which does not exist will throw an error and prevent the script from continuing. To work-around we can use TRY / EXCEPT syntax. Example - snippet from sample script which deals with the capture of JDBC System Resource targets.
v_any_targets = '';
v_jdbc_target = get('Target');
# Even if the get fails, the variable is assigned a value of none, set the flag variable accordingly
if v_jdbc_target == 'None':
v_any_targets = 'None';
v_no_of_targets = 1;
# If the get has succeeded then set flag accordingly and obtain length of array returned by the get
# The array length will be used to determine the HTML rowspan value
v_any_targets ='Use v_jdbc_target';
v_no_of_targets = len(v_jdbc_target);
# Setting flag and rowspan variable here as well .. belt and braces
v_any_targets = 'None';
v_no_of_targets = 1;
# The exception will still display to standard out, which may cause alarm
# So adding this message telling the user the exception is expected and can be ignored
print "IGNORE this exception";