As soon as your Jython scripting reaches the point where you start trying to build reusable Jython modules, you’ll hit another odd limitation of the wsadmin environment – you can only access the Admin objects from the top-level module. Try to create a utility module and import it and you’ll find that AdminTask (or AdminControl, or…) is undefined.
Various workarounds have been posted over the past few years:
- Passing the Admin objects into the methods that need them. This is straightforward but clutters the interface.
- Registering the Admin objects as __builtin__. This does make them available everywhere but it does mean adding (ugly) boilerplate to modules that might not even have much to do with WebSphere internals.
- Registering the Admin objects as modules, as for example in this blog post. This is really just a variant of the previous workaround. I think it’s a bit cleaner, but it still makes demands on the caller.
To my mind, and for the purpose of the ibmfixes module, the problem with all of these is that the caller has to know that you’re going to need these objects (and which ones). I want a solution that can be implemented in the module where the object is needed. More than that, I want to be able to hide the fix in a module to be imported by the module that needs it so I don’t even have to know about it anymore.
Fortunately, Jython provides the required functionality:
import sys # We're going to be referencing the top-level frame in many of the fixes. topframe = sys._getframe() while topframe.f_back: topframe = topframe.f_back try: for module in 'AdminApp', 'AdminConfig', 'AdminControl', 'AdminTask', 'Help': if topframe.f_globals.has_key(module): sys.modules[module] = topframe.f_globals[module] except: pass
What this does is copy the Admin objects from the topmost frame into sys.modules. Once that’s done, any module can import the Admin objects they need as if they were proper modules. The beauty of this approach is you can now use the Admin objects anywhere without adding any additional burden on the scripts that might call you (or in an existing system, might already be calling you).