Archive

Posts Tagged ‘noXML config’

Using Spring with no xml config …

October 21, 2013 Leave a comment

As usual i was just on the way to fixing something else and thought it worth while just documenting a couple of things to know about using spring and groovy.

Spring 3+ now has good support for beans either with traditional xml configuration files (which has the benefit of being independent of the code, and so useful for third party software you may have but little code control over) and more latterly for annotation driven config from code – which if your writing /maintaining code can be more pleasant to work with than lots of angle brackets

so quickie introduction to using noXml anywhere context build – here goes

i’ve built this as a gradle project to handle the dependency management (I am working with Groovy so this makes a lot of sense) but you could do this with maven, our just add the jars to your build path.

I’m using Springsource IDE – but you can install gradle support into ordinary eclipse also

once you have the gradle project support enabled from the eclipse market place and (either use embedded gradle – or download your own install) you should be ready to go

I created a new gradle project using the wizard – kept it simple and just used simple gradle project structure

in the build.gradle file in the root of the project edit the file to include some additional dependencies and apply the groovy plugin, and added a src/main.groovy source directory to the standard gradle project.

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'groovy'

sourceCompatibility = 1.5
version = '1.0'
jar {
    manifest {
        attributes 'Implementation-Title': 'Gradle Quickstart', 'Implementation-Version': version
    }
}

//project variables
ext {
	spring_version = "3.1.4.RELEASE"
}

repositories {
    mavenCentral()
}

dependencies {
	compile 	'org.codehaus.groovy:groovy-all:2.1.+'
        compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
        testCompile group: 'junit', name: 'junit', version: '4.+'
	compile 	"org.springframework:spring-core:${spring_version}"
	compile 	"org.springframework:spring-beans:${spring_version}"
	compile 	"org.springframework:spring-context:${spring_version}"
	compile 	"org.springframework:spring-aspects:${spring_version}"
	compile 	"org.aspectj:aspectjrt:1.6.10"
	compile 	"org.aspectj:aspectjweaver:1.6.10"
	compile 	"cglib:cglib:2.2"
}

test {
    systemProperties 'property': 'value'
}

uploadArchives {
    repositories {
       flatDir {
           dirs 'repos'
       }
    }
}

couple of things to note: you have to have cglib in the dependency list, and groovy (if you are using groovy) and as i want to try spring DI outside of the context – i’ve included the aspectj necessities

then what you need to do is provide an entry point (I could use a groovy script here – but i have just used a class with a static main instead as you would for a java like app)

package com.softwood

import org.springframework.context.annotation.AnnotationConfigApplicationContext

class Sampler {
	
	static void main (String[] args) {
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(/*BeanConfig.class*/)
                //could add dynamically like this - but I didn't,  I just used the scan()
                //ctx.register (BeanConfig.class)
		ctx.scan ("com.softwood")
		ctx.refresh ()
		
		WillsBean wb = ctx.getBean("willsBean")
		assert wb != null
		println "willsBean : " + wb.type

		WillsBean pwb = ctx.getBean("privateBean")
		WillsBean pwb2 = ctx.getBean("privateBean")
		println "privateBean with type $pwb.type and int : " + pwb.i + " dump: " + pwb.dump()
		println "privateBean with type $pwb.type and int : " + pwb2.i + " dump: " + pwb2.dump()

	}

}

so pretty simple to start with – i’ve created a Sampler class which creates a new AnnotationConfigApplicationContext() – you can pass the list of @Configuration classes into the constructor (as shown in commented out params), or call the register() action on the context to register these at runtime (commented out), and lastly call the refresh() to reload the context.

what i’ve done here however is set a context-scan starting from com.softwood and below looking for annotated files (@Configuration, @Component, @Service etc ) and call refresh(). This loads the @Configuration class BeansConfig and its beans (and WillsBean as its annotated with @Component) into the context.

So then you provide the basic @Configuration annotated class, and define the @Beans within that you expect to be handled within the context. In this example i’ve declared WillsBean with @Component (but you needn’t do that) which adds the default bean as willsBean using the default constructor as a singleton.

in the BeanConfig class i declare two @Bean instances; publicBean (singleton) and privateBean (which is prototype scoped – a new instance every time is returned) (note it didn’t like the private bean as being decalred private – i had to make it public to work)

@Configuration
class BeanConfig {
	static int i
	
	@Bean 
	WillsBean publicBean () {
		return new WillsBean ("willsPublicBean")
	}
	
	@Bean @Scope ("prototype")
	WillsBean  privateBean () {
		return new WillsBean ("willsPrivateBean", i++)
	}
}

@Component
class WillsBean  {
	
	String type 
	int i 

	WillsBean () {
		this.type = "singletonComponent"
		this.i = -1
	}

	WillsBean (String type) {
		this.type = type
		this.i = -1
	}
	
	WillsBean (String type, int i) {
		this.type = type
		this.i = i 
	}
}

This all works as expected when you run it.

Equally you can expand the example and add say a DISource and DITarget class, where the DITarget has an @Autowired Field dependency on a a DISource which will be fulfilled when you get the diTarget bean from the context like this

class BeanConfig {
       ....
	@Bean 
	DISource diSource () {
		return new DISource()
	}

	@Bean 
	DITarget diTarget () {
		return new DITarget ()  //trigger autowired injection on field 
	}
} //end BeanConfig

//DI source class 
class DISource {
	String name = "DI source for injection "
}

//DI dependent class 
class DITarget {
	@Autowired DISource diSource
}

you trigger the DI injection from the Sampler.main() like this

		DITarget target = ctx.getBean("diTarget")
		println "injected DISource into DItarget and set as : " + target?.diSource?.name

The rest of the annotation examples can be gleaned from the user guide documentation when is pretty good.

Categories: Groovy, Spring Tags: , ,
%d bloggers like this: