REFLEX RComponent DEMO ====================== NOTE - To run this demo you must have installed the Java API for XML Parsing available from http://java.sun.com/xml and also be running JDK1.3 (or later). Steps to compile the RComponent demo source ------------------------------------------- 1) Open the directory containing this file and type "javac *.java" in a command-prompt window 2) Compile the EJB wrapper by typing "compileEJB" in a command-prompt window 3) Compile the RMI stubs using the command "rmicc", then "rmic NotificationListener". 4) Rebuild the JAR library by running the file "jar_it". NOTE - If you are running the RComponent on a different host and the driver program on localhost, then change line 18 of "driver.java" to reflect the hostname of the machine where the RComponent is located. Steps to run the basic RComponent demo -------------------------------------- 1) Open 3 command prompt windows. 2) In each of the command-prompts go to the REFLEX demo directory. 3) In the first window type "rmiregistry" to start the rmi naming service. 4) In the second window type "daemon" to start the RMI activation daemon. 5) In the third window type "register1" to register the component for remote activation 6) In the third window type "run -v". The -v option checks that the components are correctly registered with the required interfaces before starting the application. 7) You should see the client activate the remote component. Output Description ------------------ On the initial run of the driver we inspect the component registry to determine services provided at the localhost. Next we select the service for the component called "TestComponent". Now we go on to exercise the component using both its metainterface and its provided interfaces. You should see the component introspect its methods provided by the component's external public interfaces. After this the add behaviour is invoked on the component through a call to the add(int a, int b) method on the Maths interface. Next, we can see how the addition of intercessions (or method traps) on the component affects the behaviour of the add method. In this case the intercession behaviour is set to evolve the add method by incrementing the parameters and then incrementing the result of the add method. After this has been performed the RComponent's metalevel is adjusted further to evolve the external interface of the component by adding subtract behaviour to the component whilst it is still operational. Once the subtract behaviour has been added, through an evolved interface called FurtherMaths, we can see that this interface contains a subtract method and also inherits the add method. The component retains the Maths interface for compatibility with older client revisions. Calling the subtract behaviour is then demonstrated. Finally, we can see the effect of behaviourally manipulating the component's metalevel and substituting the component's add behaviour to always return the same value. The behaviour in this case though raises an exception which is handled by the RComponent through a custom exception handler. In this case the error is division by zero. The exception handler can be dynamically changed with a metalevel call. Switching to the command-line window where the "daemon" was run you should see the component print out the effects of any manipulations on the metalevel. Also the component will log all calls that are make to the dispatcher in this window. Here we can see the effects of any invocations on the component, and also the effects of adding intercessions around the method invocation. Finally, the window logs the results of any method substitutions and displays the trapped exception in the replaced behaviour of the add method in the interface "FurtherMaths". Running the example again without re-registering the component produces slightly different results in that the component on the second and subsequent runs has the FurtherMaths interface from its last run (it retains this interface until it is re-registered). Therefore, if we again try to evolve the interface the component's addInterface() method will report that the interface is already presented by the component. Subsequently, because we have just added intercessions to all methods on the component in its previous run, any call to the published component methods will inherit the intercession, until the metalevel is modified again. See the source code for the file "driver.java" for further details. The behaviour of the component declared in the delegation files "AddBehaviour.java", and "NewBehaviour.java" can be re-compiled whilst the component is registered. The component will use the latest compiled version of the behaviour upon each invocation to that specific behaviour. For example, comment out line 10 of the file "NewBehaviour.java" and the division by zero exception will not occur and the FurtherMaths.add method will return normally. Summary ------- The demonstration therefore shows, * Interface and component introspection * Remote component activation & registration * Delegation and method invocation * Dynamic custom exception handling * Runtime dynamic evolution * Metalevel manipulation through, * Intercession * Interface evolution * Component interface version preservation, & backward compatibility * Type-safe method introduction through interface evolution * Behavioural manipulation through logic substitution * Component inheritance * XML ADL for component registration verification Notification DEMO1 ------------------ A client can set itself up as a listener for events generated by any other RComponent. To demonstrate this take the following steps, 1) Open another command-prompt window. 2) Edit the file "listener.bat" and insert the correct paths for your machine in the parameters to register the component. i.e. the "java.rmi.server.codebase" URL. Save the edited file. 3) Type the command "listener" to start the component listener service. 4) In the other free command-prompt window re-run the "driver" again to exercise the RComponent. You will see that the listener window is notified when any events happen within the RComponent that we are listening to (i.e. TestComponent). Inheritance Demo ---------------- An additional component namely, "ExtTestComponent" is included in the demo to show component inheritance. The ExtTestComponent inherits all interfaces, behaviour, and mappings from the original test component. To demonstrate this follow these steps, 1) Edit line 74 of the file "driver.java" changing "SimpleTest" to "InheritTest". This allows the program to verify that both the components used during this test are correctly registered with the correct interfaces before driver execution. The file "RComponentADL.xml" is used to specify what components and interfaces are used for which tests. 2) Edit line 111 of the file "driver.java" changing "TestComponent" to "ExtTestComponent". 3) Save & Compile 4) Make sure that TestComponent is registered with RMID using "register1.bat" (it should be from the above steps, so you don't need to repeat this). 5) Register ExtTestComponent with "register2.bat" 6) type "run -v". You should see that ExtTestComponent during introspection states that it has inherited its behaviour from its super component (TestComponent). Otherwise, ExtTestComponent should execute in the same manner as the original TestComponent. Similarly you should see the notification listeners and inherited component definitions added to the RMI registry printout. Notification DEMO2 ------------------ One RComponent can notify others of what is happening to it, so instead of a separate client as in Notification DEMO1 (above) we are going to setup "ExtTestComponent" to listen to events on "TestComponent". 1) Edit line 111 of the file driver.java changing "ExtTestComponent" back to "TestComponent". 2) Save & Compile driver.java. 3) All components should already be registered if you have run the previous demos. 4) Run the driver by typing "run -v". 5) Goto the window where you executed the activation "daemon", you should see that ExtTestComponent has been notified of the activities performed on TestComponent by the driver application. If the notification has not occurred then you may need to re-register the components by typing "register1" then "register2". In any case, if the components for this section of the demo are missing then verification with the RComponent ADL should produce the message "application not deployed" when running the driver with the -v command-line option. ADL Demo -------- To check that components are registered with the correct set of interfaces before execution the current configuration is inspected against the XML ADL for the specified application. To demonstrate this use the following steps. 1) Edit line 74 of the file "driver.java" changing "InheritTest" back to "SimpleTest". 2) Edit the file "RComponentADL.xml" and add the following line after, --> add line 3) Save the file. 4) At a spare command-line window type "register1" 5) Run the driver program with "run -v". The application will not run because a component cannot be located that implements all of the interfaces specified in the ADL. 6) Re-run the driver this time without verifying the ADL so that the component will have its set of interfaces updated to include "FurtherMaths". 7) Run the driver program again with "run -v". Because the component is now registered with the required interfaces specified in the ADL the driver runs to completion. Therefore the ADL can be used to specify both what components are required for a particular application and also the set of required interfaces that must be presented by the registered components. This enables us to ensure application integrity. Not shown in this demo for the case of simplicity is the ORB's capability of being evolved in a non-programmatic fashion via XML behavioural wiring files. These allow the delegation and intercession tables within the ORB's dispatcher to be setup via a file and do not require any subsequent calls to the RComponent's meta-interface unlike the code supplied in the "driver.java" example used here. To use this facility call the setDispatchWiring() method to read the configuration and re-wire the ORB to reflect the behaviour represented within the file. A snapshot of the ORB's current dispatcher configuration may be captured in a XML file by executing the meta-level's getDispatchWiring() method. The configuration XML file may be edited using the REFLEX RComponent configuration editor available elsewhere on the REFLEX project website.