|
 |
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.
|
|