[2.0] Spring Module

1,044 views
Skip to first unread message

Scott Phillips

unread,
Apr 6, 2012, 6:07:57 PM4/6/12
to play-fr...@googlegroups.com

Everyone,

I've been playing around with the new version of Play for the past few days. I know Guillaume don't much care for Spring. However, we have several projects here that are Spring based and if we want to port them forward Spring support is needed. Plus I kind of like Spring :)

I've done a first pass at creating a Play 2.0 plugin that supports Spring. It's basically a repackaging of Nicolas' original spring module for Play 1.x. It basically works the same way as the original, except I haven't gotten component scanning to work yet. It is published on git hub:

https://github.com/scott-phillips/Spring4Play2

It's not published in a module/sbt/maven repository at present. That will follow in time.

Scott--

Liyu Yi

unread,
Apr 7, 2012, 1:21:36 AM4/7/12
to play-framework
Scott,

Can you please share some instructions for installing this module/
plugin?

I am new to Play (and new to Play 2 as well), and we have a old-
fashioned Spring application need to to be integrated.

Thanks a bunch.

-- Liyu

Guillaume Bort

unread,
Apr 7, 2012, 5:19:20 AM4/7/12
to play-fr...@googlegroups.com
Do you know that (at least for the Java API), you could manage the
controllers via Spring?

Here is an exemple. Let's define two controllers:

------

package controllers;

import play.mvc.*;

public class Controller1 extends Controller {

public Result index() {
return ok("INDEX 1");
}

}

-------

package controllers;

import play.mvc.*;

public class Controller2 extends Controller {

public Result index() {
return ok("INDEX 2");
}

}

------

Note that here the action methods are not static. So there is no way
for Play to invoke them.

We need to create instances of these controllers. Let's write a
controllers factory:

-----

package controllers;

public class Application {

public static Controller1 controller1() {
return new Controller1();
}

public static Controller2 controller2() {
return new Controller2();
}

}

----

Here we create a new controller instance for each request. We could
also apply the singleton pattern and keep a single instance for the
whole application.

.... Or retrieve the controller instance from Spring (with
dependencies injection already managed by Spring):

-----

package controllers;

public class Application {

static ApplicationContext ctx = initStuff(...);

public static Controller1 controller1() {
return ctx.get("controller1");
}

public static Controller2 controller2() {
return ctx.get("controller2");
}

}

----

How does the routing/reverse routing work? The same way:

GET /index1 controllers.Application.controller1.index()
GET /index2 controllers.Application.controller2.index()

And to reverse:

routes.Application.controller2.index()

Hope that give you some ideas for your plugin.

> --
> You received this message because you are subscribed to the Google Groups
> "play-framework" group.
> To post to this group, send email to play-fr...@googlegroups.com.
> To unsubscribe from this group, send email to
> play-framewor...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/play-framework?hl=en.

--
Guillaume Bort

Scott Phillips

unread,
Apr 7, 2012, 11:15:22 AM4/7/12
to play-fr...@googlegroups.com, liy...@gmail.com

Liyu,

Unfortunately for the immediate future it is a pain to install the module. Once it's hosted somewhere it will become much easier. Until then here's the easiest way I know to locally install modules (maybe someone else has some short cuts?):

1. Check the project out from github or where ever.
2. If the project has a project-code/ directory or something else to separate out sample apps from the actual module then cd into that directory.
3. Drop into the play/sbt console
4. Run "publish-local"

Elsewhere on that same machine in your application:
5. Edit your project/build.scala configuration to look something like this:

 val appDependencies = Seq(
      "spring4play2" % "spring4play2_2.9.1" % "1.0-SNAPSHOT"
 )

 val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings(
      resolvers += "Local Play Repository" at "file://Users/aggiescott/Development/play/current/repository/local/"
 )

Obviously you'll have to change the path to your local repository within your play installation. I assume there's a better way to reference the a local sbt repository without hard coding a path, but I'm not sure what parameters are accessible from the build file.

Scott--



Scott Phillips

unread,
Apr 7, 2012, 11:18:31 AM4/7/12
to play-fr...@googlegroups.com

Guillaume,

No I didn't realize that, and that is awesome! I'll write that up to include in the documentation.

Thanks.

Scott--

Liyu Yi

unread,
Apr 9, 2012, 2:03:33 AM4/9/12
to Scott Phillips, play-fr...@googlegroups.com
Scott,

Yes, it worked like a charm!

Thanks so much.

-- Liyu 

Morten Kjetland

unread,
Apr 9, 2012, 5:53:30 AM4/9/12
to play-fr...@googlegroups.com

Just a tip: you can host your own maven repo on github.
If you create a repo named <username>.github.com its files will be available at http://<username>.github.com

Have a look at http:/github.com/mbknor to see how i publish my projects, for example gt-engine-play2

-morten

Liyu Yi

unread,
Apr 9, 2012, 9:57:31 PM4/9/12
to play-framework
Scott,

Honestly, there will be multiple ways to pull in a Spring context. I
am just trying to figure out a nice one, which is the one you folks
are going to release. IMHO, the @inject annotation approach (or
equivalent) will be the best.

Thanks,

-- Liyu

On Apr 7, 8:18 am, Scott Phillips <sc...@scottphillips.com> wrote:
> Guillaume,
>
> No I didn't realize that, and that is awesome! I'll write that up to
> include in the documentation.
>
> Thanks.
>
> Scott--
>

Will Sargent

unread,
Apr 10, 2012, 12:19:55 AM4/10/12
to play-fr...@googlegroups.com

Scott Phillips

unread,
Apr 10, 2012, 12:27:33 PM4/10/12
to play-fr...@googlegroups.com

Everyone,

I have finished my version of the Spring Module for Play 2.0, it has documentation and is published in a maven repository. So it should be much easier to install now. I've added a documentation on how to use it, along with several sample applications which show how to use @annotation configuration, and illustrate Guillaume's example of injecting dependencies into controllers. I'm hoping to eventually submit this to the play repository when that's up and ready.

https://github.com/scott-phillips/Spring4Play2

Unfortunately, I wasn't aware of Will Sargents work until today. :( Our implementations are basically the same evolution of the original Play module except Will's is in Scala and mine is in Java.

Scott--

Scott Phillips

unread,
Apr 10, 2012, 12:31:33 PM4/10/12
to play-fr...@googlegroups.com

Liyu,

You can use Java's @Inject or Spring's @Autowire to configure your Spring dependencies. To use @inject you'll have to include those annotations as a dependency:

    val appDependencies = Seq(
      "play" % "spring_2.9.1" % "2.0",
      "javax.inject" % "javax.inject" % "1"
    )


You can then take the example application and replace @autowire with @inject.
https://github.com/scott-phillips/Spring4Play2/tree/master/samples/AnnotationConfigExample

Scott--

Liyu Yi

unread,
Apr 10, 2012, 2:22:16 PM4/10/12
to play-framework
Awesome, You guys rock!

BTW, what will be the recommended mechanism for dependency wiring (or
DI). I know Spring will work, but somewhere I saw you guys are talking
about Guice.

Thanks again for the great job.

-- Liyu

On Apr 10, 9:31 am, Scott Phillips <sc...@scottphillips.com> wrote:
> Liyu,
>
> You can use Java's @Inject or Spring's @Autowire to configure your Spring
> dependencies. To use @inject you'll have to include those annotations as a
> dependency:
>
>     val appDependencies = Seq(
>       "play" % "spring_2.9.1" % "2.0",
>       "javax.inject" % "javax.inject" % "1"
>     )
>
> You can then take the example application and replace @autowire with
> @inject.https://github.com/scott-phillips/Spring4Play2/tree/master/samples/An...

Scott Phillips

unread,
Apr 10, 2012, 2:34:36 PM4/10/12
to play-fr...@googlegroups.com

There's not going to ever be one way. My best guess is that neither Guice, Spring, or another DI framework will be included in the core distribution of Play. These are all perfect examples of the use-case for modules. Really play don't need a dependency injections framework, the need is mostly driven by the requirement of integrating Play with other APIs who use dependency injection. I think for your typical small play app dependency injection is overkill that just adds complexity and slows down development without bringing any practical benefits to the table.

The real question is what is better for your project Guice, Spring, something else, or nothing at all?

Scott--

Liyu Yi

unread,
Apr 11, 2012, 1:43:01 AM4/11/12
to play-framework
Hey, Scott,

When I am using
    val appDependencies = Seq(
    "play" % "spring_2.9.1" % "2.0",
    "javax.inject" % "javax.inject" % "1"
    )

    val main = PlayProject(appName, appVersion, appDependencies,
mainLang = JAVA).settings(
    resolvers += "TAMU Release Repository" at "https://
maven.library.tamu.edu/content/repositories/releases/"
    )

I got the following error.

! Internal server error, for request [GET /] ->
sbt.PlayExceptions$CompilationException: Compilation error [package
edu.tamu.play.modules does not exist]
at sbt.PlayReloader$$anon$2$$anonfun$reload$3$$anonfun$2$$anonfun
$apply$11$$anonfun$apply$12.apply(PlayReloader.scala:224) ~[na:na]
at sbt.PlayReloader$$anon$2$$anonfun$reload$3$$anonfun$2$$anonfun
$apply$11$$anonfun$apply$12.apply(PlayReloader.scala:224) ~[na:na]
at scala.Option.map(Option.scala:133) ~[scala-library.jar:0.11.2]
at sbt.PlayReloader$$anon$2$$anonfun$reload$3$$anonfun$2$$anonfun
$apply$11.apply(PlayReloader.scala:224) ~[na:na]
at sbt.PlayReloader$$anon$2$$anonfun$reload$3$$anonfun$2$$anonfun
$apply$11.apply(PlayReloader.scala:221) ~[na:na]
at scala.Option.map(Option.scala:133) ~[scala-library.jar:0.11.2]

Any suggestions?

Thanks,


-- Liyu

James Roper

unread,
Apr 11, 2012, 5:05:00 AM4/11/12
to play-fr...@googlegroups.com
On Tuesday, April 10, 2012 8:34:36 PM UTC+2, Scott Phillips wrote:

There's not going to ever be one way. My best guess is that neither Guice, Spring, or another DI framework will be included in the core distribution of Play. These are all perfect examples of the use-case for modules. Really play don't need a dependency injections framework, the need is mostly driven by the requirement of integrating Play with other APIs who use dependency injection. I think for your typical small play app dependency injection is overkill that just adds complexity and slows down development without bringing any practical benefits to the table.

No.  The biggest driver for dependency injection, and the biggest reason why I always use it, is testability.  I can't remember when the last time I worked on a web application that didn't call a remote API of another application.... it's WEB 2.0, applications build on each other.  And every application that I write has tests, and every application that I write has a CI server running those tests on every commit.  But tests and remote calls on external systems don't mix well, here's a sample of reasons:

1) Usually you can't control that system.  If that system fails, your tests fail.  If you want to test certain error scenarios (for example, if that system is down) you can't.  If you want to load that system with test data, you can't.  Even when that service is something as reliable google, it's still a massive pain.  I've had just a small subset of tests which get run less frequently against google, to make sure we catch any changes in Google's APIs, but it's amazing when you have something running frequently against Google's APIs how high you find their error rate is.
2) Even if you do control that system, and maybe even have the source code so you can start your own instance up, the overhead of maintaining a development environment with both systems (and every other system that is required to run the system you're calling, and so on) adds FAR greater complexity than simple DI.
3) Running CI that calls out to someone elses server is wrong.  You're potentially adding a large load to that server.  You're likely to find yourself getting an IP block against you.

Dependency injection solves these issues by allowing you to substitute implementations of the clients to the third party services with mocks, and this happens transparently to the code that uses the services.  The code can focus on using the service, and not what mode it's running in, while your DI framework focuses on ensuring the right implementations are used for the right mode.

These days, your average small play app will call external services... particularly a small app, as small apps usually build on larger apps.  Your average small play app should have automated tests.  Therefore your average small play app will find dependency injection very useful.

The real question is what is better for your project Guice, Spring, something else, or nothing at all?

Scott--


On Tue, Apr 10, 2012 at 1:22 PM, Liyu Yi wrote:
Awesome, You guys rock!

BTW, what will be the recommended mechanism for dependency wiring (or
DI). I know Spring will work, but somewhere I saw you guys are talking
about Guice.

Thanks again for the great job.

-- Liyu
> > > > > To post to this group, send email to play-framework@googlegroups.com

> > .
> > > > > To unsubscribe from this group, send email to

> > > > > For more options, visit this group at
> > > > >http://groups.google.com/group/play-framework?hl=en.
>
> > > > --
> > > > Guillaume Bort
>
> > > > --
> > > > You received this message because you are subscribed to the Google
> > Groups
> > > > "play-framework" group.
> > > > To post to this group, send email to play-framework@googlegroups.com.

> > > > To unsubscribe from this group, send email to

> > > > For more options, visit this group at
> > > >http://groups.google.com/group/play-framework?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "play-framework" group.
> > To post to this group, send email to play-framework@googlegroups.com.

> > To unsubscribe from this group, send email to

> > For more options, visit this group at
> >http://groups.google.com/group/play-framework?hl=en.

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To post to this group, send email to play-framework@googlegroups.com.
To unsubscribe from this group, send email to play-framework+unsubscribe@googlegroups.com.

Scott Phillips

unread,
Apr 11, 2012, 9:50:07 AM4/11/12
to play-fr...@googlegroups.com

Liyu,

The package names changed to match those from the original spring module.

Scott--

Liyu Yi

unread,
Apr 12, 2012, 2:15:15 AM4/12/12
to play-fr...@googlegroups.com
Scott,

I got the Spring working with the latest Spring4Play2. The classpath scanning (a.k.a the injection with annotation) is also working as expected. Later I tried to push the application to Heroku. It somehow crashed.

If I disable the Spring stuff, it works fine in Heroku. Any suggestions? Could it be the dependency resolving went wrong?

Have you ever tried to push a Play application with Spring into Heroku?

Thanks!

-- Liyu 


PS: heroku logs
2012-04-12T05:52:26+00:00 heroku[web.1]: Starting process with command `target/start -Dhttp.port=${PORT} ${JAVA_OPTS}  -DapplyEvolutions.default=true`
2012-04-12T05:52:26+00:00 app[web.1]: Play server process ID is 3
2012-04-12T05:52:27+00:00 app[web.1]: [info] play - database [default] connected at jdbc:h2:mem:play
2012-04-12T05:52:30+00:00 app[web.1]: [debug] application - Loading application context: application-context.xml
2012-04-12T05:52:30+00:00 app[web.1]: Oops, cannot start the server.
2012-04-12T05:52:30+00:00 app[web.1]: java.lang.NoClassDefFoundError: org/springframework/asm/ClassVisitor
2012-04-12T05:52:30+00:00 app[web.1]: at org.springframework.context.support.GenericApplicationContext.<init>(GenericApplicationContext.java:103)
2012-04-12T05:52:30+00:00 app[web.1]: at play.modules.spring.SpringPlugin.onStart(SpringPlugin.java:76)
2012-04-12T05:52:30+00:00 app[web.1]: at play.api.Play$$anonfun$start$1.apply(Play.scala:60)
2012-04-12T05:52:30+00:00 app[web.1]: at play.api.Play$$anonfun$start$1.apply(Play.scala:60)
2012-04-12T05:52:30+00:00 app[web.1]: at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
2012-04-12T05:52:30+00:00 app[web.1]: at scala.collection.immutable.List.foreach(List.scala:45)
2012-04-12T05:52:30+00:00 app[web.1]: at play.api.Play$.start(Play.scala:60)
2012-04-12T05:52:30+00:00 app[web.1]: at play.core.StaticApplication.<init>(ApplicationProvider.scala:51)
2012-04-12T05:52:30+00:00 app[web.1]: at play.core.server.NettyServer$.createServer(NettyServer.scala:132)
2012-04-12T05:52:30+00:00 app[web.1]: at play.core.server.NettyServer$$anonfun$main$5.apply(NettyServer.scala:153)
2012-04-12T05:52:30+00:00 app[web.1]: at play.core.server.NettyServer$$anonfun$main$5.apply(NettyServer.scala:152)
2012-04-12T05:52:30+00:00 app[web.1]: at scala.Option.map(Option.scala:133)
2012-04-12T05:52:30+00:00 app[web.1]: at play.core.server.NettyServer$.main(NettyServer.scala:152)
2012-04-12T05:52:30+00:00 app[web.1]: at play.core.server.NettyServer.main(NettyServer.scala)
2012-04-12T05:52:30+00:00 app[web.1]: Caused by: java.lang.ClassNotFoundException: org.springframework.asm.ClassVisitor
2012-04-12T05:52:30+00:00 app[web.1]: at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
2012-04-12T05:52:30+00:00 app[web.1]: at java.security.AccessController.doPrivileged(Native Method)
2012-04-12T05:52:30+00:00 app[web.1]: at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
2012-04-12T05:52:30+00:00 app[web.1]: at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
2012-04-12T05:52:30+00:00 app[web.1]: at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
2012-04-12T05:52:30+00:00 app[web.1]: at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
2012-04-12T05:52:30+00:00 app[web.1]: ... 14 more
2012-04-12T05:52:32+00:00 heroku[web.1]: Process exited with status 255
2012-04-12T05:52:32+00:00 heroku[web.1]: State changed from starting to crashed
2012-04-12T05:58:53+00:00 heroku[slugc]: Slug compilation started


> > > > .
> > > > > > > To unsubscribe from this group, send email to

> > > > > > > For more options, visit this group at
> > > > > > >http://groups.google.com/group/play-framework?hl=en.
>
> > > > > > --
> > > > > > Guillaume Bort
>
> > > > > > --
> > > > > > You received this message because you are subscribed to the Google
> > > > Groups
> > > > > > "play-framework" group.
> > > > > > To post to this group, send email to

> > > > > > To unsubscribe from this group, send email to

> > > > > > For more options, visit this group at
> > > > > >http://groups.google.com/group/play-framework?hl=en.
>
> > > > --
> > > > You received this message because you are subscribed to the Google
> > Groups
> > > > "play-framework" group.
> > > > To post to this group, send email to play-framework@googlegroups.com.

> > > > To unsubscribe from this group, send email to

> > > > For more options, visit this group at
> > > >http://groups.google.com/group/play-framework?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "play-framework" group.
> > To post to this group, send email to play-framework@googlegroups.com.

> > To unsubscribe from this group, send email to

> > For more options, visit this group at
> >http://groups.google.com/group/play-framework?hl=en.

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To post to this group, send email to play-framework@googlegroups.com.
To unsubscribe from this group, send email to play-framework+unsubscribe@googlegroups.com.

Scott Phillips

unread,
Apr 12, 2012, 10:15:08 AM4/12/12
to play-fr...@googlegroups.com

I have only read about Heroku, looks interesting, but I haven't played around with it. So, I can't really speak about any specific problems there. But from the error message it is very clear that the spring dependencies are not being resolved. Play 2.0 itself includes some of the spring libraries, presumably for some third party libraries, but they are not complete. Here's the relevant line from play's build.scala:

            ("org.springframework" % "spring-core" % "3.0.7.RELEASE" notTransitive())
              .exclude("org.springframework", "spring-asm")
              .exclude("commons-logging", "commons-logging")

It is excluding the asm libraries that your are failing on currently. The Spring module is depends upon the full spring libraries without excluding anything. Here's the relevant line from the build.scala:


    val appDependencies = Seq(
            "org.springframework" % "spring-context" % "3.0.7.RELEASE",
            "org.springframework" % "spring-core" % "3.0.7.RELEASE",
            "org.springframework" % "spring-beans" % "3.0.7.RELEASE"
    )


So, somehow when building on Heroku the dependencies are not being resolved correctly.

Scott--


To view this discussion on the web visit https://groups.google.com/d/msg/play-framework/-/YrfJQLHejO4J.

To post to this group, send email to play-fr...@googlegroups.com.
To unsubscribe from this group, send email to play-framewor...@googlegroups.com.

Liyu Yi

unread,
Apr 12, 2012, 12:41:36 PM4/12/12
to play-fr...@googlegroups.com
Scott,

Thanks for the information. I think this can explain it. When the application is pushed to Heroku, the sbt is executed inside Heroku to pull in all the dependencies. If ASM is excluded, the JVM in Heroku is expected to miss this class.

I'll try to make it work by myself. It might be also nice for Play! to take care of this wrinkle, since deploying to Heroku is a such an attractive feature for Play!.

Again, thanks a lot,

-- Liyu 

To post to this group, send email to play-framework@googlegroups.com.

Trung Ly

unread,
Apr 12, 2012, 11:21:13 PM4/12/12
to play-fr...@googlegroups.com
Thanks for the plugin, Scott!

Question: do you have any plans to allow loading multiple context files either by specifying a list, wildcard/blob, or directory path?


On Tuesday, April 10, 2012 9:27:33 AM UTC-7, Scott Phillips wrote:

Everyone,

I have finished my version of the Spring Module for Play 2.0, it has documentation and is published in a maven repository. So it should be much easier to install now. I've added a documentation on how to use it, along with several sample applications which show how to use @annotation configuration, and illustrate Guillaume's example of injecting dependencies into controllers. I'm hoping to eventually submit this to the play repository when that's up and ready.

https://github.com/scott-phillips/Spring4Play2

Unfortunately, I wasn't aware of Will Sargents work until today. :( Our implementations are basically the same evolution of the original Play module except Will's is in Scala and mine is in Java.

Scott--

On Mon, Apr 9, 2012 at 11:19 PM, Will Sargent <will.s...@gmail.com> wrote:
On Fri, Apr 6, 2012 at 3:07 PM, Scott Phillips <sc...@scottphillips.com> wrote:

Everyone,

I've been playing around with the new version of Play for the past few days. I know Guillaume don't much care for Spring. However, we have several projects here that are Spring based and if we want to port them forward Spring support is needed. Plus I kind of like Spring :)

I've done a first pass at creating a Play 2.0 plugin that supports Spring. It's basically a repackaging of Nicolas' original spring module for Play 1.x. It basically works the same way as the original, except I haven't gotten component scanning to work yet. It is published on git hub:

https://github.com/scott-phillips/Spring4Play2

It's not published in a module/sbt/maven repository at present. That will follow in time.


Scott--

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To post to this group, send email to play-framework@googlegroups.com.
To unsubscribe from this group, send email to play-framework+unsubscribe@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/play-framework?hl=en.

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To post to this group, send email to play-framework@googlegroups.com.
To unsubscribe from this group, send email to play-framework+unsubscribe@googlegroups.com.

Scott Phillips

unread,
Apr 13, 2012, 9:45:20 AM4/13/12
to play-fr...@googlegroups.com

With Play 2.0 I don't think it's necessary to add a special feature to the spring module for this. I suggest instead just load the one initial context from Play, and from there load all the additional contexts using all the tools that spring has available. You can use the wildcard designations that you are looking for with the <import/> tag.

http://blog.sarathonline.com/2008/10/classpath-making-your-modular-spring.html

Scott--



To view this discussion on the web visit https://groups.google.com/d/msg/play-framework/-/QvzdzgutuksJ.

To post to this group, send email to play-fr...@googlegroups.com.
To unsubscribe from this group, send email to play-framewor...@googlegroups.com.

Mary Senkiv

unread,
Oct 23, 2013, 4:32:43 PM10/23/13
to play-fr...@googlegroups.com

Hi, everyone

The structure of my application:
common-module - it contains base functionality and also it has application-context.xml which describes all beans from all modules
core - module
module- 2
module - 3

All modules are separete play projects dependant on common. With spring module all beans are resolved perfactly but all tests are failing with ClassNotFoundException, as running tests from core - module cannot find beans from module - 2. 
As all modules are gathered together so why tests are failing?

Thank you in advance!!!
Reply all
Reply to author
Forward
0 new messages