A First Example

The bulk of this chapter is concerned with describing the dynamic language support in detail. Before diving into all of the ins and outs of the dynamic language support, we look at a quick example of a bean defined in a dynamic language. The dynamic language for this first bean is Groovy. (The basis of this example was taken from the Spring test suite. If you want to see equivalent examples in any of the other supported languages, take a look at the source code).

The next example shows the Messenger interface, which the Groovy bean is going to implement. Note that this interface is defined in plain Java. Dependent objects that are injected with a reference to the Messenger do not know that the underlying implementation is a Groovy script. The following listing shows the Messenger interface:

package org.springframework.scripting;

public interface Messenger {

	String getMessage();
}

The following example defines a class that has a dependency on the Messenger interface:

package org.springframework.scripting;

public class DefaultBookingService implements BookingService {

	private Messenger messenger;

	public void setMessenger(Messenger messenger) {
		this.messenger = messenger;
	}

	public void processBooking() {
		// use the injected Messenger object...
	}
}

The following example implements the Messenger interface in Groovy:

// from the file 'Messenger.groovy'
package org.springframework.scripting.groovy;

// import the Messenger interface (written in Java) that is to be implemented
import org.springframework.scripting.Messenger

// define the implementation in Groovy
class GroovyMessenger implements Messenger {

	String message
}

To use the custom dynamic language tags to define dynamic-language-backed beans, you need to have the XML Schema preamble at the top of your Spring XML configuration file. You also need to use a Spring ApplicationContext implementation as your IoC container. Using the dynamic-language-backed beans with a plain BeanFactory implementation is supported, but you have to manage the plumbing of the Spring internals to do so.

For more information on schema-based configuration, see XML Schema-based Configuration.

Finally, the following example shows the bean definitions that effect the injection of the Groovy-defined Messenger implementation into an instance of the DefaultBookingService class:

<?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:lang="http://www.springframework.org/schema/lang"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/lang https://www.springframework.org/schema/lang/spring-lang.xsd">

	<!-- this is the bean definition for the Groovy-backed Messenger implementation -->
	<lang:groovy id="messenger" script-source="classpath:Messenger.groovy">
		<lang:property name="message" value="I Can Do The Frug" />
	</lang:groovy>

	<!-- an otherwise normal bean that will be injected by the Groovy-backed Messenger -->
	<bean id="bookingService" class="x.y.DefaultBookingService">
		<property name="messenger" ref="messenger" />
	</bean>

</beans>

The bookingService bean (a DefaultBookingService) can now use its private messenger member variable as normal, because the Messenger instance that was injected into it is a Messenger instance. There is nothing special going on here — just plain Java and plain Groovy.

Hopefully, the preceding XML snippet is self-explanatory, but do not worry unduly if it is not. Keep reading for the in-depth detail on the whys and wherefores of the preceding configuration.