I am exploring play-scala 2.4.2 and trying to get the spring DI working with it. I see there are a lot of changes in play 2.4.x and old way of overriding the GlobalSettings.getC
The latest version of Play:
Create the class Global (Old Global than extended GlobaSettings):
@Singleton
public class Global {
private static final String APPLICATION_CONTEXT = "applicationContext.xml";
private ConfigurableApplicationContext applicationContext;
@Inject
public Global( ApplicationLifecycle lifecycle ) {
applicationContext = new ClassPathXmlApplicationContext(APPLICATION_CONTEXT_XML);
lifecycle.addStopHook( () -> {
applicationContext.close();
return F.Promise.pure( null );
});
}
}
Create the class ConfigurableApplicationContextModule:
public class ApplicationContextModule extends AbstractModule {
@Override
protected void configure() {
bind( Global.class ).asEagerSingleton();
}
}
In application.conf add this:
play.modules.enabled += "config.ApplicationContextModule"
Create file applicationContext.xml:
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="services, dao"/>
</beans>
After creating what stated above by Ranga
Just in case it can help someone, I also worked on a solution that is working based off of jroper's project: https://github.com/jroper/play-spring. The key was to use spring's scanning feature to "load" the Play classes:
ctx.scan(packages:_*)
with the default play's packages:
def defaultPackages(): Seq[String] = Seq("router", "play", "controllers")
The solution works with 1 hack: you need to add the @javax.inject.Named next to the @Singleton annotations in the Play classes so that Spring can scan them and load them (i.e you need to "fork" the Play version you are using, but it's a rather small and easy change). So here is my sample app with the SpringApplicationLoader: https://github.com/remithieblin/play24_spring
Please follow the following steps:
Step1: Add the spring dependencies in build.sbt file.
libraryDependencies += "org.springframework" % "spring-context" % "4.1.6.RELEASE"
libraryDependencies += "org.springframework" % "spring-core" % "4.1.6.RELEASE"
libraryDependencies += "org.springframework" % "spring-beans" % "4.1.6.RELEASE"
libraryDependencies += "org.springframework" % "spring-aop" % "4.1.6.RELEASE"
Step2: Create a new class (ApplicationGlobalSettings.java) and that implements with GlobalSettings class.
package com.ranga.global.settings;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import play.Application;
import play.GlobalSettings;
public class ApplicationGlobalSettings extends GlobalSettings {
private static final String APPLICATION_CONTEXT_XML = "applicationContext.xml";
private ConfigurableApplicationContext applicationContext;
@Override
public void beforeStart(Application application) {
super.beforeStart(application);
}
@Override
public void onStart(Application application) {
super.onStart(application);
applicationContext = new ClassPathXmlApplicationContext(APPLICATION_CONTEXT_XML);
}
@Override
public void onStop(Application application) {
super.onStop(application);
if(applicationContext != null) {
applicationContext.close();
}
}
}
Step3: Create a new spring configuration file under conf folder (applicationContext.xml) conf\applicationContext.xml
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.ranga.services, com.ranga.daos"/>
</beans>
Step4: Add the newly created GlobalSettings file location to the application configuration file (conf/application.conf).
.....some more configuration here.....
# Global Objects class
application.global=com.ranga.global.settings.ApplicationGlobalSettings
Step5: Create a new service class under com.ranga.service package (HelloWorldService.java).
package com.ranga.services;
import javax.inject.Inject;
import org.springframework.stereotype.Service;
import com.ranga.daos.HelloWorldDAO;
@Service
public class HelloWorldService {
@Inject
private HelloWorldDAO helloWorldDAO;
public String sayHello() {
return helloWorldDAO.sayHello();
}
}
Step6: Create a new dao class under com.ranga.daos package (HelloWorldDAO.java).
package com.ranga.daos;
import org.springframework.stereotype.Repository;
@Repository
public class HelloWorldDAO {
public String sayHello() {
return "Hello Ranga!";
}
}
Step7: Finally inject the HelloWorldService in Application.java file.
package com.ranga.controllers;
import javax.inject.Inject;
import org.springframework.beans.factory.annotation.Autowired;
import com.ranga.services.HelloWorldService;
import play.*;
import play.mvc.*;
import views.html.*;
public class Application extends Controller {
@Inject
private HelloWorldService helloWorldService;
public Result index() {
return ok(index.render(helloWorldService.sayHello()));
}
}
Step8: Finally modify the index.scala.html file code.
@(message: String)
<h1>@message</h1>
Now done.. run the application.