james-server-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Norman Maurer ...@byteaction.de>
Subject Re: Central class for service injection
Date Wed, 12 Jul 2006 10:48:25 GMT
This sound very cool to me and whould give me also a better "extension"
solution for my smtp-api-fastfail stuff to make it easier to write
fastfail stuff. 

bye
Norman

Am Mittwoch, den 12.07.2006, 12:34 +0200 schrieb Bernd Fondermann:
> 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
> 
> !EXCUBATOR:1,44b4d04643381960717602!

Mime
View raw message