Jython V2.7 behavior changes

Discover what you need to know when porting Jython V2.1 scripts to use Jython V2.7.

The following are known Jython behavioral changes in V2.7. If your script does not work properly with Jython V2.7, update your script by using the following suggestions or stay with the older Jython V2.1:

Deprecated library modules in Jython V2.7

Some V2.1 library modules were deprecated or rewritten for Jython V2.7. So if your Jython V2.7 script imports them, you receive an ImportError like so:
WASX7017E: Exception received while running file "c:/test.py"; exception information: com.ibm.bsf.BSFException: exception from Jython:
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: No module named jreload
You need to rewrite your Jython script to use the most recent Jython library functions available in V2.7 or continue to use the older Jython V2.1 if you do not want to update your script.
Deprecated Jython library modules:
  • dospath
  • gopherlib
  • javaos
  • jreload
  • reconvert
  • tzparse
  • whrandom

The javaos module was replaced with os. Most of the jreload functions are contained within ihooks in V2.7.

String behavior changes

The String handling behavior uses a default string type of Unicode in V2.7. It does not impact the existing application server functions, but it displays the returned string as Jython Unicode string with a string literal u added to the beginning of the string. For example, it returns the regular string as Unicode u'string. When you use the returned string value as a variable for the wsadmin command, check to make sure that the string value does not contain Unicode string. If the string value contains Unicode string, then use str(va1) before you pass val1 to the wsadmin command. You can specify the print command to display the regular string. Alternatively, you can call the str() command to convert Jython Unicode string to a regular string such as:

AdminConfig.list('Node')
	u'TestCellManager(cells/TestCell/nodes/TestCellManager|node.xml#Node_1)\r\nTestNode(cells/TestCell/nodes/TestNode|node.xml#Node_1)'
        
       # use print command to display regular string
	print AdminConfig.list('Node')      
	TestCellManager(cells/TestCell/nodes/TestCellManager|node.xml#Node_1)
	TestNode(cells/TestCell/nodes/TestNode|node.xml#Node_1)

	nodes = AdminConfig.list('Node')
	u'TestCellManager(cells/TestCell/nodes/TestCellManager|node.xml#Node_1)\r\nTestNode(cells/TestCell/nodes/TestNode|node.xml#Node_1)'
	print nodes
	TestCellManager(cells/TestCell/nodes/TestCellManager|node.xml#Node_1)
	TestNode(cells/TestCell/nodes/TestNode|node.xml#Node_1)

       # Call str() command to convert unicode string to regular string
	nodes = str(nodes)   
	nodes
	'TestCellManager(cells/TestCell/nodes/TestCellManager|node.xml#Node_1)\r\nTestNode(cells/TestCell/nodes/TestNode|node.xml#Node_1)'

Changes to sys.exit() function

The sys.exit() raises a SystemExit exception, so it expects to capture the SystemExit exception. It does not need to raise the SystemExit exception in v2.1, but your script can fail with the SystemExit error if you do not capture the SystemExit exception in v2.7:

See example code test.py, which demonstrates this behavior:

test.py: 

     a = 5 
     b = 6 
     
     if (a > b): 
          print "a > b" 
          sys.exit(1) 
     else: 
          print " a < b" 
          sys.exit(0)

The following exception occurs:

WASX7017E: Exception received while running file "c:/q.py"; exception information: com.ibm.bsf.BSFException: exception from Jython:
	Traceback (most recent call last):
           	File "<string>", line 12, in <module>
	SystemExit: 0

The problem can be avoided by using any one of the following solutions:

  • Comment out sys.exit() if you don't want to raise the SystemExit exception.
  • Use os._exit() function instead of sys.exit() if you don't want to trigger an exception.
    test.py:
    
          import os 
          
          a = 5 
          b = 6 
          
          if (a > b): 
              print "a > b" 
              os._exit(1) 
          else: 
              print "a < b" 
              os._exit(0)
  • Capture the SystemExit exception if you want to detect the SystemExit error and raise an exception.
    test.py: 
    
         a = 5 
         b = 6 
         
         try: 
              if (a > b): 
                  print "a > b" 
                  sys.exit(1) 
              else: 
                  print "a < b" 
                  sys.exit(0) 
         except SystemExit: 
               print "sys.exit() worked as expected" 
         except: 
               print "Something went wrong"

Changes to importing modules

If your Jython script needs to import a module, the module can be placed in the wsadmin working directory or it can be placed in another location.

For example:

test.py contains the following line:

import custom

The custom.py can be placed in the wsadmin working directory such as c:\WebSphere\AppServer\profiles\dmgr01\bin where wsadmin is run.

The custom.py is automatically loaded when you run test.py such as:
wsadmin -f c:/test.py
If custom.py is placed in other location such as c:\customscripts directory, you need to specify -profile <profile_module> to import the custom module such as:
wsadmin -profile c:/customscripts/custom.py -f c:/test.py
If you need to import multiple modules located in different locations, for example:
  • test1.py is in the profile_root/profile_name directory
  • test2.py is in the profile_root/ directory
You can add modules through multiple -profile <profile_module> commands such as:
wsadmin -profile <profile_root/profile_name/test1.py> -profile <profile_root/test2.py> -f c:/test.py
Or you can add the modules path through the Jython system property python.path and it appends the paths to the property python.path when Jython is loaded such as:
wsadmin.sh -lang jython -javaoption "-Dpython.path=<profile_root/profile_name>;< profile_root>" -f c:/test.py

If your importing module invokes wsadmin Admin commands, you can receive the NameError: global name 'AdminConfig' is not defined error message. It can complain about other Admin objects such as AdminControl, AdminApp, AdminTask, or Help as well. With Jython 2.7, Admin objects no longer register in the global name space so you need to retrieve it from system local name space instead.

For example, if custom.py contains the function print1(), which invokes the wsadmin AdminConfig.list() command:
def print1():
           print "I am custom"
           nodes = AdminConfig.list('Node')
           print "Nodes: " + nodes
When you run test.py, you can receive the error:
WASX7017E: Exception received while running file "c:/test.py"; exception information: com.ibm.bsf.BSFException: exception from Jython:
Traceback (most recent call last):
  File "<string>", line 15, in <module>
  File "<string>", line 9, in print2
  File "c:\custom.py", line 21, in print1
    cell = AdminConfig.list('Cell')
NameError: global name 'AdminConfig' is not defined
To resolve the NameError, you need to add the following Jython commands in front of your importing module script (not the calling script):
#custom.py:

import sys

# Retrieve scripting objects from system local name space 
AdminConfig = sys._getframe(1).f_locals['AdminConfig']
You can retrieve other Admin objects too if your script invokes other Admin commands:
AdminApp = sys._getframe(1).f_locals['AdminApp']
AdminControl = sys._getframe(1).f_locals['AdminControl']
AdminTask = sys._getframe(1).f_locals['AdminTask']
Help = sys._getframe(1).f_locals['Help']

def print1():
      print "I am custom"
      nodes = AdminConfig.list('Node')
      print "Nodes: " + nodes

How to raise a string exception

Jython V2.7 does not allow raising a string exception, so you need to either raise an exception or error such as ValueError, AttributeError, TypeError, or create your own error type in a Jython class.

For example:

test.py:

	nodeName = "testNode1"
	if (nodeName != "testNode2"):
     	      raise "Could not find node name '%s'" % (nodeName)

It works with Jython 2.1, but you receive the following TypeError in Jython V2.7:

WASX7017E: Exception received while running file "c:/p.py"; exception information: com.ibm.bsf.BSFException: exception from Jython:
	Traceback (most recent call last):
       File "<string>", line 5, in <module>
	TypeError: exceptions must be old-style classes or derived from BaseException, not str

You need to rewrite your script to raise as an exception or a ValueError/TypeError/AttributeError.

  • Raise an exception:
    if (nodeName != "testNode2"):
              raise Exception("Could not find node name '%s'" % (nodeName))
  • Raise a ValueError:
    if (nodeName != "testNode2"):
              raise ValueError("Could not find node name '%s'" % (nodeName))
  • Create your own error type in a Jython class:
    class MyError(Exception): 
       	      '''raise this when there's an error from my command''' 
       
    	if nodeName != "testNode2":
              raise MyError("Could not find node name '%s'" % (nodeName))

Numeric type changes

In Jython V2.1, numeric types were Py objects like PyInteger or PyFloat and as such had methods like toString(). In Jython V2.7, numeric types are more like native types and do not have these basic Object methods available. The difference was discovered when an integer is passed into a Jython function and its value is printed by using the toString() method.

In Jython V2.7, using this sample code:

foo = 3.1415
	print "foo =", foo.toString()  
	foo =

Results in the following error:

WASX7015E: Exception running command: ""foo =", foo.toString()"; exception information:
	com.ibm.bsf.BSFException: exception from Jython:
	Traceback (most recent call last):
  	File "<input>", line 1, in <module>
	AttributeError: 'float' object has no attribute 'toString'

You can use the following command to display the numeric type:

print "foo = %f" % foo
	foo = 3.141500

Non-English locale on the Windows operating system

When you use Jython V2.7 on a Windows operating system, the processing of Unicode characters is affected because of how encoding is handled. The Jython V2.7 behavior assumes UTF-8 encoding. On the UNIX operating system, the processing and display of characters is correct. For the Windows operating system, the Jython V2.7 process breaks the display of characters on the Windows command prompt because the Windows command console does not support UTF-8 and misinterprets the Unicode characters.

Update the wsadmin.bat file to add the -Dfile.encoding=UTF-8 statement to avoid this issue. The following example demonstrates this script adjustment.
%JAVA_EXE% -Dfile.encoding=UTF-8 
-Djava.ext.dirs="%WAS_JAVA_EXT_DIRS%" 
-Djava.endorsed.dirs="%WAS_ENDORSED_DIRS%" 
-Dcmd.properties.file=%TMPJAVAPROPFILE%  %PERFJAVAOPTION%
 %WAS_LOGGING%  %CONSOLE_ENCODING%
 %WAS_DEBUG%  "%CLIENTSOAP%"
 "%JAASSOAP%"  "%CLIENTSAS%"
 "%CLIENTSSL%"
 %WSADMIN_PROPERTIES_PROP%
 %WORKSPACE_PROPERTIES% "
-Duser.install.root=%USER_INSTALL_ROOT%" 
"-Dwas.install.root=%WAS_HOME%
" %javaoption%
com.ibm.wsspi.bootstrap.WSPreLauncher  -nosplash -application 
com.ibm.ws.bootstrap.WSLauncher
com.ibm.ws.admin.services.WsAdmin %*

Using the -useJython21 option

Jython scripts that are implemented with a line continuation character "\" execute properly on WebSphere Application Server Version 8.0 and Version 8.5.5 but not on Version 9.0. For Version 9.0, these same scripts fail with a com.ibm.bsf.BSFException: exception from Jython: "no viable alternative at input"...

Two solutions to this anomaly are possible:
  1. Remove the continuation character and string the script out into a long single line. This approach works for V9.0 using Jython27.
  2. Keep your script as is (with the line continuation character), but add the -useJython21 option to the script.
See the following example of a script that fits this condition.
def updateEAR(input_appName, input_appname_path,
input_MapModulesToServers):
#print "input_appName : " + input_appName
#print "input_appname_path : " + input_appname_path
#print "input_MapModulesToServers : " +
input_MapModulesToServers

AdminApp.update(input_appName, \
'app',
'[ -operation update \
-contents ' + input_appname_path + ' \
-nopreCompileJSPs \
-distributeApp \
-nouseMetaDataFromBinary \
-nodeployejb \
-createMBeansForResources \
....

Changes to the name space for scripting objects

For Jython 2.7, the scripting objects are retrieved from the system local name space instead of being registered in the global name space. The scripting objects are AdminApp, AdminConfig, AdminTask, AdminControl, and Help.

When you import a custom script to the scripting library, if the custom script runs wsadmin scripting libraries such as AdminUtilities and Micromanagement, the custom script might receive a NameError error. The error occurs when the wsadmin scripting libraries use scripting objects that are not specified in the system local name space. The following example is the test1 custom script:

test1.py: (invoke AdminUtilities script library function)

import AdminUtilities,AdminClusterManagement,AdminServerManagement
bundleName = "com.ibm.ws.scripting.resources.scriptLibraryMessage"
resourceBundle = AdminUtilities.getResourceBundle(bundleName)

# 1: Remove Cell Custom Property
def disableAdminAuthCache(cellName):
   try:
      # Get a handle to the JVM object...
      AdminUtilities.infoNotice("Cell name supplied to disableAdminAuthCache: " + cellName)
      propertyId = AdminConfig.getid("/Cell:"+cellName+"/Property:enableAdminAuthorizationCache/")

      AdminUtilities.infoNotice("Property to remove is: " + propertyId)

      # Get the current args set
      if (propertyId != ""):
          AdminConfig.remove(propertyId)

      AdminUtilities.infoNotice("enableAdminAuthorizationCache property is now removed")

   except:
      AdminUtilities.infoNotice("There was an issue removing the enableAdminAuthorizationCache property")
      raise
   #endTry
#endDef
In the following example, the test1 custom script receives a NameError error:
D:\WebSphere\AppServer\profiles\Dmgr01\bin>wsadmin -conntype none -javaoption "-Dwsadmin.script.libraries=c:\testscript" -c "test1.disableAdminAuthCache('abc')"
WASX7357I: By request, this scripting client is not connected to any server process. Certain configuration and application operations will be available in local mode.
WASX7015E: Exception running command: "test1.disableAdminAuthCache('abc')"; exception information:
com.ibm.bsf.BSFException: exception from Jython:
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'test1' is not defined
To resolve the NameError error, add the scripting objects to the custom script:
import sys

# Retrieve scripting objects from local name space
AdminConfig = sys._getframe(1).f_locals['AdminConfig']
AdminApp = sys._getframe(1).f_locals['AdminApp']
AdminControl = sys._getframe(1).f_locals['AdminControl']
AdminTask = sys._getframe(1).f_locals['AdminTask']
Help = sys._getframe(1).f_locals['Help']
If you use the -usejython21 option to run a custom script as Jython V2.1 and the custom script runs the wsadmin scripting libraries, comment out the scripting objects in the custom script. The scripting libraries are commented out in the following example:
$WAS_HOME/scriptLibraries/servers/V70/AdminServerManagement.py

# Retrieve scripting objects from local name space
#AdminConfig = sys._getframe(1).f_locals['AdminConfig']
#AdminApp = sys._getframe(1).f_locals['AdminApp']
#AdminControl = sys._getframe(1).f_locals['AdminControl']
#AdminTask = sys._getframe(1).f_locals


['AdminTask']
#Help = sys._getframe(1).f_locals['Help']

Custom script named test.py not allowed

To avoid an AttributeError error when your custom script runs, do not name the custom script test.py because the test term is used in Jython library modules. The following example illustrates the AttributeError error:
D:\WebSphere\AppServer\profiles\Dmgr01\bin>wsadmin -conntype none -javaoption "-Dwsadmin.script.libraries=c:\testscript" -c "test.disableAdminAuthCache('abc')"
WASX7357I: By request, this scripting client is not connected to any server process. Certain configuration and application operations will be available in local mode.
WASX7015E: Exception running command: "test.disableAdminAuthCache('AMYLIN8Cell43')"; exception information:
com.ibm.bsf.BSFException: exception from Jython:
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'module' object has no attribute 'disableAdminAuthCache'