Resources.
Home
Press Releases
ePortal
Contact us

Products.
Live Samples
Download
Buy
Support
News
FAQ

Documentation.
Overview
How it works
Installation
Configuration
Testing
References

Resources.
Forums
Customers

How it works.


Architecture

Callbacks, JMS, asynchronous communication

Communication



 

Architecture
JProxy allows manipulate Java objects located on remote host (server). The classes that represent such objects can be any Java classes. They do not have to be serializable. The only requirement is that the class has to implement an interface.

JProxy can dynamically create on remote host stub class that implements and delegates any number of requested interfaces. The stub class then can be used to create stub instance to invoke methods on certain remote objects that implement same set of interfaces.

JProxy runtime can create remotely object instance of any class and, if requested, create stub for any of interfaces of object class.

All references to server objects and theirs stub instances are stored on JProxy Sever in Object Hash. It allows managing lifetime of the objects. Each such server object and stub reference is wrapped in special object that attaches some properties such as Object's Time-to-Live (TTL), Object ID, Session ID, etc. There is a special Timeout Thread on JProxy Server that periodically checks object expiration time.

Usually JProxy Client cannot explicitly send signal to destroy certain server object: the client can be just killed, or connection can be suddenly broken. In this situation Object TTL expiration is reliable indication of time to remove object reference from JProxy Server.

Just to make clearer: JProxy does not destroy server objects by itself it just frees objects reference that allows utilizing JVM Garbage Collector. For instance JProxy Server keeps in Object Hash EJB stub, and the hash item is expired. JProxy Server does not call EJB "remove" method, it just delete reference to the EJB object from Object Hash.

There is also other way to control server objects reference lifetime for asynchronous objects. The method is based on validating client polling requests suspended by JProxy Server.

So the described above JProxy functionality is very similar to such Distributed Object Systems (DOS) as CORBA or RMI.
The functionality does not make JProxy very unique.
The real idea of JProxy is that a set of customizable logic automates implicit stub creation and stub delivery.
The logic input is object request Java parameters, Java result returned and method stack of methods invoked on the stub.

When method invoked on server object returns result to JProxy Server the returned Java object is serialized with JProxy serializer before passing it to the network. The serializer checks types of serialized objects if its instance of one from the list of interfaces specified in customizable property. If match found then JProxy Runtime substitute Java objects to generate JProxy stubs. Any interfaces that implement one of interfaces enumerated in the property are considered as remote. So, for instance, if class implements interface ICustomer which implements java.rmi.Remote and Remote is mentioned in the property then ICustomer considered as remote interface.

A reverse object substitution performed during object deserialization.

During object analysis JProxy Runtime also gets specifics of certain J2EE API by examining objects and method invocation stacks on both client and server. It helps, for instance, JProxy to recognize callback objects passing as parameters.

The result of such object substitution is creation of thin presentation of server objects regardless of its nature.
The server object can be any remote object: RMI, CORBA, SOAP or EJB. Or it can be JMS topic, JNDI context or even local object. JProxy can bring any server functionality to the client. Only one requirement has to be satisfied: the object functionality must be described in an interface. So, for instance, JProxy can remote JNDI InitialContext because its functionality is specified in Context interface.

Because of such flexibility JProxy simplifies callback object functionality. With JProxy any local interface class instance can be passed to remote call. Developer does not need to wrap object functionality in special classes and then export object. Any non-remote aware objects can be become a server objects and receive remote calls.

By default JProxy creates stubs for any instances of classes implementing java.rmi.Remote and org.omg.CORBA.Object and some other J2EE specific objects. The list can be customized. New user interfaces can be included. Interfaces that implement one of such interfaces become remote interfaces. And during runtime JProxy will automatically recognize such objects and make them remotely accessible.

There are two properties in JProxy used to specify such interface list. One is for synchronous calls and other for asynchronous. A property for synchronous interfaces is used during analyzing of result object from method invocation on server objects. A property for asynchronous (or callback) property is used during analyzing of method arguments for method invocation or construct request.

If same interface is mentioned in both properties then there is no matter if the object was found in result or in method argument list.

Below is more detailed explanation of JProxy functionality.

The JProxy communication is initiated by obtaining initial stub for server object. In this way it is similar to most of Distributed Object Systems. Usually it is made in JNDI way (for EJB, RMI or JMS) by obtaining naming initial context. For instance:

env.put(Context.PROVIDER_URL, serverUrl);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.jproxy.proxy.NamingContextFactory");
Context context = new InitialContext(env);

com.jproxy.proxy.NamingContextFactory - is a JProxy JNDI SPI implementation that allows implicitly activate JProxy communication.

During construction of InitialContext JProxy Client request JProxy Server to create instance of InitialContext on the server. JProxy creates instance of InitialContext locally and passes serializer.
And because the JProxy property for synchronous interfaces contains "javax.naming.Context" the serializer replaces object with class javax.naming.InitialContext to stub that implements javax.naming.Context.

From this point client gets initial JProxy stub (reference). And all subsequently requested by "lookup" remote objects will be replaced to JProxy stubs.

By using JProxy you do not need presence of any provider specific classes on the client. And it does not matter what API or Application Servers are utilized. With exactly same client you can connect to JBoss or WebLogic. There are no needs in different libraries to work with EJB, JMS or CORBA. Just one JProxy Client is used for all varieties of Java technologies and server providers.

JProxy Client runtime is just about 100Kbytes. So small footprint and ability to run in standard sand-box security model opens great potential to use J2EE or other Java technologies from Web Browsers as a thin client.

Callbacks, JMS, asynchronous communication
A callback can be set by passing in remote call the callback receiver object as an argument. Any number of arguments can be used. JProxy Client Runtime recognizes callbacks from analyzing method arguments passed to JProxy stub. Each argument class is compared with classes enumerated in property "com.jproxy.proxy.callback.classes"
Default property value - java.rmi.Remote, javax.jms.MessageListener, javax.jms.ExceptionListener, org.omg.CORBA.Object
It is a list of interfaces. The Callback Object could be any object that is instance of the class implementing either interface from the list.

If matched argument is found then JProxy replaces the argument to stub descriptor and performs remote call as regular JProxy call.

At same time JProxy Client makes remote request to create HttpCallbackServer remote object on JProxy Server.
HttpCallbackServer is similar to JMS Queue. The object has 2 main methods: "push" for sender and ?pop? for receiver.

JProxy Client also starts thread that calls method "pop". When method is called JProxy Client wait for return from the method. But moment of return from the method is controlled by HttpCallbackServer running on JProxy Server. If sender calls "push" then "pop" can be unblocked. Method "pop" cannot be blocked for long time in order to support HTTP timeouts, no more than several minutes. And HttpCallbackServer periodically allows return from "pop" without any result. After return from ?pop? client immediately calls the method again.

JProxy Server during deserialization replaces stub descriptors to special callback stubs and then invokes call on "real" object. So when in JMS case "setMessageListener(listener)" invoked, JMS Server will receive JProxy callback stub in place of "listener" argument.

JProxy Callbacks implementation that JProxy Client Runtime is very similar to Server Runtime: it also has ability to host remote objects, it has GC and session support. It is very similar to CORBA with its ORB or RMI. But to keep client small and able to work with sand-box security mode, JProxy Runtime misses some functionality.

A communication with Client Runtime is possible only asynchronously via CallbackTunnel because luck of Web-container on the client. It is also impossible to utilize client-side HTTP server because of firewall issues. And all reason why HTTP tunneling is used is to go through firewalls.

During setting of callback, client treats actual callback listener (receiver) as remote object (or servant in CORBA). Client Runtime cannot generate dynamically stub because of lack of functionality and security and this JProxy Server is doing it for client. Client just sends stub request.

HttpCallbackServer is destroyed if receiver is not active even if sender is still running.

During collecting of the object JMSException is thrown to the sender.

There are other callback related properties:

com.jproxy.proxy.callback.validate.receiver
It is a server property. Default - false.
If set to "true" HttpCallbackServer returns from "push" requested by the sender only if callback receiver is active. During max time (com.jproxy.proxy.callback.receiver.timeout) sender waits till receiver invoke "pop" call. Only if sender finds out that callback receiver is alive it will leave "push".
If "false" receiver validation is based only on delay since last "pop" request from the client
The delay or timeout is specified by property below:

com.jproxy.proxy.callback.receiver.timeout
It is a server property. Default - 30000 (30 seconds).

Just to remind that since JProxy 2.0 all properties can be set outside of proxyservlet.war or proxyclient.jar: in $JAVA_HOME/lib/proxy.properties

In order to set javax.jms.ExceptionListener the class name has to be present in server property: com.jproxy.proxy.callback.classes.

If application server and JMS server (JBoss) was restarted it will not be able to restore connection with callback clients. The only way to restore connection is to do it explicitly from the client when it discovers that connection is down. The server cannot restore connection with clients after start up because all client-server communication is session-based, also each JProxy remote object has unique time-based ID.

Communication
Currently JProxy utilizes HTTP/HTTPS for its communication with remote objects. It makes JProxy very usable as generic HTTP Tunneling for different J2EE APIs and server providers.

JProxy provides timeout functionality for HTTP communication.
According to Java API, java.net.URLConnection does not expose the underlying socket. As result, you cannot explicitly set timeout for the socket.
Timeout capabilities in JProxy implemented in two ways:
First - based on overriding sun.net.www.protocol.http.HttpURLConnection, sun.net.www.protocol.http.Handler and sun.net.www.http.HttpClient.
Second - using threads. Calling thread executes each remote call in separate communication thread. Then calling thread waits for communication thread. And if communication thread is still busy calling thread discards it and resume working: starts new communication thread or throws exception. Later on discarder communication threads will timeout and recycled by JVM Garbage Collector.

JProxy automatically selects which one must be used based on the Java Security Model. If an applet does not have enough security privileges it selects threading to support timeouts.
You may set default timeout in proxy.properties file in proxyclient.jar, or specify different timeout for each remote object at runtime.

JProxy Runtime automatically attempts to avoid networking if it detects that remote objects located in same instance of JVM. It greatly increases performance.

During all networking JProxy runtime measures performance of communication and if detected performance is lower then specified in threshold property (com.jproxy.proxy.network.performance.threshold) then JProxy uses data compression for current call. Later on if network resumes working faster compression dynamically is turned off.

JProxy Tunnel supports simple failover mechanism.
Whenever a connection link is broken and from within your Applet you make a remote call on and EJB interface JProxy Tunnel client runtime will detect that there has been a failure and will try to reestablish the connection up to the number of times that you specify in JProxy Tunnel client runtime configuration file located in proxyclient.jar/com/jproxy/proxy/proxy.properties.
If it fails to do so, then JProxy tries to switch to a different App server using comma separated values of com.jproxy.proxy.provider.url client property. The switching is possible only during obtaining JNDI InitialContext and not after.
JProxy Tunnel tries to reestablish the connection to your servers with no coding involved on your part.


Copyright ©2001-2005, JProxy, LLC. Dec 1, 2008