Pages

How Stuff Works: Spring Component Scanning

Spring has an interesting feature of scanning its components defined and load it.So the configuration is tied to application ie the code, using annotations.Spring javaconfig also provides the capability to do convention over configuration.There are a lot of documents,references etc explaining how to do the spring configuration. I was looking into the under the hood flow of how the stuff works...

A minimal config to application context xml

<context:component-scan base-package="packageName"/>

will scan all the component classes in the package.The component classes in the classpath are detected and bean definitions are auto-registered for them.

As per the Schema URI and Schema XSD, the context namespace will be like this - Reference


There are stereotype annotations which are markers for any class that fulfills a role within an application.This is well showcased in SpringMVC.More about the annotations

For efficient configuration, we can have multiple context xmls for maintaining resources. The application can have one for DAOs, one for services and so on.The layers can be effectively scanned by the context loader with this usage. So MVC applications will have seperate xmls for @Repository (data access tier),@Service (service),@Controller (web tier) components.
So for the example in a simple java app, I used them in a single xml. But this is mot an mvc app.

A UserDAO Interface

package com.sample.data;

import java.util.List;

public interface UserDAO {

List<String> getUsers();
}


Its Implementation

package com.sample.data;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Repository;

@Repository("userDAO")
public class UserDAOImpl implements UserDAO {

@Override
public List<String> getUsers() {

List<String> l = new ArrayList<String>();
l.add("Roger Moore");
l.add("Pierce Brosnan");

return l;
}

}


Service Layer

package com.sample.service;

import java.util.List;

public interface UserService {
List<String> getUsers();
}

And its implementation

package com.sample.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sample.data.UserDAO;


@Service("userService")
public class UserServiceImpl implements UserService{

@Autowired
private UserDAO userDAO;

@Override
public List<String> getUsers() {

return userDAO.getUsers();
}


}


the client

package com.sample.client;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.sample.service.UserService;

public class SpringClient {

private UserService service;

public SpringClient(){
ApplicationContext appContext = new ClassPathXmlApplicationContext("resource/applicationContext.xml");
service= (UserService) appContext.getBean("userService");
((ClassPathXmlApplicationContext)appContext).close();
}


public void showUsers() {
for (String s : service.getUsers()) {
System.out.println(s);
}
}

public static void main(String[] args) {
SpringClient spc = new SpringClient();
spc.showUsers();
}

}




applicationContext

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
default-autowire="byName">

<!-- Enable autowiring via @Autowire annotations -->
<context:annotation-config/>


<context:component-scan base-package="com.sample.data">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Repository"/>
</context:component-scan>

<context:component-scan base-package="com.sample.service">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Service"/>
</context:component-scan>

</beans>



After bootstrapping, the set of application components and service that need to be created are identified. AbstractbeanDefinitionReader will read resource definitions. DefaultListableBeanFactory will be used as default bean factory based on bean definition objects. XmlBeanDefinitionReader.loadBeanDefinitions() load bean definitions from the specified XML file in which the BeanDefinitionParser will identify the context namespaces and parses the applicationContext xml. The resources are identified by the implementation of ResourcePatternResolver:, ie PathMatchingResourcePatternResolver in which the location patterns are found like an ant-style. Internally it uses ClassLoader.getResources(String name) method which returns an Enumeration containing URLs representing classpath resources. Then the ComponentScanBeanDefinitionParser will parse through the context defintion nodes. If annotation configuration is enabled, autowiring of components takes place as these "candidate patterns" can be set as autowired. A default AutowiredAnnotationBeanPostProcessor will be registered by the "context:annotation-config" and "context:component-scan" XML tags.If filters are added, then it will parse the type filters. In the example I have provided annotation is the type filter. So it will use AnnotationTypeFilter to load the annotation Repository which is provided as the DAO's annotation resolver.

And we know that spring classes are designed to be extended.I was going through the API docs and found that we can add and exclude filters programmatically too.

So I added showComponents to client code using a selected base package

public void showComponents(){

ClassPathScanningCandidateComponentProvider provider =
new ClassPathScanningCandidateComponentProvider(true);
String basePackage = "com/sample/data";
provider.addExcludeFilter(new AnnotationTypeFilter(Repository.class, true));
Set<BeanDefinition> filteredComponents = provider.findCandidateComponents(basePackage);
System.out.println("No of components :"+filteredComponents.size());

for (BeanDefinition component : filteredComponents) {
System.out.println("Component:"+ component.getBeanClassName());
}

provider.resetFilters(true);
provider.addIncludeFilter(new AnnotationTypeFilter(Repository.class, true));
filteredComponents = provider.findCandidateComponents(basePackage);
System.out.println("No of components :"+filteredComponents.size());

for (BeanDefinition component : filteredComponents) {
System.out.println("Component:"+ component.getBeanClassName());
}

}

So the output will be

No of components :0
No of components :1
Component: com.sample.data.UserDAOImpl



If code and configuration are static like beans, the scanner annotations are useful. For accessing resources, jndi or jdbc or anything dynamic like that better go for xml as it is easy to modify it without code change.Its widely used for request mappings and controllers in Spring MVC.The xml overrides the config.When classes are more scanning will be difficult, so we have to filter them based on the type required.


More Reading

Classpath scanning and managed components

Model Driven Development in Adobe RIA and Eclipse RCP new thoughts

I had a chance to attend Adobe Dev Summit 09 Hyderabad. Among the plethora of Adobe "hoo-hah" products for the new age developers, a very good demo caught my attention. Model driven development in Adobe. Adobe is investing a lot in rooting themselves in the enterprise arena by their Adobe Livecycle stack.

The product has a LiveCycle Workbench ES to integrate with Flex studio which is an Eclipse based development environment. RIA has find its way to enterprise as Web 2.0 has moved from a hype to a standard development use case.But for me, the attention grabber is the powerful Eclipse development environment.More than an IDE, it is a wonderful platform for developing powerful applications with its handy plug-in architecture and widgets.From simple RSS readers to Rational platform, eclipse has its magic hand.

RIA for desktop is AIR.If one develops app in AIR we wont be able to use native widgets, as the runtime provides them.But we can access native windows . Also from the AIR2 next api release it is possible to run native applications from AIR.

What about RCP ? It has SWT runtime component uses native widgets..We may think most of the RCP apps will look like the dry eclipse IDE look and feel... Nope !



See the look of Lotus Domino with the power of custom skinning. Lotus Software has been purchased by IBM and has put a lot of resources to continue the development of different Lotus components (such as Domino and Notes). The UX feel of applications based on Eclipse 4 would be amazing.The upcoming e4 architecture of Eclipse is a promising space for next generation eclipse based applications.User experience guidelines for IBM Lotus rich client applications and plug-ins is here


There has always been a rivalry between desktop and web applications. Both of these genre of applications fight to conquer the business space farmed across the computing world.Web apps want to be in desktop and desktop apps want be in we.Its a fame race. RCP has got a wide enterprise users.The choice of RIA or RCP depends on use case.GWT and Flex in web are good in data visualizations. But 2D and 3D will require the power of native processors. The RCP could make use of Java 2D.There are a lot of solutions in market. More choice more pain ! So I may write about them later.

In the demo (Adobe Max)




rich data model can be modelled and exposed as a crud application with a rich UI
Similar presentation was done by Sujith Reddy where the presentation slides he shared

In Eclipse the model driven development is accomplished using EMF - Eclipse Modelling Framework.It provides an API to access the models. Access models by reflection and dynamic creation are possible.As it goes with RCP,it is like an UI for domain objects.The MVC architecture is done through EMF.It can make use of hibernate, JPA or eclipse link.

As seen in the demo, Flex became the UI of the model.

But there are developments going on in eclipse RCP framework. As Flex SDK is open source these eclipse guys wrote programs to create java for flash !

E4 ?

e4 is the incubator for Eclipse 4.0, to be released 2010 built on current Eclipse and OSGi technology as a solid foundation.

Use of web styling technology (CSS), allows the presentation of user interface elements to be infinitely tweaked and reconfigured without any modification of application code.

This is bringing Eclipse runtime technology into the JavaScript world, and enabling
software written in JavaScript to be executed in the Eclipse runtime.

E4 comes with a framework for defining the design and structure of Standard Widget Toolkit (SWT) applications declarative.This eliminates writing of repetitive boilerplate SWT code, thus reducing development cost, improving UI consistency, and enabling customized application rendering. Plug-ins are coded in Java. A typical plug-in consists of Java code in a JAR library, some read-only files, and other resources such as images, web templates, message catalogs, native code libraries, etc

E4/Eclipse Application Services
-Eclipse APIs are refactored to services which should be offered as separate, independent APIs, so that clients can make use of them without having to buy into all of them. Structuring them as individual services also makes it easier to use them from other languages / environments such as e.g. JavaScript. In service programming models the consumers receive dependencies via dependency injection. This theoretically allows application code to completely eliminate its dependency on a particular container technology, thus enabling greater reuse.

Modeled UI - The E4 user interface is model based; everything that appears in the presentation is backed by a representation in the UI Model.

To that end, e4 is investigating bringing both the benefits of Eclipse to the JavaScript world (modularity, extensibility, and tooling), and JavaScript components into the Eclipse desktop environment.OSGi modularity makes integration of JavaScript Bundles easier.

Use of CSS and declarative styling a pluggable styling engine is used to customize the fonts, colors, and other aspects of widget presentation.

SWT Browser Edition- zero install widgets like RAP in which a JavaScript library (qooxdoo) is running on the client, rendering widgets that are manipulated from Java running on the server or Java is cross-compiled to Flex (ActionScript), Dojo (JavaScript) and Silverlight (.NET) technologies which is a "GWT-like" (Google Web Toolkit) approach.

This shows E4 SWT Java for Flash




More demos

Workbench - perspectives, toolbars, menus, parts. The e4 workbench greatly increases flexibility for application designers by providing a formal model of the elements that comprise an instance of the workbench.

XML UI for SWT (XWT), is a framework for writing SWT widgets declaratively in XML. In XWT, the complete structure of an application or widget hierarchy is expressed declaratively, along with bindings of the widgets to some underlying application model or to Java-based call-backs implementing the widget behavior.

More RCP apps