Revision: 1471 http://svn.sourceforge.net/spring-rich-c/?rev=1471&view=rev Author: mathiasbr Date: 2006-10-02 00:53:34 -0700 (Mon, 02 Oct 2006)
Log Message: ----------- implementations of application services must not be registered in DefaultApplicationServices any more if the bean name is defined by using the decapitalized short name of the service class. Modified Paths: -------------- trunk/spring-richclient/samples/simple/src/main/resources/org/springframework/richclient/samples/simple/ctx/richclient-application-context.xml trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/support/DefaultApplicationServices.java Modified: trunk/spring-richclient/samples/simple/src/main/resources/org/springframework/richclient/samples/simple/ctx/richclient-application-context.xml =================================================================== --- trunk/spring-richclient/samples/simple/src/main/resources/org/springframework/richclient/samples/simple/ctx/richclient-application-context.xml 2006-09-30 12:19:57 UTC (rev 1470) +++ trunk/spring-richclient/samples/simple/src/main/resources/org/springframework/richclient/samples/simple/ctx/richclient-application-context.xml 2006-10-02 07:53:34 UTC (rev 1471) @@ -94,7 +94,10 @@ <bean id="applicationServices" class="org.springframework.richclient.application.support.DefaultApplicationServices"> <property name="imageSourceId"><idref bean="imageSource"/></property> + <!-- It is not required to define each service bean here if the bean name maches the service type name like rulesSource. + The service implementation will still be found if the bean name uses the decapitalized short name of the service type. <property name="rulesSourceId"><idref bean="rulesSource"/></property> + --> <property name="conversionServiceId"><idref bean="conversionService"/></property> <property name="formComponentInterceptorFactoryId"><idref bean="formComponentInterceptorFactory"/></property> <property name="applicationObjectConfigurerId"><idref bean="applicationObjectConfigurer" /></property> Modified: trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/support/DefaultApplicationServices.java =================================================================== --- trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/support/DefaultApplicationServices.java 2006-09-30 12:19:57 UTC (rev 1470) +++ trunk/spring-richclient/support/src/main/java/org/springframework/richclient/application/support/DefaultApplicationServices.java 2006-10-02 07:53:34 UTC (rev 1471) @@ -72,42 +72,46 @@ import org.springframework.rules.reporting.DefaultMessageTranslatorFactory; import org.springframework.rules.reporting.MessageTranslatorFactory; import org.springframework.rules.support.DefaultRulesSource; +import org.springframework.util.ClassUtils; /** - * A default implementation of the ApplicationServices (service locator) interface. This - * implementation allows for the direct registration of service implementations by using - * various setter methods (like [EMAIL PROTECTED] #setImageSource(ImageSource)}). Service registry - * entries can also be added in bulk using the [EMAIL PROTECTED] #setRegistryEntries(Map)} method. + * A default implementation of the ApplicationServices (service locator) interface. This implementation allows for the + * direct registration of service implementations by using various setter methods (like + * [EMAIL PROTECTED] #setImageSource(ImageSource)}). Service registry entries can also be added in bulk using the + * [EMAIL PROTECTED] #setRegistryEntries(Map)} method. * <p> - * Except in testing environments, this class will typically be instantiated in the - * application context and the various service implementations will be set <b>BY ID</b>. - * The use of service bean ids instead of direct bean references is to avoid numerous - * problems with cyclic dependencies and other order dependent operations. So, a typical - * incarnation might look like this: + * Except in testing environments, this class will typically be instantiated in the application context and the various + * service implementations will be set <b>BY ID</b>. The use of service bean ids instead of direct bean references is + * to avoid numerous problems with cyclic dependencies and other order dependent operations. So, a typical incarnation + * might look like this: * * <pre> - * <bean id="applicationServices" - * class="org.springframework.richclient.application.support.DefaultApplicationServices"> - * <property name="applicationObjectConfigurerId"><idref bean="applicationObjectConfigurer" /></property> - * <property name="imageSourceId"><idref bean="imageSource"/></property> - * <property name="rulesSourceId"><idref bean="rulesSource"/></property> - * <property name="conversionServiceId"><idref bean="conversionService"/></property> - * <property name="formComponentInterceptorFactoryId"><idref bean="formComponentInterceptorFactory"/></property> - * </bean> + * <bean id="applicationServices" + * class="org.springframework.richclient.application.support.DefaultApplicationServices"> + * <property name="applicationObjectConfigurerId"><idref bean="applicationObjectConfigurer" /></property> + * <property name="imageSourceId"><idref bean="imageSource"/></property> + * <property name="rulesSourceId"><idref bean="rulesSource"/></property> + * <property name="conversionServiceId"><idref bean="conversionService"/></property> + * <property name="formComponentInterceptorFactoryId"><idref bean="formComponentInterceptorFactory"/></property> + * </bean> * </pre> * - * Note the use of the <code>refid</code> form instead of just using a string value. - * This is the preferred syntax in order to avoid having misspelled bean names go - * unreported. + * Note the use of the <code>refid</code> form instead of just using a string value. This is the preferred syntax in + * order to avoid having misspelled bean names go unreported. * <p> - * When a service is requested, via [EMAIL PROTECTED] #getService(Class)}, the current registry of - * service implementations is consulted. If a registry entry was made using a bean id, - * this is the point at which it will be dereferenced into the actual bean implementation. - * So, the bean impementation will not be referenced until it is requested. - * <p> - * If a service is requested that has not been registered and a default implementation can - * be provided, it will be constructed at that time. Default implementations are provided - * for essentially all services referenced by the platform. + * Which service implementation is returned by [EMAIL PROTECTED] #getService(Class)} will be determined through the following + * steps: + * <ol> + * <li>Consult the current registry of service implementations which have been explicitly defined through bean + * definition. If a registry entry was made using a bean id, this is the point at which it will be dereferenced into the + * actual bean implementation. So, the bean impementation will not be referenced until it is requested.</li> + * <li>If the service impl. is not found yet the short string name of the service' Java class in decapitalized + * JavaBeans property format will be used to lookup the service implementation in the current application context.<br/> + * If the service class is <code>org.springframework.richclient.factory.MenuFactory</code> the bean name + * <code>menuFactory</code> will be used to find the bean</li> + * <li>If the service impl. is not found yet and a default implementation can be provided, it will be constructed at + * that time. Default implementations are provided for essentially all services referenced by the platform.</li> + * </ol> * * @author Larry Streepy */ @@ -172,10 +176,13 @@ Assert.required( serviceType, "serviceType" ); Object service = services.get( serviceType ); if( service == null ) { - service = getDefaultImplementation( serviceType ); - if( service != null ) { - services.put( serviceType, service ); + service = getServiceForClassType(serviceType); + if (service == null) { + service = getDefaultImplementation(serviceType); } + if (service != null) { + services.put(serviceType, service); + } } else { // Runtime derefence of refid's if( service instanceof String ) { @@ -193,7 +200,7 @@ public boolean containsService( Class serviceType ) { Assert.required( serviceType, "serviceType" ); - return services.containsKey( serviceType ) || containsDefaultImplementation( serviceType ); + return services.containsKey( serviceType ) || containsServiceForClassType(serviceType) || containsDefaultImplementation( serviceType ); } /** @@ -684,6 +691,36 @@ } /** + * Get the implementation of a service by using the decapitalized shortname of the serviceType class name. + * + * @param serviceType + * the service class to lookup the bean definition + * @return the found service implementation if a bean definition can be found and it implements the required service + * type, otherwise null + * @see ClassUtils#getShortNameAsProperty(Class) + */ + protected Object getServiceForClassType(Class serviceType) { + String lookupName = ClassUtils.getShortNameAsProperty(serviceType); + ApplicationContext ctx = getApplicationContext(); + if (ctx.containsBean(lookupName)) { + Object bean = ctx.getBean(lookupName); + if (serviceType.isAssignableFrom(bean.getClass())) { + if(logger.isDebugEnabled()) { + logger.debug("Using bean '" + lookupName + "' (" + bean.getClass().getName() + ") for service " + serviceType.getName()); + } + return bean; + } + else if(logger.isDebugEnabled()){ + logger.debug("Bean with id '" + lookupName + "' (" + bean.getClass().getName() + ") does not implement " + serviceType.getName()); + } + } else if(logger.isDebugEnabled()){ + logger.debug("No Bean with id '" + lookupName + "' found for service " + serviceType.getName()); + } + return null; + } + + + /** * Get the default implementation of a service according to the service type. If no * default implementation is available, then a null is returned. * @@ -700,6 +737,17 @@ } /** + * Tests if the application context contains a bean definition by using the decapitalized shortname of the serviceType class name + * @param serviceType the service class to lookup the bean definition + * @return true if a bean definition is found in the current application context, otherwise false + * + * @see ClassUtils#getShortNameAsProperty(Class) + */ + protected boolean containsServiceForClassType(Class serviceType) { + return getApplicationContext().containsBean(ClassUtils.getShortNameAsProperty(serviceType)); + } + + /** * Tests if a default implementation for the requested service type is available * * @param serviceType the requested service type This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys -- and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ spring-rich-c-cvs mailing list spring-rich-c-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/spring-rich-c-cvs