Archive

Archive for the ‘Spring’ Category

silly problems with Spring @Value ‘${}’ with IoC injection

February 23, 2016 Leave a comment

hit some basic problems with Spring injection today worth noting for others

I was trying out @Value injection today in spring and hit some basic issues

1. when you use @Value in groovy and spring – despite the fact that you might want to use a ${} expression, you cant wrap this in “” which you might expect. The Groovy compiler gets in a huff and declares the the value is not a String (technically its a GString in groovy).

to make this work in groovy you have write something like (note single ”)

@Value ('${jmx.rmi.host}')

This is counter intuitive if you are used to the normal “” Gstring interpolation in Groovy. To make it work with “” you have to try

@Value ("${jmx.rmi.host}".toString())

or just use the ” as previously shown.

2. second issue: if injecting values from application.properties in root of your classpath , then note that the properties values in that file default to string, so `x.y.z=”hi”` will return a string including the quotes, which is not what you expect. just leave the strings unadorned to inject correctly.

3. then, if you use param injection alone like this

void setHost ( @Value ('${jmx.rmi.host}') String host)

then you get a null injection (not sure why). To fix this, either

a) move the

@Value ('${jmx.rmi.host}'

to method level, or

b) use @autowired at method level and leave the

@Value ('${jmx.rmi.host}')

at parameter level as well,  to get the injection to occur.

It’s these small nuances that take so much time, hopefully someone else will benefit and save a couple of hours.

4. Lastly, you can lookup properties using the Spring Environment like this. Just use the @Autowired on method or constructor, and do the lookup /type conversion using the env.getRequiredProperty call like this

@Component
class Props {

    private Map props = [:]
    boolean jmxEnabled
    String host

    @Autowired  //test inject the env
    Props (Environment env) {
        jmxEnabled = env.getRequiredProperty("org.softwood.jmx", Boolean.class)
        props[jmxEnabled]=jmxEnabled


    }

    //format either use Autowired for method and @value on param
    // or just @value as method injection will work
    @Autowired
    void setHost ( @Value ('${jmx.rmi.host}') String host)  {

        assert host
        println "set host by injection"
        this.host = host
        props[host] = host
    }

}
Advertisements

Spring Testing using annotation – how to set it up in your IDE

November 6, 2013 Leave a comment

This took a little while the other day to try and setup testing in a spring project under gradle, and using annotation configuration context.

This is just a quick post on what you need to do

in this mini explore project i’ve been trying to use the Spring-data for mongo project and then write some tests.

i’d got stuck as i didn’t have the right libraries by default in the gradle project and because i was using annotations you have to tell the testing framework where your context is

so very quickly, go into your IDE (i’m using GGTS) and create a project and convert to gradle or create a gradle project

by default this doesn’t enable for groovy which i use so you have to add some extras, and the project template is set for java – but as you can use joint compilation this isnt an issue really.

1. edit the default gradle.build. add the groovy plugin (and remove the java one to keep it simple – the grrovy one runs joint compilation so any groovy and java files get compiled
2. add the eclipse plugin
3. set your compiler version
4. create your dependencies – the one i had missed was spring-test. Without this your spring test annotations wont be found and the project wont compile – testCompile “org.springframework:spring-test:3.1.4.RELEASE”. I checked the release by looking at the project dependency list built by using the spring-data-mongodb dependency at for me that brought in all the spring 3.1.4 files – so i just used the spring-test on the same release
5. you can ignore the wrapper task its not required in the IDE

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

sourceCompatibility = 1.7
version = '1.0'
jar {
    manifest {
        attributes 'Implementation-Title': 'MongoSpringData', 'Implementation-Version': version
    }
}

//project variables
ext {
	spring_data_version = "1.3.2.RELEASE"
	}

repositories {
    mavenCentral()
}

dependencies {
	compile ("org.springframework.data:spring-data-mongodb:1.2.1.RELEASE")
	compile 	"cglib:cglib:2.2"
	compile 	"org.slf4j:slf4j-api:1.7.5"
  	compile 	"org.slf4j:slf4j-simple:1.7.5"
   	compile 	'org.codehaus.groovy:groovy-all:2.1.6'
   testCompile group: 'junit', name: 'junit', version: '4.+'
   testCompile "org.springframework:spring-test:3.1.4.RELEASE"
   
}

//not sure why i need this ??
task wrapper(type: Wrapper) {
	gradleVersion = '1.8'
}

test {
    systemProperties 'property': 'value'
}

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

update all the dependencies

then in my simple base code i have a class that builds the spring context like this. Here the application class is both the context bean builder and provides my main entry for my basic app code.

@Configuration
@EnableMongoRepositories
public class Application {

    @Autowired
    CustomerRepository customerRepository

	@Autowired
	OrderRepository orderRepository

    @Bean
    Mongo mongo() throws UnknownHostException {
        return new Mongo("localhost")
    }

    @Bean
    MongoTemplate mongoTemplate(Mongo mongo) {
        return new MongoTemplate(mongo, "sdata")
    }

    public static void main(String[] args) {...

then we come to the tests – this took a little searching on the web to find how to do this.
since spring 3.1 you can use the @ContextConfiguration – and specify the classes with @configuration.. to load, and the right context loader required to read the file above.

the rest @Before/@After/@Test – are standard Junit constructs. You can now test your code and have DI injection from the container to inject beans into your test classes

there was a useful link here i found that expands on some of this


@RunWith (SpringJUnit4ClassRunner)
@ContextConfiguration (classes=Application.class, loader=AnnotationConfigContextLoader.class)

 class OrderRepositoryTest {

	@Autowired OrderRepository repository
	Order newOrder 
	
	@Before
	void setup() {
		
		def order = new Order ("new order")
		newOrder = repository.save (order)
		assert newOrder.order == "new order"
		assert newOrder.id != null
		
	}
	
	@After
	void teardown() {
		repository.delete(newOrder)
		
	}
	
	@Test	
	void findAllTest ()
	{
		Order[] orders = repository.findAll ()
		assert orders 
		assert orders[0].order == "order987"
		assert orders.size() == 2
	}
	
	@Test
	void findNewOrder () {...

onwards and upwards all yeh testers

Categories: Groovy, Spring, Testing

Using Spring Dependency Injection outside the container

October 21, 2013 Leave a comment

This is a follow on the previous post and has led me to trying to get dependency injection to work outside the container.

This is discussed in the AOP sections of the Spring dev guide. and i thought it was clearish until i tried to get it to work and really struggled (silly me nothing is easy), so this blog is the boiled down version of what i did to get it to work.

so the way i tackled this was to extend the previous example in Gradle

Here is the revised version of the BeanConfig class, note the annotations – @EnableSpringConfigured enables the AnnotationBeanConfigurerAspect – which is required to process the @Configurable annotation later; and @EnableLoadTimeWeaving is required to process the ‘new someClass ()’ outside of the container. At one point I thought I had to set the flag (aspectjWeaving=AspectJWeaving.ENABLED) but when i got this working and commented it out it still all worked.

I define a bean to add to the context ‘diSource’


@Configuration 
@EnableSpringConfigured  // should turn on  AnnotationBeanConfigurerAspect 
@EnableLoadTimeWeaving /*(aspectjWeaving=AspectJWeaving.ENABLED)*/  // switch on for this context
class BeanConfig {
	static int i
	
	@Bean 
	WillsBean publicBean () {
		return new WillsBean ("willsPublicBean")
	}
	
	@Bean @Scope ("prototype")
	WillsBean  privateBean () {
		return new WillsBean ("willsPrivateBean", i++)
	}
	
	
	@Bean
	WillsBean publicBeanWithDI () {
		//constructor injection
		return new WillsBean (diSource())
	}

	@Bean 
	DISource diSource () {
		return new DISource()
	}

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

}

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

class DITarget {
	@Autowired DISource diSource
}

Next I had to provide the class I expected to be injected outside the container – like this. Note you cant use the ‘dependencyCheck = true’ flag – as there is a problem if you do with the unfulfilled dependency exception – as it cant set the metaClass. Given this is groovy i think this is an issue with the java spring logic – which gets all the properties and in the case of a groovy class that includes the metaClass – which it ought to ignore. I hope this issue will go away with the spring v4 baseline to groovy.

//setting dependencyCheck = true fails as it checks for metaClass property being set  
@Configurable (autowire=Autowire.BY_TYPE /*, dependencyCheck=false*/)
class ExtDI {
	@Autowired DISource diSource

		
	def say () {
		println "ExtDI : diSource set as " + diSource.name
	}
}

In my example i have setup a context using the standard java context – not a web context. I used the AnnotationConfigApplicationContext – which reads all the @Configuration/Beans annotations and loads the context. You can load the classes marked with @configuration as constructor parameters, see commented out example. But here i have used the scan option to scan the base directory and its children, and then do the refresh() to complete the load. You can also add then dynamically using the ‘register()’ method and do the ‘refresh()’

class Sampler {
	
	static void main (String[] args) {
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(/*BeanConfig.class*/)
		ctx.scan ("com.softwood")
		ctx.refresh ()


So now for the tricky bit. For all this to work you need to use AOP load time (or compile time) weaving of the classes. I haven’t got into the AOP compile time yet – so i tried the load time weaving instead

In order for this to work you must have some spring dependencies resolved and loaded. When i got this to work i was seeing all sorts of issues with ‘xlint/transactional’ warnings which i fixed by adding the spring-tx jar to the class path.

Here is the jar dependency list from my gradle.build file


...
//project variables
ext {
	spring_version = "3.1.4.RELEASE"  //use which version you like by setting this 
}

repositories {
    mavenCentral()
}

dependencies {
	compile 	'org.codehaus.groovy:groovy-all:2.1.7'
    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.springframework:spring-aop:${spring_version}"
	compile 	"org.springframework:spring-instrument:${spring_version}"
	compile 	"org.springframework:spring-tx:${spring_version}"
	compile 	"org.aspectj:aspectjrt:1.6.10"
	compile 	"org.aspectj:aspectjweaver:1.6.10"
	compile 	"cglib:cglib:2.2"
}

spring-aspects and spring-aop are needed for the load time weaving, along with the aspectjweaver jar

if you run all this it fails saying it cant addTransform classes to java class loader. The way to fix this is to set the ‘-javaagent:spring-instrument.xxx.RELEASE jar. (on windows i think there maybe a problem if the path to the jar has a space in the path names – so put the jar somewhere without white space in the path names)

So I had problems right here that took all day to sort. When using a gradle project i right clicked on the project and went to run as>external config – however what this is doing is setting the vm args for the gradle build – not the Sample.class your running

gradle run config

I only spotted this when when I went and created a basic groovy project – and right clicked the run as>external config and I could see the vm args for the Sampler.class – then it was clear i been setting the javaagent on the wrong thing. Once i corrected that (see below) things started to work

proj run config

The net of all this is that the load time weaving should now work for you when you call new ExtDI() outside the context, which triggers the DI via AOP.

If your doing this with tomcat you need to load a different class loader, that’s aop aware – this is outlined in the Spring documentation (I havn’t tried this yet).

Also one other point, you can change the default loadTimeWeaver like this by overriding the getLoadTimeWeaver on you config class that implements LoadTimeWeavingConfigurer.

@Configuration
/**
 * can use this form to add classTransformer 
 */
class AppConfig implements LoadTimeWeavingConfigurer {
	LoadTimeWeaver getLoadTimeWeaver () {
		InstrumentationLoadTimeWeaver ltw =  new InstrumentationLoadTimeWeaver ()
		ltw.addTransformer(new BasicTransformer())
		return ltw
	}
} 

public class BasicTransformer implements ClassFileTransformer {
	
	public BasicTransformer () {
		super ()
	}
	
	public byte[] transform (ClassLoader loader, String className, Class redefiningClass, ProtectionDomain domain, byte[] bytes) 
			throws IllegalClassFormatException {
		System.out.println ("transformer applied to class " + className)
		return bytes
	}

}

In my example the BasicTransformer just lists the classes as loaded to show it works. As Groovy is dynamic and supports AST transforms – i’m not sure i’ll ever use this to instrument my classes – but you can instrument your classes this way from a pure java perspective.

So there you have it, load time weaving, and DI enabled outside the sprint context.

You can also trigger DI in constructors but you need to add an extra flag in the annotation to do this.

@Configurable(preConstruction=true)
public class MyDomain {

  @Autowired private MyContext context;

  public MyDomain() {
    context.doSomething(this); // access the autowired context in the constructor
  }

}

Lastly you need to remember that load time weaving only applies to the context configured – and not all contexts in a chain – to comply with java security policies – so you can only instrument/inject beans in the scope of the context chain.

in the case of web apps you therefore need to be careful where you apply the @SpringConfigured flags. If your doing domain class injection do this in the parent context to the web contexts below – again there is information on this in the spring documentation – but i haven’t gone through all the nuances yet – i’ve merely got the basic version working for now

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: , ,

Jsf2 and spring integration in dynamic web project

August 18, 2013 Leave a comment

in this blog I show how you can run JSF2 as the web view framework but integrate with spring web application context to get to business services, etc.

This is a set on the way to getting JSF2, Primefaces (just a JSF2 library and widgets) and grails2 to work together. This is the next baby step on the way.

see the attached word file that takes you through the steps required to do this

jsf – spring integration example steps

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