Dependency injection with Spring

The Spring framework has been released in 2003, and has been very successful in introducing concepts such as dependency injections and aspect-oriented programming to a wider audience. It is one of the most comprehensive and feature-complete frameworks in the Java ecosystem. It is possible that you may need to use the Spring framework in your Play application, maybe in order to reuse some components that have dependencies on the Spring API. In this case, the Spring module will help you to integrate the two frameworks together easily.

Also, you might want to use some existing code from your application and just test some features of Play. This is where the Spring module comes in very handy.

The source code of this recipe is available in the examples/chapter3/spring directory.

Getting ready

Create an application. Install the Spring module by adding it to the dependencies.yml file and rerun playdeps. Optionally, you may need to rerun the command to generate your IDE specific files. And, as usual, let's go test first. This example features a simple obfuscation of a string by using a service to encrypt and decrypt it:

public class EncryptionTest extends FunctionalTest {

    @Test
    public void testThatDecryptionWorks() {
        Response response = GET("/decrypt?text=foo");
        assertIsOk(response);
        assertContentEquals("Doof", response);
    }

    @Test
    public void testThatEncryptionWorks() {
        Response response = GET("/encrypt?text=oof");
        assertIsOk(response);
        assertContentEquals("Efoo", response);
    }
}

How to do it...

Now let' define some encryption service in this example.

Create a conf/application-context.xml file, where you define your beans:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN""http://www.springsource.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="encryptionService" class="spring.EncryptionServiceImpl" />
</beans>

Define two routes:

GET     /encrypt      Application.encrypt
GET     /decrypt      Application.decrypt

Define an EncryptionService interface and create a concrete implementation:

package spring;

public interface EncryptionService {
    public String encrypt(String clearText);
    public String decrypt(String cipherText);
}

It is true that this is not the strict definition of encryption, but it serves the purpose:

package spring;

public class EncryptionServiceImpl implements EncryptionService {

    @Override
    public String decrypt(String cipherText) {
        return "D" + StringUtils.reverse(cipherText);
    }

    @Override
    public String encrypt(String clearText) {
        return "E" + StringUtils.reverse(clearText);
    }
}

The last part is the controller:

public class Application extends Controller {

    public static void decrypt() {
        EncryptionService encService = 
        Spring.getBeanOfType(EncryptionService.class);
        renderText(encService.decrypt(params.get("text")));
    }

    public static void encrypt() {
        EncryptionService encService = 
        Spring.getBeanOfType(EncryptionService.class);
        renderText(encService.encrypt(params.get("text")));
    }

}

How it works...

If you have worked with Spring before, most of the work is straightforward. After defining a bean in the application context and implementing the interface, your Spring application is up and running. The Play specific part is calling Spring.getBeanOfType() in the controller, which returns the specific spring bean.

You can call Spring.getBeanOfType() either with the name of the bean as argument or with a class you want to have return.

There's more...

Unfortunately, the Spring module (version 1.0 at the time of writing) does not yet support the @Inject annotation. Furthermore, the Spring version used is 2.5.5, so you might need to patch the module by replacing the jars in the lib directory of the module, before you Play around with the spring integration.

Use the component scanning feature

If you do not want to create a Spring definition file at all, you can use annotations. Comment out any bean definitions in the application-context file (but do not remove it!) and annotate the service with the @Service annotation on class level.

Have Spring configurations per ID

If you have set a special ID via "play ID", you can also load a special context on startup. If your ID is set to foo, create a conf/foo.appliction-context.xml Spring bean definition.

Direct access to the application context

You can use SpringPlugin.applicationContext to access the application context anywhere in your application.

See also

If you like dependency injection and inversion of control, just read on to find out that Google guice is also supported.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.18.198