james-server-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Siegfried Goeschl <siegfried.goes...@it20one.at>
Subject Re: Central class for service injection
Date Wed, 12 Jul 2006 14:18:06 GMT
Hi Bernd,

do you mind if I nick the idea for Turbine/Fulcrum ... :-) ... never had 
the time to write it.

Cheers,

Siegfried Goeschl

Bernd Fondermann wrote:
> Having setters to inject service components (Store, DNSServer and all 
> the others) into the respective objects creates a new chance to take 
> another step to dramatically lower the dependency on Avalon and 
> centralize the service lookup code.
> 
> A utility class "AvalonServiceInjector" could automatically inject all 
> needed services. The manual lookup code would become obsolete.
> 
> This yields the chance to remove dependencies on Avalon's ServiceManager 
>  from all components.
> 
> It further yields the chance to replace the lookup with the use of "your 
> favorite ServiceManager".
> 
> This is how for example RemoteManager would look now and then:
> 
> public void service( final ServiceManager componentManager )
>         throws ServiceException {
>         super.service(componentManager);
> 
>         MailServer mailServer = 
> (MailServer)componentManager.lookup(MailServer.ROLE );
>         setMailServer(mailServer);
>         Store store = (Store)componentManager.lookup( 
> org.apache.avalon.cornerstone.services.store.Store" );
>         setStore(store);
>         UsersStore usersStore = 
> (UsersStore)componentManager.lookup(UsersStore.ROLE );
>         setUsersStore(usersStore);
>         UsersRepository users = 
> (UsersRepository)componentManager.lookup(UsersRepository.ROLE);
>         if (users == null) {
>             throw new ServiceException("","The user repository could not 
> be found.");
>         }
>         setUsers(users);
>         SpoolManagementService spoolManagement =
> (SpoolManagementService)componentManager.lookup(SpoolManagementService.ROLE); 
> 
>         setSpoolManagement(spoolManagement);
> }
> 
> =====>
> 
> public void service( final ServiceManager componentManager )
>         throws ServiceException {
>         super.service(componentManager);
> 
>         new AvalonServiceInjector(componentManager).canoncialInject(this);
> 
> }
> 
> 
> Note: the whole injection line could even be moved out to the caller of 
> service() and make service() redundant in most of the cases.
> 
> This is how the utility works:
> 
> public class AvalonServiceInjector extends ServiceInjector {
> 
>     private ServiceManager serviceManager;
> 
>     public AvalonServiceInjector(ServiceManager serviceManager) {
>         this.serviceManager = serviceManager;
>     }
> 
>     protected Object lookup(String typeFQName) {
>         try {
>             return serviceManager.lookup(typeFQName);
>         } catch (ServiceException e) {
>             return null;
>         }
>     }
> }
> 
> Note: the lookup could easily be replaced by JNDI lookups or anything else.
> 
> The beef happens to happen in all-purpose ServiceInjector which is 
> already totally independent of Avalon. It uses reflection to gather all 
> setters and tries to find fitting objects in ServiceManager:
> 
> 
> public abstract class ServiceInjector {
> 
>   protected abstract Object lookup(String fullyQualifiedType);
> 
>   public int canoncialInject(Object injectionReceiver) {
> 
>     Class injecteeClass = injectionReceiver.getClass();
>     Method[] methods = injecteeClass.getMethods();
>     int injectionCount = 0;
> 
>     for (int i = 0; i < methods.length; i++) {
> 
>       Method method = methods[i];
>       String methodName = method.getName();
>       if (!methodName.startsWith("set")) continue; // is it a setter?
> 
>       Class[] parameterTypes = method.getParameterTypes();
>       // is it a one parameter setter?
>       if (parameterTypes == null || parameterTypes.length != 1) continue;
> 
>       Class parameterType = parameterTypes[0];
>       String injectionClassCandidate = methodName.substring(3);
> 
>       // does setter parameter match the setter name?
>       String typeFQName = parameterType.getName();
>       if (!typeFQName.endsWith(injectionClassCandidate)) {
>         System.out.println("setter name/param mismatch: " + 
> injectionClassCandidate + " <> " + parameterType);
>         continue;
>       }
> 
>       Object injected = lookup(typeFQName);
>       if (injected == null) {
>         System.out.println("setter parameter lookup failed: " + 
> typeFQName);
>         continue;
>       }
> 
>       try {
>         method.invoke(injectionReceiver, new Object[] {injected});
>         System.out.println("setter injection successfull: " + 
> injectionClassCandidate);
>         injectionCount++;
>       } catch (IllegalAccessException e) {
>         e.printStackTrace();
>       } catch (InvocationTargetException e) {
>         e.printStackTrace();
>       }
>     }
>     return injectionCount;
>   }
> 
> }
> 
> This works perfectly after renaming those setters not already strictly 
> following the setter naming convention.
> 
> By evaluating the canoncialInject() return code the component has full 
> control to check whether all of its components have been injected.
> 
>   Bernd
> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
> For additional commands, e-mail: server-dev-help@james.apache.org
> 
> 
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


Mime
View raw message