Showing posts with label dependecy injection. Show all posts
Showing posts with label dependecy injection. Show all posts

Saturday, June 11, 2011

Using JSR 330 annotations with Spring Framework

No doubts Spring Framework had (and still has) a great influence on JSR 330: Dependency Injection for Java. For a long time Spring Framework has a pretty rich set of Java annotations in order to push dependency injection to superior levels. But ... most of such annotations are Spring-specific (like @Autowired, @Component, etc.). So ... the question is: does Spring Framework support JSR 330: Dependency Injection for Java? And the answer is: yes, it does, starting from version 3.

So let me show by example how to use Spring Framework together with JSR 330: Dependency Injection for Java. First, we need to reference JSR 330 annotations, f.e. from atinjet project. As always, I'm using Apache Maven 2/3 so here is my POM file:

  4.0.0

  com.example
  cdi-spring
  0.0.1-SNAPSHOT
  jar

  
    UTF-8
 3.0.5.RELEASE
  

  
    
      javax.inject
      javax.inject
      1
    
        
    
      org.springframework
      spring-context
      ${spring.version}
    
  
  
  
    
      nexus.xwiki.org
      http://nexus.xwiki.org/nexus/content/repositories/externals/
    
  

Pretty simple, the only thing we need to do is to have JSR 330 annotations in classpath. That's it. Here is my simple Spring context XML (applicationContext.xml):



    
    
 

I just asked Spring to do all job for me. Let me declare two simple beans, OneBean and AnotherBean, and inject one bean into another. So here is OneBean.java:
package com.spring.cdi;

import javax.inject.Named;

@Named
public class OneBean {
 public void doWork() {
  System.out.println( "Work is done" );
 }
}
And here is AnotherBean.java:
package com.spring.cdi;

import javax.inject.Inject;
import javax.inject.Named;

@Named
public class AnotherBean {
 @Inject private OneBean oneBean;
 
 public void doWork() {
  oneBean.doWork();
 }
}
As you can see, there are no any Spring specific imports. Let me declare some Starter class which will host main() function (Starter.java):
package com.spring;

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

import com.spring.cdi.AnotherBean;

public class Starter {
 public static void main( String[] args ) {
  ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml" );
  AnotherBean bean = context.getBean( AnotherBean.class );
  bean.doWork();
 }
}
It just loads Spring application context from classpath, asks it for AnotherBean class and call the doWork() method on it (which delegates call to injected OneBean bean). Here is my log when I am running Starter class (please notice that Spring detected JSR 330 annotations and properly handled them):
Jun 11, 2011 1:08:03 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2626d4f1: startup date [Sat Jun 11 13:08:03 EDT 2011]; root of context hierarchy
Jun 11, 2011 1:08:03 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [applicationContext.xml]
Jun 11, 2011 1:08:03 PM org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
INFO: JSR-330 'javax.inject.Named' annotation found and supported for component scanning
Jun 11, 2011 1:08:04 PM org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor 
INFO: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
Jun 11, 2011 1:08:04 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@4979935d: defining beans [anotherBean,oneBean,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor]; root of factory hierarchy
Work is done
So those beans could be easily used without modifications by any Java framework which supports JSR 330 (f.e., JBoss Weld). Cool stuff.

Wednesday, February 2, 2011

Using @Configurable in Spring Framework: inject dependency to any object

Honestly, I like Spring Framework: awesome dependency management combined with rich features and great community. Recently I encountered very nice feature - @Configurable. In short, it allows developer to inject dependency into any object (who defines this annotation) without explicit bean definition. It's pretty cool. Techniques behind - AspectJ with runtime weaving.

Let me show how it works by creating simple test project. Let's start with Maven's project descriptor (pom.xml):

 4.0.0

 spring-configurable
 spring-configurable
 0.0.1-SNAPSHOT
 jar

 spring-configurable
 http://maven.apache.org

 
  UTF-8
  3.0.5.RELEASE
 
 
 
  
   org.aspectj
   aspectjweaver
   1.6.5
  
  
  
   org.springframework
   spring-beans
   ${spring.framework.version}
  
  
  
   org.springframework
   spring-aspects
   ${spring.framework.version}
  
  
  
   org.springframework
   spring-core
   ${spring.framework.version}
  
  
  
   org.springframework
   spring-context
   ${spring.framework.version}
  
  
  
   org.springframework
   spring-jdbc
   ${spring.framework.version}
  
 

Next one, let me create application context (applicationContext.xml) and place it inside src/main/resources:


   
 <context:annotation-config />
 <context:spring-configured />
 <context:load-time-weaver />
 
 <context:component-scan base-package="com.test.configurable" />
 
 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" />

Two key declarations here are <context:spring-configured /> and <context:load-time-weaver />. According to documentation, <context:spring-configured /> "... signals the current application context to apply dependency injection to non-managed classes that are
instantiated outside of the Spring bean factory (typically classes annotated with the @Configurable annotation)..."
and <context:load-time-weaver /> turns on runtime weaving.

Respective Java code which uses power of @Configurable annotation is located into Starter.java, which itself is placed inside src/main/java:
package com.test.configurable;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.Assert;

public class Starter {
 
 @Configurable
 private static class Inner {
  @Autowired private DataSource dataSource;  
 }
 
 public static void main(String[] args) {
  final ApplicationContext context = new ClassPathXmlApplicationContext( "/applicationContext.xml" );
  
  final DataSource dataSource = context.getBean( DataSource.class );
  Assert.notNull( dataSource );
  
  Assert.notNull( new Inner().dataSource );
 } 

}
As we see, class Inner is not a bean, is nested into another class and is created simply by calling new. Nevertheless, dataSource bean is injected as expected. Last but not least, in order this example to work, application should be run using an agent (I am using Spring Framework 3.0.5): -javaagent:spring-instrument-3.0.5.RELEASE.jar

Sunday, October 17, 2010

Injecting file dependency into Spring bean

Continuing to explore power of Spring Framework, I would like to explain how to inject file resource into the Spring bean using @Resource annotation.

First of all, let's start with beans definition file. We need basically to declare file dependency we would like to inject:

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

   <context:annotation-config />   
   <context:component-scan base-package="org.example" />

   <bean id="source" class="org.springframework.core.io.ClassPathResource">
      <constructor-arg index="0" value="some.file.txt" />
   </bean>

</beans>

Having configuration part is ready, we can inject file to a bean.
package org.example;

import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamSource;
import org.springframework.stereotype.Component;

@Component
public class SomeBean implements InitializingBean {   
 @Autowired @Resource( name = "source" ) private InputStreamSource source; 
 
 public SomeBean () {
 }
 
 @Override
 public void afterPropertiesSet() throws Exception {
     for( final String line: ( List< String > )IOUtils.readLines( source.getInputStream() ) ) {
                // do something here    
     }
 }
}
That's it :)
Pretty easy and powerful technique.

Wednesday, April 1, 2009

Testing Spring applications

In my last post we talked about Spring. As a test infected developer, my commitment is to test as much as I can to be sure in quality of my code. So, is it feasible to test (and how?) applications which heavily use Spring? The answers are: yes and very easy with help of Spring testing framework. We will consider a few basic scenarios with testing simple Spring beans and then touch a little bit context-related issues.

So. let's start with Spring beans under the test. I prefer to use Java 5 and annotations to publish regular POJOs as Spring beans and declare dependency injection between beans as well. The bean will be MessageService as in code snippet below:

package com.krankenhouse.services;

@Component
public class MessageService {
@Autowired private ITransport impl;
@Autowired private ILogger logger;

public void send( final String message ) {
logger.log( message );
impl.send( message );
}

public String receive() {
final String message = impl.receive();
logger.log( message );
return message;
}
}

This bean is pretty simple and just demonstrates two important concepts: exporting POJO as Spring bean (@Component) and using dependency injection (@Autowired). Before diving into how to test it, let's create applicationContext.xml (placed inside WEB-INF folder) file.
<?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"
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">

<context:annotation-config/>
<context:component-scan base-package="com.krankenhouse.services" />
</beans>

OK, now we're ready to write our first test, named MessageServiceTestCase. There are basically several ways to do that, depending which features do you need. The first one looks like:

package com.krankenhouse.services;

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( locations = {
"classpath:/META-INF/applicationContext.xml"
}
)
public class MessageServiceTestCase {
@Autowired private MessageService messageService;

public void testSend() {
messageService.send( "Message" );
}
}
And that's it! Spring takes care about context initialization, beans creation, dependency injection, etc. If you need application context inside the test, then a little bit different approach could be used (by inheriting test class from AbstractJUnit4SpringContextTests class):
package com.krankenhouse.services;

@RunWith( SpringJUnit4ClassRunner.class )
@ContextConfiguration( locations = {
"classpath:/META-INF/applicationContext.xml"
}
)
public class MessageServiceTestCase
extends AbstractJUnit4SpringContextTests {
public void testSend() {
MessageService messageService =
( MessageService )applicationContext
.getBean( "messageService");
messageService.send( "Message" );
}
}
There's one important issue concerning Spring context: only one context will be created for each test class instance (not test method!). If you would like to recreate context for each single test method, you have to adorn these ones with @DirtiesContext annotation. Unfortunately, there is no class-level annotation for that up to 2.5.x versions.

In spring with Spring ...

Today I'm going to talk a little bit about Spring. Unfortunately, I didn't use heavily this great framework so far. And that's my fault. Spring is definitely worth to learn and use. Beforehand I would like to recommend an excellent book Pro Spring 2.5 which gave me good start in using Spring.

So, why Spring? Over the years I've been developing software pursuing the same principles: good and clever design, simplicity (keep it simple but not simpler), and easy configuration. In our object-oriented programming era it's all about objects. How simple are relations (dependencies) between objects, how loosely coupled are modules/subsystems/objects, how painful is deployment? And are you able to cover with unit tests each piece of critical functionality (you definitely must do that)?

Spring definitely helps with solving all those issues. Its core is dependency injection container which allows to inject dependencies in declarative manner (either in XML configuration or using Java 5 annotations). And a bunch of additional modules provides everything you need from AOP to JUnit support in order to develop high-quality JEE applications.