Archive

Posts Tagged ‘Spring’

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

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: