Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Letters to the Editor

  • Print
  • Feedback

"Repair Invalid Cached Services in the Service Locator Pattern"
Paulo Caroli

The Verified Service Locator Pattern doesn't eliminate invalid services



Paulo,

My application could call VerifiedServiceLocator.lookUp(), which could return an invalid (that is, expired) service. Imagine this sequence:

  1. At 10:00, checkService() is called—it determines the service is available
  2. At 10:01, the service becomes unavailable (for whatever reason), and the cached service is now no longer valid
  3. At 10:03, my application calls VerifiedServiceLocator.lookUp(), which returns the expired cached service


So we're right back where we started. The Verified Service Locator (VSL) pattern may alleviate the problem of expired cached entries returned from lookUp() by returning them less frequently, but it does not seem to eliminate the problem completely.

Am I missing something here?

Tony

Tony, You didn't miss anything. Your scenario really shows a situation where the client would get an invalid cached service. If a cached service becomes invalid, the service also remains invalid for a short time period, and we can't do much else besides wait for recovery. Usually, the server handles the service recovery. The key point is how often to check for the cached services' validity. In my last project environment, it took about three minutes to recognize a down server and restart it. That means our application would have problems for at least three minutes, and we could do nothing about it in our code. We set the verification frequency in the Verified Service Locator for two minutes. That way, in the worst scenario, the application could reach the invalid service for, at most, five minutes. You can reduce the verification frequency to almost zero seconds, in which case, the application could reach the invalid service for three minutes at most, but it would be constantly checking the cached services' validity. For an application using the Verified Service Locator, the problem would exist only for at most these five minutes (service recovery time plus verification frequency); for an application not using it, the problem would remain until the application restarts. The perfect alternative would be a server that kept all services always valid; Verified Service Locator gives a server-independent alternative to reduce the problem. Paulo Caroli


How do you handle an invalid service on the client side?



Paulo,

I agree that the Verified Service Locator pattern reduces the problem of invalid services. When the server shuts down, eventually no more invalid services will return to clients, which improves the original pattern.

However, the chance still exists that an invalid service will return. How do you handle that on the client side? You do not want client code to check for a service's validity, but at the same time, a service may be invalid (however small the chance). The client must handle that eventuality.

Ronald

Ronald, I agree with you. The solution reduces the problem, but doesn't reach 100 percent robustness. I would consider treating the exception in the client code when it happens. However, I don't like that the code replicates for each client or that the client must handle the problem. Some EJB (Enterprise JavaBean) servers have specific solutions to avoid the problem. I heard WebLogic provides a clustered Home interface that would redirect EJB Homes internally in case one container is down. Paulo Caroli



Paulo,

Unfortunately the VSL pattern can't guarantee 100 percent robustness, but it does improve the previous situation.

In WebLogic, you can replace your home stubs with cluster-aware home stubs that provide load-balancing and failover support. I've never used this myself, but read it once in the documentation.

Ronald



"Empower RMI with TRMI"
Guy Gur-Ari

Can Transparent Remote Method Invocation help with serializable objects?



Guy,

We recently made something similar to the TRMI (Transparent Remote Method Invocation) API by using proxies from Reflection. The idea behind our implementation was similar.

We had one problem with serializable objects when calling remote objects' methods. What do you do when it is assumed that the method should modify its serializable parameter? Does TRMI provide such possibility? Example:

interface SimpleRemote {
  void updateProperties(Properties props) {
//...
  }
}


The SimpleRemote implementation is assumed to be on the server side. The updateProperties() method should modify the props object when it is called from the client side. This is normal behavior for local classes. Can you perform the same trick with TRMI?

Maxim

Maxim, I can't think of a transparent way to do what you're asking. Making the serialized object's changes appear in the original object requires intimate knowledge of a specific class's construction. However, I have an idea for a nontransparent approach. You can declare a new interface:
interface CopyBackSerializable extends Serializable {
   public void copyBack(CopyBackSerializable copyObj);
}
copyBack() will re-initialize the instance with the copyObj, and classes that need to be copied back to the caller will implement it instead of Serializable. To send the changed copy from the server to the caller, TRMI can recognize when a parameter is CopyBackSerializable and when the method call ends. Then TRMI can call copyBack() on the original object to make the remote changes appear in it. Implementing this solution isn't trivial, and it also seems quite esoteric. Guy Gur-Ari


Tips 'N Tricks
"Java Tip 127: See JAR Run"
Shawn Silverman

How does JAR work with third-party libraries?



Shawn,

Great article, but it doesn't address an application that uses additional third-party libraries already in a .jar file. I've tried in vain to add the kunststoff.jar into the app's JAR and then modify Class-Path to include kunststoff.jar.

I can't seem to get it to work. java -jar runs the app, but still reports a missing KunstoffLookAndFeel class (which is in the kunststoff.jar, of course, and runs nicely from my IDE, where it is in the classpath).

Tim

Tim, The Class-Path attribute specifies additional paths or JARs from which to load classes not found in the JAR or the VM's default classpath. Relative URLs are used, and each URL is referenced relative to the JAR's code base. In plain English, that means that if you specify a JAR here, the VM will look for it in the same place as the first JAR (and not inside the first JAR). For example, say you type java -jar myjar.jar, and a manifest is inside myjar.jar containing a Class-Path reference to an extras.jar:
Class-Path: extras.jar
Suppose all of a sudden, the VM needs access to a class inside extras.jar. A file called extras.jar must be in the same directory as myjar.jar. If it is, the VM can load classes from this new archive. If it is not, the class cannot load. Placing extras.jar inside myjar.jar is the same as placing it beneath myjar.jar, and not at the same place or same codebase. For more details about this attribute, see: http://java.sun.com/j2se/1.3/docs/guide/extensions/spec.html Shawn Silverman


Shawn,



After researching a bit more, the clarification you give makes good sense in explaining the Class-Path header. However, the tidbit still missing is specifically how to access classes inside extra.jar if the JAR is indeed placed inside myjar.jar?

Again, after a bit more research, it would appear that for Java Web Server (JWS), the solution is to have only myapp.jar contain my app-specific classes, then place additional libraries on the Web server, and load them as additional JAR resources.

Perhaps like so:

     <resources
       <j2se version="1.2+"/
       <jar href="myapp.jar"/
       <jar href="commonlibs/extras.jar"/
     </resources


From various documents at Sun Microsystems, it seems there should be some way to further specify the commonlibs directory absolutely (that is, not relative to myapp codebase) so that the extras.jar could be shared/cached between multiple jws instances.

Tim

Tim, As for your first question of accessing classes inside a JAR inside another JAR: You could use getResource("extras.jar"), which would return a URL pointing to that file inside myjar.jar. Then, you could use URLClassLoader to get the classes from inside this URL. This method, however, is not efficient. You probably want something like a .war file (Web archive), which can contain multiple items such as classes and libraries. As a starting point, look in the Servlet 2.2 or 2.3 specifications, under "Web Applications." WARs, however, are not runnable, as JARs are. A server that properly uses WARs will look in the correct places for any additional JARs. As for the relative paths, I suppose it is up to the server to share loaded libraries and be clever enough to distribute them properly among different instances. A comment in the Extension Mechanism Architecture I referred you to mentions that absolute paths in the Class-Path manifest attribute are relative for security reasons, and that absolute paths may be supported in the future. Shawn Silverman


  • Print
  • Feedback
What is Tech Briefcase?
TechBriefcase is a new, free service where IT Professionals can Search, Store and Share IT white papers and content like this. Learn more
Bookmark content
Speed up your research efforts with content across the web.
Search and Store
Find the white papers you need. Create folders for any topic.
View Anywhere
Open your briefcase on your iPhone, tablet or desktop. Share with colleagues.
Don't have an account yet?

Resources