the cajo project
Free, simple, powerful: Transparent Distributed Computing
Frequently Asked Questions
This page will stand as a living document, based on the feedback of developers. In any project, a certain collection of questions are asked disproportionately often. These deserve their own space, as they have the highest statistical probability of being very helpful.
How can I ... ?
How can I determine my cajo.jar library release number?
How can I launch a generic proxy hosting JVM?
How can my container shut down all exported objects?
Can I ... ?
Can I forcibly disconnect a client?
Can I restrict my server only to local clients?
Can I run cajo over Secure Sockets Layer?
Can my application put proxies in an Applet sandbox?
Can I use the example's TileLayout manager?
Can my item have public methods that are only locally invokable?
Can I use null arguments in a remote method invocation?
Can I include cajo classes in a proprietary application JAR?
Can I tell if my method is being invoked remotely vs. locally?
Can I make my server accessible both inside and outside a NAT subnet?
Why is it ... ?
Why doesn't the example work in Appletviewer?
Why is there no package version number?
Why is the framework named cajo?
Why do the build scripts target JRE 1.2?
Why does each ItemServer create its own rmiregistry?
Why is cajo licensed under the GNU LGPL?
What is ... ?
What is a zedmob?
What is this crazy cajo coding style?
General
What if someone forks this code?
Does cajo pass objects by reference, or by value?
(Questions are numbered in the order posted)

1. Why doesn't the example work in Appletviewer? The CodebaseServer tells the browser to make the applet 100% of the width and height of its window. While this has been legal HTML since 1.0, the Appletviewer doesn't know what to make of it, as it has no window open when it connects to the server. If you really need to use Appletviewer, you'll have to edit CodebaseServer to use a fixed width and height value.

2. What if someone forks this code? A fork: i.e. a breakaway development, is something I would not like to see happen; as it could divide the community. In this type of project, there is so much more to be gained through cooperation. However, this is an essential freedom, and thus is permitted under the licence; to forever prevent technological lock-in.

3. What is a zedmob? A zedmob first off, is a contraction of the two words Zipped MarshalledObject. It is the standard mechanism for encapsulating remote item references, serialised objects, and item proxies; for transmission over the network, or storage on disc. A zedmob is particularly helpful in the case of proxies, as items are free to pass a proxy zedmob between each other, and successfully extract the proxy. This is because its codebase annotation stays intact. In other words; once a proxy is extracted from a zedmob, it cannot be passed to another item, unless that item already has the codebase for the proxy; since the codebase location information is lost. A zedmob is typically written to a stream, and read from a stream, using the static zedmob methods of the Remote class, and typically has the file extension .zmob for identification.

4. Can I forcibly disconnect a client? The answer is yes, but it will take a little effort. In RMI it is possible to terminate an object's remoteness, but it will mean for all remote VMs connected to remoted instance. If you want to disconnect a specific client, you need to uniquely remote the object reference given to that client, using the Remote class. Then you can invoke the remote wrapper's unexport(true) method. This will forcibly terminate all remote connections to that wrapper, even to clients currently attempting to execute methods, and report if any remote invocations were in progress (or pending) on it.

5. Can I restrict my server only to local clients? This is an intriguing question; fortunately the answer is yes! To make the example server solely accessible locally, use the following startup:

     java -jar server.jar 1111 2222 localhost localhost

The two port numbers, for http and rmiregistry service respectively, can be anything, even zero, meaning chosen at runtime. What the localhost arguments will do is require the client to connect specifically to the host name localhost, or to 127.0.0.1. This effectively restricts access to this server only to clients running locally on the machine. For example:

     java -jar client.jar //localhost:2222/   -or-   //127.0.0.1:2222/

What this means internally, is for the server to do something like the following:

     Remote.config("localhost", 2222, null, 0);

6. What is this crazy cajo coding style? I never thought this would become a FAQ, but apparently it has. OK, over the years I've become quite tolerant of allowing each developer his own formatting style. (I know this freedom drives some developers crazy!) Basically, I find it becomes easy to see who wrote a section; just by its formatting. In my case, my primary motivation is: I hate whitespace! Other developers seem to love the stuff. I think this stems from my early years, developing large applications in assembly language. There each line did so little, that to get an overview of how a subroutine (prehistoric for method) worked, you needed to see a lot of lines. In Computer Science there is a concept called Locality of Reference. Basically it means how many adjacent resources are involved in any particular operation. I believe as developers improve, their locality of reference increases. I hear both noobs, and soi-disant industry experts loudly proclaim that no method should be longer than 9 to 12 lines: Rubbish! Were that reasonable, no books should be written above the Grade 5 reading level. As you probably know, I have methods of 100 lines or more; but precisely as many as needed, no less, and definitely no more! The same implementation, so-called "properly" decomposed, would require likely an order of magnitude more lines, introduce much greater chance for error, and incur pointless stack consumption, all of which seriously add up. Even when I print code, it is always 4 pages per sheet, ordered top to bottom. I do however heartily recommend, and try to follow, Sun Microsystems' code conventions for the Java programming language.

7. Can I run cajo over Secure Sockets Layer? Yes, of course. If you need to support pre JSE 5 clients, have a look here; you can copy the sample zip file, and replace the two socket factories in Remote. If all JVMs involved are certain to be using JSE 5 or higher; SSL/TLS socket factories are included in the runtime. Here is a very excellent example of this whole process. *However, a much more important question is; Would you want to? Please have a look at the following project discussion thread.

8. Why is there no package version number? This is an excellent question! In the cajo project, a release version number is irrelevant. This is due to the philosophy of its design. This project evolves continuously, but always in a consistently forward compatible manner. Why? Because it is important to remember that in this framework, one will both receive, and use, objects at varying levels of development in the project's timeline. This is not unlike natural language; for example, one does not ask: "Might we converse, at v.1.2.7.a," rather, one interacts, at the highest common ground possible. This project is fundamentally focused on communication, between virtual machines, potentially separated in both space and time... Woah dude; What hast thou spoketh?

9. Can my application put proxies in an Applet sandbox? Wow, what an important question! I am sorry the answer to this was not perfectly clear sooner: Of course, it is Yes! This is easily done. When starting up your application, use the following two -D arugments:
java -jar -Djava.security.manager -Djava.security.policy=policyURL myApp.jar
The first -D argument puts the entire VM in an applet sandbox. Then, if you need your host code to be free of these restrictions, the second -D argument is used. It specifies a policy file, which could look something like this:
grant codeBase "file:${java.class.path}" {
   permission java.security.AllPermission;
};
This file gives full permissions, but only to classes that were loaded from your local filesystem.

10. Why is the framework named cajo? This is a fair question. I guess the best answer is; it had to be named something. It also seemed like; all the good names were taken! I certainly didn't want to get things rolling, only to fall into some sort of trademark dispute. Instead I opted for a risky personal association. I believed in this framework so strongly: I gave it my first, and only 'net handle; dating back to 1979. I essentially put my entire online reputation at stake. The name was christened by my high school sysadmin, as a username on an old System/360. He took the first two letters of a 'computer club' member's last name, and concatenated it with the first two of the first. I then went on to use it at University, and ever since. I hope he never found out the full extent; but he was the first person to let me really experiment with 'big-iron', and the 'then-called' ARPANET... Thank-you cuto! :-)

11. Can I use the example's TileLayout manager? Certainly, I am glad people like it! I have yet to see a frame that I could not layout in a single panel. For the past 5 years or so, it has been the only LayoutManager I have used. For some really special screens, I have had many developers ask: How did you lay that out? This is my secret; it is extremely fast, and flexible, and with its component overlaying capability, it is unmached by any of the standard layout managers. A link to the fully documented version can be found here. Definitely run javadoc on it; while short, it is more than half comments, which are very much needed. Have fun with it!

12. Does cajo pass objects by reference, or by value? To provide the ultimate in flexibility, the answer is: Either! The Java language only allows passing objects by reference; meaning that when you provide an object to a method as an argument, any changes the method makes to that object are actually changes to your object. In cajo an object is passed by reference to a remote Virtual Machine, by wrapping it in a Remote object. However unlike Java, and more like C++, cajo also allows you to pass an object by value; meaning the receiving method gets an exact copy of the object, and anything it does to it, has no affect on your object. This is accomplished very simply, by passing the object without wrapping it in a Remote wrapper. (Note: If the client receiving this object does not have the class file for this object, then you will need to run something like a CodebaseServer to provide it.)

13. Why do the build scripts target JRE 1.2? By using the lowest practical target JRE, the cajo project ensures compatibility with all higher versions. Note that this in no way restricts application code from targeting whatever JRE target is needed. In general, the lower the JRE version a Java application can successfuly target; the more JREs, and subsequently larger installed base, on which it can run.

14. Can my item have public methods that are only locally invokable? Yes. This brings up a very important feature in the design of of cajo transparent remote invocation. If an object implements the Invoke interface, any invocation through Remote.invoke will automatically be passed to its interface, rather than being performed on its public methods directly. This feature makes things like MonitorItem and AuditorItem possible. It can also allow your item to have public methods which can be invoked only by objects within the same Virtual Machine. You would simply implement Invoke, and manually route calls only to those methods you wish to make remotely callable. Normally this can (and should) be avoided completely, by designing an object expressly for remote invocation from the outset. However this is sometimes helpful, when remoting a derived object, say one that extends javax.swing.JFrame for example.

Note: This is what also allows wrappers to be chainable; to create things liked monitored audited objects, and audited monitored objects. (two distinctly different things by the way)

15. Why is cajo licensed under the GNU LGPL? The GNU LGPL gives you a very important guarantee. The way cajo works, to enable cooperation between both free and proprietary applications, can never be made proprietary itself. If someone were to modify the cajo semantics, or its operation; the licence requires full disclosure of these modifications, and complete source code, to anyone receiving the modified library. Aside from the GNU GPL, which does the same, but would prohibit use in proprietary applications; no other licence (that I know) provides you this crucial guarantee.

16. Why does each ItemServer create its own rmiregistry? While it would perhaps be conceptually simpler to run a central rmiregistry in its own JVM; this would represent a very unsatisfactory single point of failure, for the entire server physical machine. The additional load of carrying an individual rmiregistry within each server JVM is quite small, but the added stability it buys is very large. Besides, if you really want to use a central rmiregistry; you can still do that too!

17. Can I use null arguments in a remote method invocation? Yes. However: as mentioned in the overview; with remote method invocations, typechecking has to move from compiletime, to runtime. This creates a very important detail to keep in mind, when it comes to overloaded methods. With a local object; when passing null arguments makes the selection of overloaded methods ambiguous, the compiler demands specification. For example: x.doit((String)null); vs. x.doIt((LinkedList)null);. Unfortunately, in the remote case, an ambiguous overloaded method will simply be selected indeterminately. So use null arguments, but with care on methods that are overloaded.

18. Can I include cajo classes in a proprietary application JAR? Yes. Essentially, JAR is a standard file format. Your proprietary licence applies to your classes, and the GNU LGPL applies to the cajo classes. Your classes may even be obfuscated, however the cajo classes may not. Most importantly; end users must be able to update the cajo classes in the JAR, and the application must still operate normally. Normally means that the application will not refuse to run, nor change its feature set, by detecting changed cajo classes.

19. Can I tell if my method is being invoked remotely vs. locally? Yes. Sometimes a server may want to process things differently when the client is remote, rather than local. Fortunately this is extremely easy to do, as the following code snippet illustrates:
    try {
        java.rmi.server.RemoteServer.getClientHost();
        // the method invocation is remote...
    } catch(java.rmi.server.ServerNotActiveException x) {
        // the method invocation is local...
    }
Put your remote specific functionality in the try block, and your local specific stuff in the catch. The common functionality can be placed above and below the test, or even in a finally block.

This is the server side corollary to the client side test, for object remoteness vs. locality:
    if (object instanceof gnu.cajo.invoke.RemoteInvoke) {
        // the object is remote...
    } else {
        // the object is local...
    }
This is used in cases where the client wishes to behave differently, when the object is remote vs. local.

20. Can I make my server accessible both inside and outside a NAT subnet? This is a great question because the answer is yes, but it requires a sophisticated, yet surprisingly simple technique. First create your server so it is accessible inside the NAT subnet, for example:

  Remote.config(192.168.0.101, 1234, null, 0);

Now for the interesting part; create a simple 'wrapper' server, which is accessible from outside the subnet. It would look something like this:
   public static void main(String args[]) throws Exception {
      Remote.config(192.168.0.101, 1198, outsideIP, 1198);
      Object o = Remote.getItem("//192.168.0.101:1234/");
      ItemServer.bind(o, "main");
   }
In remoting a an already remote object, the wrapper will automatically forward all of the external clients' invocations to the local object. The wrapper server need not even be running on the same physical machine as the local server. You could even place a MonitorItem on the object for example, to get a detailed log of how external clients are using the object.

Update: In addition to the interesting approach outlined above, starting with release 1.88 there is yet another solution. A new two argument constructor to Remote has been added. You can use this to specify the NAT external address on which you would like to remote your object, while using the single argument Remote constructor to export NAT internal references. This allows both to be done from within the same JVM.

21. How can I determine my cajo.jar library release number? Starting with release 1.83, this is now easily done. The cajo.jar has become executable! In a console window simply type:

    java -jar cajo.jar    

the release number, and date, will be output.

22. How can I launch a generic proxy hosting JVM? Fortunately, since these are so valuable for clustered application development, the project supports them implicitly. Simply type:
java -cp cajo.jar -Djava.security.policy=host.policy gnu.cajo.utils.ItemServer gnu.cajo.utils.BaseItem
where the host security policy looks something like:
     grant { // allow proxies to make network connections
        permission java.net.SocketPermission "*", "connect, accept, resolve";
     };
This will launch a generic proxy host, bound under the name "main", operating on a port selected by your OS. To install a proxy, invoke its installProxy method. It will return a remote reference to the proxy provided as an argument, on which you can communicate with it, synchronously. If you wish to use specific ports, or route across NAT, have a look at the command line arguments accepted.

23. How can my container shut down all exported objects? The static shutdown() method of the gnu.cajo.invoke.Remote class will forcibly disconnect all clients currently connected to exported objects. The objects can be made remotely accessible again, by re-remoting their references.


Everybody seems to ask these questions.
© 2004 John Catherino, GNU FDL