| D:\DEV\PROJECTS\Harbor_Tests\src\harbor\test\testGettingRemoteClasses.java |
/* * testClassLoading.java */ package harbor.test; import java.lang.NoClassDefFoundError; import harbor.interfaces.*; import kewlstuff.harbor.client.Vessel; /** * * @author Johnny Kewl * TEST 1 * This test GETS classes from a remote harbor and runs them on the local machine. */ public class testGettingRemoteClasses { private Vessel vessel = null; /** Creates a new instance */ public testGettingRemoteClasses() { String harborUrl = "http://localhost:8080/harbor/service"; //location of container harbor vessel = new Vessel(harborUrl); //get a vessel from the harbor vessel.verboseVessel(true);// watch the class loading process in system.out, for debugging } /** Gets a remote class and runs it */ public void runTest(){ Class msgTest = vessel.getRemoteClass("harbor.classContainer.MsgTest");//load a class from the harbor if(msgTest != null){// if class is null check the url and make sure tomcat is running I_MsgTest i_MsgTest = (I_MsgTest)vessel.newInst(msgTest);//can have many instances of a single class (its just like new) try{//run a function System.out.print(i_MsgTest.getTheMsg() + "\n"); }catch(NoClassDefFoundError e){System.out.print("NoClassDefFoundError normally because DEPENDENT class not found " + e.getMessage()); return;} } } } /* Notes: * GETS... means the class bytes are read from the remote server, and the class is loaded * locally. So other than the delivery of the class to this local client, the * server does no work. Because it then sits in your client side classloader, any * further use of the class, does not disturb the server at all. * Its a fantastic way to deliver applications, or parts of applications to a remote * client... and one can do it incrementally. For example you can do just enough to * quickly get the client GUI running, and only if a class is needed, is it loaded * from the server. The client does not notice big downloads, and the important * thing to understand is that once that class is loaded, its as fast as if the * application had been installed on the machine. * * Its the best of both worlds, clients tend to be overpowered, and typical application * servers burdened trying to run everything, this allows one to still control the code * but not run it all on the application server. * * And to really blow your sox off, you will see that you can use inter-dependent classes * between client and server. So for example you can take your whole POJO application, * drop it into the server, and then decide to run one class on the client, and the other * (in the same application) on the server. Even though one class in your application * is now actually running 2000km away from the other class in your application, and they * depend on each other... the software will work as a single application. * Will smart design, a typical organization will never need a huge application * server cluster. Incidentally, because one can cluster Tomcat behind Apache JK, it means * that naturally you can cluster Harbor, however this has very little to do with load, because * one can simply run many Tomcats with Harbors as well, clustering in the Harbor context is * more about redundancy, ie if a machine breaks, the app keeps running. * * Some technical comments.... * If any of the supporting dependent classes can be found on the local system they will * be loaded locally. * For example MsgTest uses the class Msg... so when you (getRemoteClass) MsgTest, the system * will try get msgTest AND Msg which in most cases is what you want. * BUT if Msg is LOCAL, it wont come from the remote system. * Maybe you want that, maybe not... it simply gives you even more control over how you * want to deliver classes. For example, some can be on the installation CD, some can be on * the server but run locally, and some can be on the server and run remotely. * * NB - Understand that classes in the harbor repository should NOT be in the Java Class Path * Its an independent container outside of your PCs containment. To install a normal * POJO library jar, and its dependencies, you just drop them into the repository folder * of the server... thats it. You do not put them in the system class path. * * Now other things also happen... Indirectly MsgTest is also an Object, so this will * be loaded from the local system because its a java class, thats how it should be. * * BUT NB NB.. if the system cant find the I_MsgTest INTERFACE locally it will try get * it from the remote system... THIS IS BAD. * If it does load the interface remotely, the code will crash and behave badly. * You will get weird ClassCastException messages on perfectly good code. * The reason for this is that Object comes from the local system and the interface * depends on it, and if they come from different systems, they dont see each other. * So REMEMBER... the INTERFACES you cast to MUST be on the LOCAL system. * Its actually not a big problem because when you develop in your IDE, for example * look at the code above, you need to have the Interface in the local class path of * your application, anyway. * However if for example you have your interfaces in another client side library * and you forget to include that with your client side application, then you will * get this strange error. * While you developing you can use the vessel.verboseVessel(true) utility, and if you * see the interfaces coming from the server... put it in the client. * * In normal programming people tend to name the interface MyThing, and the class * MyThingImpl, and classes without interfaces MyThing... in all the examples we * name them I_Mything... so there is never any doubt which is interface and which is * class... they must not come from the server, here is an example of the test output * with the above code running.... * * You should see this is your debug screen (System.out) Class found on local system harbor.interfaces.I_MsgTest Class found on local system java.lang.Object Class loaded from remote system harbor.classContainer.MsgTest Class loaded from remote system harbor.classContainer.Msg * * Very easy to forget that code is actually sitting at head office 2000 km * away. * * When you write your code in your dev environment... * This I_MsgTest i_MsgTest = (I_MsgTest)vessel.newInst(msgTest); * becomes I_MsgTest i_MsgTest = (I_MsgTest) new MsgTest; * * The code on the server is EXACTLY the same as it would be if it was just a * library used by a NORMAL POJO (Plain Old Java) application. * * EXACTLY the same... harbor is a pojo container, the idea is you * write normal code and then if you feel like it, drop your library modules * into the container and run them from the other side of the world. * Thats why you dont develop in the container... running code remotely can be an * after-thought... or conversely taking the code out of the container and testing * it stand-alone.... is just as easy. */