Showing posts with label scripting. Show all posts
Showing posts with label scripting. Show all posts

Thursday, February 12, 2009

A scripting bundle for OSGi

I've wrapped the scriptconsole4j as an OSGi bundle (tested in Apache Felix 1.4.0 and Equinox 3.4.0).

This console is a simple GUI that allows using the JSR-223 compatible scripting languages available in you Java 6 VM. The Rhino Engine (Javascript) is available by default.

If you want to execute scripts accessing the OSGi framework to retrieve services in adhoc scripts, you may find this version of the scriptconsole4j tool useful. When the bundle is started a scripting window is automatically displayed. Upon bundle termination, the window is disposed and vice-versa.

How to use it:
  • Just download it.
  • Install it on your favorite OSGi framework
  • Start the bundle
  • And its ready to be used

You can, for example, register listeners to framework objects:


var o = new Object();
o.bundleChanged = function(e) {
message = "An event happened to bundle "
+ e.getBundle().getBundleId();
output.println(message);
//Writing in the standard output
java.lang.System.out.println(message);
};

ctx.addBundleListener(new org.osgi.framework.BundleListener(o));

Since the bundle uses DynamicImport-Package, you can use it with any exported class, so you can dynamically implement and register services:

var o = new Object();
o.sayHello = function() { java.lang.System.out.println("closed")};

r = new com.foo.HelloServerService(o);
//registering the service in the OSGi Service Registry
ctx.registerService("foo.BarService",r,null);
//retrieving the service instance
service = ctx.getService(ctx.getServiceReference("foo.BarService"));
service.myMethod();

Take a look at the Rhino page showing how to use Java from Javascript, and use your imagination for the scripts that may help you.

Recently I needed the scripting functionality in OSGi on a Java 5 Virtual Machine, which does not come with the JSR-223. I've removed the JSR-223 dependant stuff from the scriptconsole4j and embedded the beanshell core with it. It worked fine but without dynamic class generation. I guess by adding the bsh-classgen it "would" work. Since we are running on OSGi, classloading is always an issue when dynamically generating stuff...
I'll test it and leave it available soon (I hope so).

Sunday, July 6, 2008

Heap snapshot analysis and objects with different class versions

I’ve been working lately on the detection of a particular problem, called stale references, that may happen on OSGi based applications. It is a consequence of bad OSGi programming practices that may lead to memory retention and the utilization of inconsistent objects.

As a part of the diagnosis process I need to analyze heap snapshots to find the referrers of services that have been unregistered. I’ve found some interesting stuff (at least for me) concerning memory inspection and classloading. Each module (bundle) in OSGi is provided with its own class loader instance. If you replace (update) a module during runtime, it will basically stop, refresh and restart; and get a new class loader. Objects and classes from the previous class loader must not be referenced anymore, and that previous CL is supposed to be “discarded” and GC’d.

In our custom tool I was seeing that objects from “discarded” class loaders were still being referenced by other modules. However, when I used JHat (either embedded or standalone) to inspect the heap snapshots by performing queries like “select x from com.foo.TheClassOfTheReferencedObject” the result set listed only one object instance (from the running module) when I was supposed to get two instances (one loaded by the old class loader and other by the new one).

I thought my tracking code was falsely accusing the service object from the old bundle version. After patiently and manually (maybe “stupidly”) verifying each class loader instance, I found the two different class loaders that referred to the same bundle ID, and could also found the “lost” object.

After a few weeks I’ve tried to track the same problem with the heap inspection provided in the VisualVM. It worked like a charm! I could see all object instances of the same class name, no matter what class loader provided the object class. It does not have advanced queries like JHat, but in this case I only needed a filter to find the class instances that interest me.

It’s a pity. JHat has powerful queries to analyze heap snapshots, but it can’t deal clearly with the same class names loaded by different class loaders (i.e. different versions of the same class). VisualVM has much more limited power that JHat, but allows to see attribute values, referrers and referring trees just like JHat. In addition, VisualVM deals with no problem with classes carrying the same name but loaded by different class loaders, and that what’s more interesting for me, at least for now.

Wednesday, April 23, 2008

Scriptconsole4j: Embed a scripting console in your Java App.

Using scripting languages in Java became very easy. The JSR 223 standardizes the usage of scripting languages in the Java Platform; and Java 6 already ships with built-in support to JavaScript (Mozilla Rhino engine).

If you need to embed a multi-language enabled scripting “visual console” to your application you may try the scriptconsole4j.

I was developing a Java application where I needed to do some coding on the fly during runtime, change variable values, run snippets of code, etc. So, I’ve created a simple scripting console to use on that application. I don’t know if something like that already existed, but my code and its usage are really simple.

I’ve extracted the classes and made a few changes on it and created a separate reusable jar library (the scriptconsole4j). It is hosted at http://code.google.com/p/scriptconsole4j/

There are two ways to use it:

  • A JPanel with scripting functionality that can be embedded in another application (e.g. you can add a scripting window, or a scripting console to your app and access some of your application variables through the scripting window)
  • A standalone frame that embeds the above scripting console (e.g. you can practice the scripting language of your choice with it)

This scripting console provides a standard output variable, but allows variables from your own application to be available through the scripting console.
The combobox shows all available scripting engines on the running JVM. By default, Java 6 comes with JavaScript.

By doing the following as in the example, it is possible to add you custom(s) variable(s):
import scriptconsole4j.*;
...

JFrame frame = new JFrame("[Scriptconsole4j] Default Window");
//No textual description available. The console will just display the classname as info
ScriptContextVariable myObjectVar = new ScriptContextVariable(new MyObject(),"myobj","");
//The scripting panel can take several ScriptContextVariable as parameter
ScriptingPanel panel = new ScriptingPanel(myObjectVar);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.add(panel);
frame.setVisible(true);
You can add any variable that you want and use it from the scripting panel. In the above code we add an object of type MyObject that will be available in the console with the alias of "myobj". There is no big deal here, since the JSR 223 allows context objects. However, we wrap it and put some additional info so other can see what are the variables that we intentionally want to let available to the console, and hopefully some (optional) textual description of it.


Other JSR 223 compliant engines of existing scripting languages are available at http://scripting.java.net .The download on that site provides the JSR 223 engines but it is still necessary to make additional downloads to the scripting libraries themselves.

Several improvements still need to be done in the console (e.g. ability to load scripts, script embelisher, undo support), but this little panel brought a lot of flexibility for me during development time of my apps.

The first release can be downloaded here.

I hope you can give it a try to see if it helps you too.