link
Avalon
Planet - Facilities
Home PlanetProductsCentral
Using the Reflector Facility

The Reflector has two pre-defined blocks that can be used straight up without any further configuration.

Example of including the Complete block in a larger block;


<container name="myapplication" >
  <classloader>
    :
  </classloader>
  
  <component name="MyComponent" type="com.mycompany.myproject.MyComponent" />
  
  <include 
    artifact="block:metro/facilities/reflector/metro-reflector-blocks-complete#SNAPSHOT" />
  
</container>

Group Name Purpose
metro/facilities/reflector metro-reflector-blocks-complete The Complete block consist of everything need when you don't have the HTTP Facility available and used elsewhere in the system. It starts the HTTP Facility on port 8080 with a normal socket listener and registers the composition model as a root object in the Reflector.
metro/facilities/reflector metro-reflector-blocks-standard The Standard block is intended for use when you want it to attach itself to an existing HTTP Facility running on any port. By default, the Reflector will lookup 'any' HttpContext, so it is not defined which context it will add itself to. If you need better control, you need to use the 'manual assembly' features of Merlin.
Normal Use - My own Root objects.

If you want to have your own root objects, you look up the Reflector and call the addRootObject( String name, Object object ) method, either directly from your component, or preferably from a separate component that does the registration.

/**
 * @avalon.dependency type="org.apache.metro.facilities.reflector.ReflectorService"
 *                    key="reflector"
 * @avalon.dependency type="com.mycompany.myproject.MyApplication"
 *                    key="app"
 */
public void service( ServiceManager man )
    throws ServiceException
{
    MyApplication app = (MyApplication) man.lookup( "app" );
    ReflectorService reflector = (ReflectorService) man.lookup( "reflector" );
    reflector.addRootObject( app );
}
Normal Use - Direct utlization of Reflector

There are sometimes reasons to use the Reflector programmatically and not using it as a troubleshooting tool only. For instance, let's say that you define the entire application with events, and that you want to enable that the user can subscribe to changes via mail. You can then utilize the Reflector to provide for a fairly understandable object model, i.e. the dot-notation, and have a mail application register itself at each of the objects defined in the mail. Another example of use is a report generator, which has its fields defined with the dot-notation of the objects that are the live data in the form.

The ReflectorService interface is fairly easy to understand and has many convenience methods to make these sorts of applications easier to write.

Advance Use - Defining my own TypeHandler

There might be reason to handle the containment of certain types differently than the standard ObjectTypeHandler. Reasons for this varies, but typically it would be that there are additional information in the class or interface that you want to view or change. You create a TypeHandler and implement each of the methods.

Method signature Description
boolean isDefault(); All implementations should return false, unless the purpose is to provide a new default behaviour, instead of the ObjectTypeHandler. This method is only called once upon startup.
String[] getNames( Object container )
    throws ReflectionException;
This method should return an array of all the members of the class. This determines which members are available in the type the TypeHandler handles. This method is called for every object introspected by the Reflector. The names returned will be used as input in the methods below (i.e. the membername argument).
Class getClass( Object container, String membername )
    throws ReflectionException;
Return the Class of the member. The Class returned must be the type of the reference, and not the Class of the object assigned to the reference. In case of JavaBeans get methods, the Class returned equals the return type of the get method. If the Class of the object assigned to the reference is returned, then assignment of new objects to the same reference will be required to be the same class or a subclass of the Class returned from this method.
Object getMemberObject(
    Object container, String membername )
    throws ReflectionException;
Return the object with the given membername.
void setMemberObject(     Object container, String membername, Object value )
    throws ReflectionException;
Assignment of a new value to a member. For primitive types and the subclasses of Number, the value (or true/false in case of boolean) can either be the numeric object, or a string with the value in it. For Number types a Double object will be created and assigned. For all other types, you can pass a String with the fully qualified class name, and a new object of that class will be instantiated and assigned, provided that the class can be found through the classloader hierarchy and that it has a default (i.e. empty) constructor.
boolean isSettable(
    Object container, String memberName )
    throws ReflectionException;
This method should return true if it is possible to modify the member, i.e. call the setMemberObject method.