|
Comments
|
Today's Top SOA Links
Enterprise JavaCaller: The Last Session Bean
A poweful and universal EJB
By: Michael Havey
Jan. 5, 2005 12:00 AM
Most Enterprise JavaBeans (EJBs) serve a definite purpose, performing a specific set of actions on behalf of client applications. The ubiquitous Bank Account bean, which supports basic account transactions such as withdrawal and deposit, appears in almost every J2EE tutorial. Students are persuaded that real-life EJBs, though more advanced, are as practical and particular as those developed in the classroom. This article presents an unusual stateful session bean called JavaCaller, whose interface is entirely general, providing client applications with the ability to run arbitrary Java code on the application server. Because of its generality, JavaCaller can be made to do anything that any other session bean can do; to use the language of computability theory, any problem that can be solved by a session bean can be solved by JavaCaller. What distinguishes JavaCaller from other session beans is that its execution of actions is completely controlled by client applications. Different clients can make JavaCaller do different things because the client manages the control flow. Supporting a simple reflection interface, JavaCaller exposes methods that let clients create objects and classes, invoke class or object methods, and get or set object fields, all on the server side. As Figure 1 shows, JavaCaller is like a robotic arm, controlled remotely by client applications to manipulate classes and objects in the application server's JVM. Not that the tutorials are wrong; the specificity of the typical EJB is a virtue. Lack of specificity implies lack of focus and gets flagged during design review; an EJB should do exactly what it is required to do. However, JavaCaller's purpose is atypical: it is a hook into the server JVM, or, alternatively, a shell that runs scripts and jobs on the server. It opens up the application server to users to the degree that operating system shells open up the operating system. True, application servers provide management consoles and open management APIs such as SNMP and JMX, but only for the administration of managed objects, such as applications and resources. The shell is an interface to all the nonmanaged objects too.
JavaCaller API JavaCaller can get or set static fields (getClassField(), setClassField()) and call static methods (callClassMethod()), as well as get and set object-level fields (setField(), getField()) and call object-level methods (callMethod()). JavaCaller can also instantiate a class (instantiate()), add a new class to JavaCaller's class loader (createClass()), and return to the client a serialized copy of an object (getObject()). JavaCaller stores object and class references in its object cache. This cache, which constitutes the client state of the bean, is empty when the client's session begins and builds up as the client uses objects and classes. JavaCaller is stateful because it manages an object cache for the client. The population of the cache is described in Table 1. In keeping with the notion of "remote control," the client never uses server objects directly, but has JavaCaller use them on its behalf. The client normally resides in a separate address space anyway, making direct manipulation impossible. JavaCaller's getObject() method returns to the client a serialized copy of a server object, which provides the client with a snapshot of the object's state and perhaps the ability to play with it locally. However, because the object is only a copy, nothing the client does with it has any server-side effect. If the client wants to perform successive operations on the same server-side object, it calls successive JavaCaller methods passing the same numeric object reference, representing an index to JavaCaller's object cache. Note: Objects maintained by JavaCaller need not be serializable, but getObject() works only for serializable objects. Most JavaCaller methods return either an integer or a Union. The integer is a cache reference identifier that the client can use to specify an object or class when invoking subsequent JavaCaller methods. The concept underlying the Union type comes from the "C" union type: it represents a value of one type selected from a set of possible types. In the context of JavaCaller, these types are:
The Union type is also used as an argument type in JavaCaller methods. In setField() and setClassField(), the client uses it to specify a new object or primitive value for the specified field. In callMethod(), callClassMethod(), and instantiate(), the client uses it to specify object or primitive argument values for the given method or constructor. In this case, the client also specifies the string name of the argument type (for example, "int" for a primitive integer type, "java.util.Date" for the Date object type). This is required because classes or objects can overload methods and constructors. Argument types are required to distinguish methods or constructors with the same name. The createClass() method allows the client to add a new class on the server side. The client passes a buffer of bytes, representing the contents of a Java class file on the client side. JavaCaller dynamically adds a new class on the server side based on the specified byte code and adds a reference to the class in its object class. The client can then manipulate the new class, or create instances of it and manipulate those instances.
Examples The main steps are as follows:
The second example shows how to write a Web service, called PourJavaOnServer, that loads and runs classes on the server. The Web service is written in WebLogic Workshop, a graphical Web service development tool from BEA. PourJavaOnServer has one method, runObject(), that does the following:
Reader Feedback: Page 1 of 1
Your Feedback
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week |
|||||||||||||||||||||||||||||||||