Changements relatifs au comportement de Jython version 2.7

Cette rubrique présente les informations à connaître pour procéder au portage de scripts Jython V2.1 afin d'utiliser Jython V2.7.

Changements de comportement de Jython connus dans la version 2.7. Si votre script ne fonctionne pas correctement avec Jython version 2.7, mettez à jour le script en suivant les suggestions ou restez à la version Jython 2.1:

Modules de bibliothèques obsolètes dans Jython V2.7

Certains modules de bibliothèque de la version 2.1 ont été dépréciés ou réécrits pour Jython version 2.7. Par conséquent, si votre script Jython V2.7 les importe, vous recevez une erreur ImportError semblable à la suivante :
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
Vous devrez réécrire votre script Jython pour utiliser les fonctions de bibliothèque Jython les plus récentes disponibles dans la version 2.7, ou bien continuer d'utiliser Jython 2.1 si vous ne souhaitez pas mettre à jour votre script.
Modules de bibliothèques Jython obsolètes :
  • dospath
  • gopherlib
  • javaos
  • jreload
  • reconvert
  • tzparse
  • whrandom

Le module javaos a été remplacé par os. La plupart des fonctions jreload sont contenus dans ihooks pour la version 2.7.

Modifications de comportement de chaîne

Le comportement de traitement de String utilise un type de chaîne par défaut Unicode dans la version 2.7. Il n'a pas d'impact sur les fonctions existantes du serveur d'application, mais il affiche la chaîne renvoyée sous forme de chaîne Jython Unicode avec une chaîne littérale u ajoutée au début de la chaîne. Par exemple, il renvoie la chaîne string régulière en tant que chaîne u'string Unicode. Lorsque vous utilisez la valeur de la chaîne renvoyée comme variable pour la commande wsadmin, vérifiez que la valeur de la chaîne ne contient pas de chaîne Unicode. Si la valeur de la chaîne contient une chaîne Unicode, utilisez str(va1) avant de transmettre val1 à la commande wsadmin. Vous pouvez spécifier la commande print pour afficher la chaîne régulière. Vous pouvez également appeler la commande str() pour convertir la chaîne Jython Unicode en une chaîne régulière telle que :

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)'

Modifications apportées à la fonction sys.exit()

Le sys.exit() lève unSystemExitexception, il s'attend donc à capturer laSystemExitexception. Il n'a pas besoin d'augmenter laSystemExitexception dans v2.1, mais votre script peut échouer avec laSystemExiterreur si vous ne capturez pasSystemExitexception dans v2.7:

Consultez l'exemple de code test.py, qui illustre ce comportement :

test.py: 

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

Il se produit l'exception suivante :

WASX7017E: Exception reçue lors de l'exécution du fichier "c:/q.py" ; informations relatives à l'exception : com.ibm.bsf.BSFException: reçues de Jython :
	Traceback (most recent call last):
           	File "<string>", line 12, in <module>
	SystemExit: 0

Le problème peut être évité en utilisant l'une des solutions suivantes :

  • Mettez en commentaire sys.exit() si vous ne souhaitez pasSystemExitexception.
  • Utilisez la fonction os._exit() à la place desys.exit()si vous ne voulez pas déclencher d'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)
  • Capturez leSystemExitexception si vous souhaitez détecter laSystemExitErreur et génération d'une 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"

Changements apportés à l'importation de modules

Si votre script Jython doit importer un module, celui-ci peut être placé dans le répertoire de travail wsadmin ou à un autre endroit.

Par exemple :

test.py contient la ligne suivante :

import custom

custom.py peut être placé dans le répertoire de travail wsadmin, par exemple, c:\WebSphere\AppServer\profiles\dmgr01\bin, où wsadmin est exécuté.

custom.py est automatiquement chargé quand vous exécutez test.py, par exemple :
wsadmin -f c:/test.py
Si custom.py est placé dans un autre emplacement tel que le répertoire c:\customscripts, vous devez spécifier -profile <profile_module> pour importer le module personnalisé tel que :
wsadmin -profile c:/customscripts/custom.py -f c:/test.py
Si vous devez importer plusieurs modules situés à différents endroits, par exemple :
  • test1.py se trouve dans le répertoire profile_root/profile_name
  • test2.py se trouve dans le répertoire profile_root/
Vous pouvez ajouter des modules par le biais de plusieurs commandes -profile <profile_module> telles que :
wsadmin -profile <profile_root/profile_name/test1.py> -profile <profile_root/test2.py> -f c:/test.py
Ou bien, vous pouvez ajouter les chemins d'accès aux modules via la propriété système Jython python.path, laquelle ajoute les chemins à la propriété python.path quand Jython est chargé ; par exemple :
wsadmin.sh -lang jython -javaoption "-Dpython.path=<profile_root/profile_name>;< profile_root>" -f c:/test.py

Si votre module d'importation appelle des commandes wsadmin Admin , vous pouvez recevoir lesNameError: global name 'AdminConfig' is not definedMessage d'erreur. Il peut également réclamer d'autres objets Admin, tels que AdminControl, AdminApp, AdminTask ou Help. Avec Jython 2.7, les objets Admin ne sont plus enregistrés dans l'espace de nom global, vous devez donc les récupérer dans l'espace de nom local du système.

Par exemple, si custom.py contient la fonction print1(), qui appelle la commande wsadmin AdminConfig.list() :
def print1():
           print "I am custom"
           nodes = AdminConfig.list('Node')
           print "Nodes: " + nodes
Lorsque vous exécutez test.py, il se peut que vous receviez l'erreur suivante :
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
Pour résoudre leNameError, vous devez ajouter les commandes Jython suivantes devant votre script de module d'importation (et non le script d'appel):
#custom.py:

import sys

# Retrieve scripting objects from system local name space 
AdminConfig = sys._getframe(1).f_locals['AdminConfig']
Vous pouvez extraire d'autres objets Admin si votre script appelle d'autres commandes Admin :
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

Comment déclencher une exception de type chaîne

Jython V2.7 ne permet pas de générer une exception de chaîne. Vous devez donc générer une exception ou une erreur telle que:ValueError,AttributeError,TypeErrorou créez votre propre type d'erreur dans une classe Jython.

Par exemple :

test.py:

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

Il fonctionne avec Jython 2.1, mais vous recevez les informations suivantes:TypeErrordans Jython V2.7:

WASX7017E: Exception reçue lors de l'exécution du fichier "c:/p.py" ; informations sur l'exception : com.ibm.bsf.BSFException: reçues de 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

Vous devez réécrire votre script pour qu'il soit généré en tant qu'exception ouValueError/TypeError/AttributeError.

  • Déclenchez une exception :
    if (nodeName != "testNode2"):
              raise Exception("Could not find node name '%s'" % (nodeName))
  • Générez unValueError:
    if (nodeName != "testNode2"):
              raise ValueError("Could not find node name '%s'" % (nodeName))
  • Créez votre propre type d'erreur dans une classe Jython :
    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))

Modifications apportées au type numérique

Dans Jython version 2.1, les types numeric étaient des objets Py tels que PyInteger ou PyFloat et, en tant que tels, comportaient des méthodes comme toString(). Dans Jython version 2.7, les types numeric sont plutôt des types native et ne disposent pas de ces méthodes Object de base. La différence est découverte lorsqu'un entier est transmis via une fonction Jython et que sa valeur est imprimée à l'aide de la méthode toString().

Dans Jython 2.7, utilisation de l'exemple de code suivant :

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

génère l'erreur suivante :

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'

Vous pouvez utiliser la commande suivante pour afficher le type numeric :

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

Environnement local non anglais sur le système d'exploitation Windows

Lorsque vous utilisez Jython V2.7 sur un système d'exploitation Windows, le traitement des caractères Unicode est affecté en raison de la façon dont le codage est géré. Le comportement de Jython V2.7 suppose un codage UTF-8. Sur le système d'exploitation UNIX, le traitement et l'affichage des caractères sont corrects. Pour le système d'exploitation Windows, le processus Jython V2.7 interrompt l'affichage des caractères dans l'invite de commande Windows car la console de commande Windows ne prend pas en charge UTF-8 et n'interprète pas correctement les caractères Unicode.

Mettez à jour le fichier wsadmin.bat pour ajouter l'instruction -Dfile.encoding=UTF-8 afin d'éviter ce problème. L'exemple suivant démontre cet ajustement du scénario.
%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 %*

Utilisation de l'option -useJython21

Les scripts Jython implémentés avec le caractère de continuation de ligne "\" s'exécutent correctement sur WebSphere Application Server version 8.0 et version 8.5.5 mais pas sur la version 9.0. Pour la version 9.0, ces mêmes scripts échouent avec une exception com.ibm.bsf.BSFException: exception from Jython: "no viable alternative at input"...

Deux solutions à cette anomalie sont possibles :
  1. Supprimez le caractère de continuation et enchaînez le script en une longue ligne. Cette approche fonctionne pour la version 9.0 en utilisant Jython27.
  2. Conservez le script tel qu'il est (avec le caractère de continuation de ligne), mais ajoutez -useJython21 option au script.
Voir l'exemple suivant d'un scénario qui répond à cette 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 \
....

Modification de l'espace de nom pour les objets de scriptages

Pour Jython 2.7, les objets de scriptage sont récupérés dans l'espace de nom local du système au lieu d'être enregistrés dans l'espace de nom global. Les objets de scriptage sont AdminApp, AdminConfig, AdminTask, AdminControl et Help.

Lorsque vous importez un script personnalisé dans la bibliothèque de scriptage, si le script personnalisé exécute des bibliothèques de scriptage wsadmin, telles que AdminUtilities et Micromanagement, le script personnalisé peut recevoir une erreur NameError. L'erreur se produit lorsque les bibliothèques de scriptage wsadmin utilisent des objets de script qui ne sont pas spécifiés dans l'espace de nom local du système. L'exemple suivant est le script personnalisé de test1 :

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
Dans l'exemple suivant, le script personnalisé test1 reçoit une erreur NameError :
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
Pour résoudre l'erreur NameError, ajoutez les objets de script au script personnalisé :
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']
Si vous utilisez l'option -usejython21 pour exécuter un script personnalisé en tant que Jython V2.1 et que le script personnalisé exécute les bibliothèques de scriptage wsadmin, mettez en commentaire les objets de script dans le script personnalisé. Les bibliothèques de scriptage sont mises en commentaire dans l'exemple suivant :
$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']

Le script personnalisé nommé test.py n'est pas autorisé

Pour éviter une erreur AttributeError lors de l'exécution de votre script personnalisé, ne nommez pas le script personnalisé test.py car le terme test est utilisé dans les modules de la bibliothèque Jython. L'exemple suivant illustre l'erreur AttributeError :
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'