Showing posts with label spring-context. Show all posts
Showing posts with label spring-context. Show all posts

Sunday, 12 June 2011

Spring ApplicationContext within Servlet

If you want to use Spring-managed beans within you web application, especially Servlet controller and you don't know which implementation of ApplicationContext to use I recommend you to use XmlWebApplicationcontext. This is pretty straightforward as all you have to do is write 4 lines of code (I love Spring ;) - the following lines of code:
XmlWebApplicationContext ctx = new XmlWebApplicationContext();
ctx.setServletContext(getServletContext());
ctx.setConfigLocations(new String[] { beans definition locations });
ctx.refresh();

Beans definition locations are paths relative to the web root i.e. if you store your bean definitions in WEB-INF/META-INF/services/descriptor.xml you should provide exactly the same string as a config location.

Don't forget to invoke refresh() method.

That's all - isn't Spring beautiful?

Saturday, 11 June 2011

BeanFactory in Spring

As its name implies, a bean factory is an implementation of the Factory design pattern. That is, it is a class whose responsibility is to create and dispense beans. The BeanFactory is the actual container which instantiates, configures, and manages a number of beans. These beans typically collaborate with one another, and thus have dependencies between themselves. When a bean factory hands out objects, those objects are fully configured, are aware of their collaborating objects, and are ready to use.

BeanFactory is a workhorse that initializes beans and calls their lifecycle methods. It should be noted that most lifecycle methods only apply to singleton beans. Spring cannot manage prototype (non-singleton) lifecycles. This is because, after they’re created, prototypes are handed off to the client and the container loses track of it. For prototypes, Spring is really just a replacement for the “new” operator.

A BeanFactory is represented by the interface org.springframework.beans.factory.BeanFactory, and it is having multiple implementations. The most commonly used simple BeanFactory implementation is org.springframework.beans.factory.xml.XmlBeanFactory. (This should be qualified with the reminder that ApplicationContexts are a subclass of BeanFactory, and most users end up using XML variants of ApplicationContext).

Although for most scenarios, almost all user code managed by the BeanFactory does not have to be aware of the BeanFactory, the BeanFactory does have to be instantiated somehow. This can happen via explicit user code such as:

Resource res = new FileSystemResource("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);
or
ClassPathResource res = new ClassPathResource("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);

or
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
new String[] {"applicationContext.xml", "applicationContext-part2.xml"});
// of course, an ApplicationContext is just a BeanFactory
BeanFactory factory = (BeanFactory) appContext;

Beans are lazily loaded into bean factories, meaning that while the bean factory will immediately load the bean definitions (the description of beans and their properties), the beans themselves will not be instantiated until they are needed. While in case of ApplicationContext Interface beans are pre-loaded. See the posts - ApplicationContext in spring and Lazy and pre-loading of beans in spring. os.

More about ApplicationContext in Spring

While the beans package provides basic functionality for managing and manipulating beans, often in a programmatic way, the context package adds ApplicationContext, which enhances BeanFactory functionality in a more framework-oriented style.

A bean factory is fine for simple applications, but to take advantage of the full power of the Spring Framework, you’ll probably want to load your application beans using Spring’s more advanced container, the application context.

Many users will use ApplicationContext in a completely declarative fashion, not even having to create it manually, but instead relying on support classes such as ContextLoader to automatically start an ApplicationContext as part of the normal startup process of a J2EE web-app. Of course, it is still possible to programmatically create an ApplicationContext.

The basis for the context package is the ApplicationContext interface, located in the org.springframework.context package. Deriving from the BeanFactory interface, it provides all the functionality of BeanFactory. To allow working in a more framework-oriented fashion, using layering and hierarchical contexts, the context package also provides the following:

In most cases, you’ll use the ApplicationContext, which adds more enterprise-level, J2EE functionality, such as

  • internationalization (i18n)
  • custom converters (for converting Strings to Object types)
  • event publication/notification
  • Access to resources, such as URLs and files
  • Loading of multiple (hierarchical) contexts, allowing each to be focused on one particular layer, for example the web layer of an application.
You could also implement your own ApplicationContext and add support for loading from other resources (such as a database). While many Contexts are available for loading beans, you’ll only need a few, which are listed below. The others are internal classes that are used by the framework itself.

1. ClassPathXmlApplicationContext: Loads context files from the classpath (that is, WEB-INF/classes or WEB-INF/lib for JARs) in a web application. Initializes using a
new ClassPathXmlApplicationContext(path)

where path is the path to the file. The path argument can also be a String array of paths. This is a good context for using in unit tests.

2. FileSystemXmlApplicationContext: Loads context files from the file system, which is nice for testing. Initializes using a
new FileSystemXmlApplicationContext (path)

where path is a relative or absolute path to the file. The path argument can also be a String array of paths.

3. XmlWebApplicationContext: Loads context files internally by the ContextLoaderListener, but can be used outside of it. For instance, if you are running a container that doesn’t load Listeners in the order specified in web.xml, you may have to use this in another Listener. Below is the code to use this Loader.

XmlWebApplicationContext context = new XmlWebApplicationContext();
context.setServletContext(ctx);
context.refresh();


Once you’ve obtained a reference to a context, you can get references to beans using
ctx.getBean(beanId)

You will need to cast it to a specific type, but that’s the easy part. Of the above contexts, ClassPathXmlApplicationContext is the most flexible. It doesn’t care where the files are, as long as they’re in the classpath. This allows you to move files around and simply change the classpath.

A side from the additional functionality offered by application contexts, another big difference between an application context and a bean factory is how singleton beans are loaded. A bean factory lazily loads all beans, deferring bean creation until the getBean() method is called. An application context is a bit smarter and preloads all singleton beans upon context startup. By preloading singleton beans, you ensure that they will be ready to use when needed—your application won’t have to wait for them to be created.

Thursday, 2 June 2011

@ContextConfiguration : Getting the context file via annotations in Spring, using JUnit

I was just working on a JUnit test today, and saw the annotation @ContextConfiguration which is good way of providing beans directly in unit test, rather than getting the bean via getBean or any method like we used to do (See here for these methods ). 
To instruct Spring to load beans for the tests in the class, we annotate the class with @ContextConfiguration.
There can be various ways we can use this annotation, lets have a look at it one by one:

No File Specified

@ContextConfiguration – with no parameters, (by Default) looks for the config file as the same name as the class with the suffix “-context.xml“. For example,
Suppose our class is Greeting.java and our context file is spring-context.xml

package com.vaani.contextconfig;

@ContextConfiguration
public class Greeting{
...
}
Well this is equivalent to

@ContextConfiguration("/com/vaani/contextconfig/spring-context.xml")
public class Greeting{

File specified (without a starting Slash)


package com.vaani.contextconfig;
@ContextConfiguration("spring-context.xml")
public class Greeting{

Again this is equivalent to fully qualified package path of Greeting class.

File specified with a Starting Slash

One Simple change can ruin your whole day! Add a Starting Slash to the file name.
package com.vaani.contextconfig;
@ContextConfiguration("/com/vaani/contextconfig/spring-context.xml")
public class Greeting{

We can give fully qualified path of the spring-context file in this annotation.

Multiple Files

Pulling multiple configuration files into the application context for your tests.
@ContextConfiguration(locations = {"spring-context.xml", "other-context.xml"})

Just a tip
Create an XML file per test that imports only the application’s context files that are needed.
This can save test execution time, where we only load beans necessary for these tests.