Play 2.4.0-M1 released

1 799 visningar
Hoppa till det första olästa meddelandet

James Roper

oläst,
20 aug. 2014 23:51:582014-08-20
till play-framework, play-fram...@googlegroups.com
Hi all,

The Play team are proud to announce the first milestone release of Play 2.4.

The purpose of this release is to get feedback about the approach to dependency injection that we're implementing in Play 2.4.  The old Play plugins mechanism is going to be deprecated.  For a detailed overview of the different styles of DI available in Play 2.4, please read here:


What we're really interested in is the following:

* If you have a favourite DI framework or approach, both runtime and compile time, please try it out, and give us feedback about how easy or not it is to use it with Play.
* If you're a library maintainer, try porting any Play plugins you've written to Play modules and their compile time DI equivalent, and give us feedback on how this worked for you.

Anyone interested in integrating Spring, we've already made a start to this here:


It's only a start that was done to validate that it will work (it doesn't even support end user defined components yet).  We do not intend on maintaining it, so feel free to fork it if you want to maintain it.

At this stage this release is nowhere near production ready, any of the new APIs that we've introduced may be complete changed or even removed, and there are major feature gaps that we haven't even started working on in the DI support.  This release is only intended for experimenting with the new approach.  Do not upgrade your production system to it and then complain when we break everything in the next milestone.

A few other things about this release:

* This is the first release to be deployed to maven central, and all future 2.4.x and onwards releases will be deployed to maven central (there are still a few of Play's dependencies that haven't been deployed to maven central that we need to sort out).
* There's been some restructuring of the sbt plugin, byte code enhancement is now a separate plugin and artifact, while the routes compiler is a separate plugin (but not a separate artifact).

Enjoy!

James

--
James Roper
Software Engineer

Typesafe – Build reactive apps!
Twitter: @jroper

Mariot Chauvin

oläst,
21 aug. 2014 05:28:292014-08-21
till play-fr...@googlegroups.com
Hi James,

Thanks for sharing early your work on 2.4 and asking feedback.
My question may be naive, but I prefer to ask.
Will it still be possible with 2.4 to build an application without using any DI?

Thanks,

Mariot


--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



Visit theguardian.com. On your mobile and tablet, download the Guardian iPhone and Android apps theguardian.com/guardianapp and our tablet editions theguardian.com/editions.  Save up to 57% by subscribing to the Guardian and Observer - choose the papers you want and get full digital access.  Visit subscribe.theguardian.com

This e-mail and all attachments are confidential and may also be privileged. If you are not the named recipient, please notify the sender and delete the e-mail and all attachments immediately. Do not disclose the contents to another person. You may not use the information for any purpose, or store, or copy, it in any way.  Guardian News & Media Limited is not liable for any computer viruses or other material transmitted with or as part of this e-mail. You should employ virus checking software.
 
Guardian News & Media Limited is a member of Guardian Media Group plc. Registered Office: PO Box 68164, Kings Place, 90 York Way, London, N1P 2AP.  Registered in England Number 908396


Julien Richard-Foy

oläst,
21 aug. 2014 05:44:472014-08-21
till play-fr...@googlegroups.com
Great job, can’t wait for the compile-time injectable router!
--
  Z E N G U L A R I T Y
––––––––––––––––––––––
Julien RICHARD-FOY - Programmer

56 rue Saint Lazare 75009 Paris
625 Market Street - San Francisco

Julien Richard-Foy

oläst,
21 aug. 2014 05:49:012014-08-21
till play-fr...@googlegroups.com
@Mariot Yes, everything works as before if the components of your application are static objects.

The difference is that if you want to use classes (which can have some advantages, especially regarding testing) you will now have choice between a runtime DI mechanism or a compile-time DI mechanism.

naturallog

oläst,
21 aug. 2014 06:04:582014-08-21
till play-fr...@googlegroups.com
+1 for compile-time.

Hopefully macwire can enable this

Alexandre Patry

oläst,
21 aug. 2014 14:01:342014-08-21
till play-fr...@googlegroups.com, play-fram...@googlegroups.com
Nice work!

Will it be possible to inject dependencies in actors?

Steve Lustbader

oläst,
21 aug. 2014 14:12:432014-08-21
till play-fr...@googlegroups.com, play-fram...@googlegroups.com
Will controller injection still use the same "@" syntax in the routes file? There's no mention of that in the new runtime DI page.

-Steve

Rich Dougherty

oläst,
21 aug. 2014 18:45:352014-08-21
till play-framework
Injecting dependencies into actors is outside the scope of this work, but it's always been possible using Guice/Spring/whatever if you make some classes to help with actor creation, inject stuff into your helper classes, and then use the helpers to create your actors.

For example, you can:
- inject stuff into an ActorFactory, then use the ActorFactory to make your Actors
- inject stuff into a PropsFactory, then use the PropsFactory to get the Props for your Actors

The Play DI changes will support Guice, Spring and compile-time dependency injection, so you should be able to use DI in any way that you wish.

Cheers
Rich


--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Rich Dougherty - @richdougherty
Engineer - Typesafe, Inc

Rich Dougherty

oläst,
21 aug. 2014 18:48:542014-08-21
till play-framework
The DI work for routers and controllers still needs to be done, but I imagine that controller injection will use the same syntax unless semantics are different, in which case maybe new syntax will be introduced. The old "singleton" routing syntax will probably stay the same. We want people to be able to upgrade their applications without needing to change their routes files.

Cheers
Rich

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Will Sargent

oläst,
21 aug. 2014 19:05:292014-08-21
till play-fr...@googlegroups.com
Akka and Guice are totally doable.



It's unfortunate that the Activator template depends on Guice 4.0.0.beta and codingwell/scala-guice, but it's easy enough to use 3.0 directly.


Will Sargent
Consultant, Professional Services
Typesafe, the company behind Play Framework, Akka and Scala

Steven Marcus

oläst,
21 aug. 2014 19:06:052014-08-21
till play-fr...@googlegroups.com

I have tried a couple of approaches to injecting dependencies into actors.
http://eng.kifi.com/guicing-up-scala-actors/ was helpful but hasn't been updated for the latest version of Akka.

It would be really great if some guidance, or better yet an implementation, were available in Play.
This area is particular convoluted and carries with it vestigial and deprecated APIs.

Looking forward to 2.4RC!

Thanks,

James Roper

oläst,
21 aug. 2014 21:36:172014-08-21
till play-framework, play-fram...@googlegroups.com
My raw thoughts at the moment (likely to change):

@ will mean "runtime lookup", no @ will mean "constructor injected".

This may not be done until Play 3, or it may be done in Play 2.4 as an alternate routes compiler implementation (we don't want to break existing routes with static actions).  Specifically, with the new routes compiler, the following routes:

GET  /foo  controllers.FooController.index
GET  /bar  @controllers.BarController.index

will compile to something that essentially looks like this:

class Routes @Inject() (
  injector: Injector, 
  fooController: controllers.FooController
) extends Router.Routes {
  def routes = {
    case <foomatcher> => fooController.index
    case <barmatcher> => injector.instanceOf[controllers.BarController].index
  }
}

or maybe even something like this:

class Routes @Inject() ( 
  fooController: controllers.FooController, 
  barController: Provider[controllers.BarController]
) extends Router.Routes {
  def routes = {
    case <foomatcher> => fooController.index
    case <barmatcher> => barController.get.index
  }
}



--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alexandre Patry

oläst,
22 aug. 2014 14:53:392014-08-22
till play-fr...@googlegroups.com


Le jeudi 21 août 2014 19:05:29 UTC-4, Will Sargent a écrit :
Akka and Guice are totally doable.



It's unfortunate that the Activator template depends on Guice 4.0.0.beta and codingwell/scala-guice, but it's easy enough to use 3.0 directly.

Thanks!

Adam Kuipers

oläst,
22 aug. 2014 15:01:182014-08-22
till play-fr...@googlegroups.com, play-fram...@googlegroups.com
Is slick still planned to be the default SQL library in this version?

Julien Richard-Foy

oläst,
28 aug. 2014 07:06:282014-08-28
till play-fr...@googlegroups.com, play-fram...@googlegroups.com
Hi,

I’m playing with runtime DI and I don’t find how to programmatically add a module or a sequence of bindings to the application’s injector.

The play.modules file works well for the project scope but for tests I’d like to load a module just for a particular test.

My use case is the following: instead of letting the DI system create my component based on its @Inject annotated constructor, I want to define a binding to a mocked version of the component.

Chanan Braunstein

oläst,
28 aug. 2014 07:12:542014-08-28
till play-fr...@googlegroups.com, play-fram...@googlegroups.com
@Will Thanks for mentioning https://github.com/chanan/AkkaGuice  

I haven't updated it to the newer style of Actors in Akka 2.3 yet (AbstractActor), but if people want to use it, let me know and I will. (Or send pull requests).

Grzegorz Słowikowski

oläst,
29 aug. 2014 16:25:272014-08-29
till play-fr...@googlegroups.com, play-fram...@googlegroups.com
Hi

Why you removed all samples?

I tried to port scala/zentasks project to 2.4.0-M1, but it does not work.
When running tests, there is a problem with evolutions, for example:
[info] ApplicationSpec
[info]
[info] Application should
[info] ! go to login page without credentials
[error]    JdbcSQLException: : Dane nie sa dostepne
[error] No data is available [2000-175]  (DbException.java:332)
[error] org.h2.message.DbException.getJdbcSQLException(DbException.java:332)
[error] org.h2.message.DbException.get(DbException.java:172)
[error] org.h2.message.DbException.get(DbException.java:149)
[error] org.h2.message.DbException.get(DbException.java:138)
[error] org.h2.jdbc.JdbcResultSet.checkOnValidRow(JdbcResultSet.java:3111)
[error] org.h2.jdbc.JdbcResultSet.get(JdbcResultSet.java:3117)
[error] org.h2.jdbc.JdbcResultSet.getObject(JdbcResultSet.java:488)
[error] anorm.Sql$RowIterator$$anonfun$next$1.apply(Anorm.scala:439)
[error] anorm.Sql$RowIterator$$anonfun$next$1.apply(Anorm.scala:439)
[error] anorm.Sql$RowIterator.next(Anorm.scala:439)
[error] anorm.Sql$RowIterator.next(Anorm.scala:432)
[error] anorm.Sql$RowIterator.toStream(Anorm.scala:432)
[error] anorm.Sql$$anonfun$as$1.apply(Anorm.scala:423)
[error] anorm.Sql$$anonfun$as$1.apply(Anorm.scala:421)
[error] anorm.Sql$$anonfun$withIterator$2.apply(Anorm.scala:430)
[error] anorm.Sql$$anonfun$withIterator$2.apply(Anorm.scala:430)
[error] resource.AbstractManagedResource$$anonfun$5.apply(AbstractManagedResource.scala:86)
[error] resource.AbstractManagedResource.acquireFor(AbstractManagedResource.scala:86)
[error] resource.ManagedResourceOperations$$anon$2$$anonfun$acquireFor$1.apply(ManagedResourceOperations.scala:40)
[error] resource.ManagedResourceOperations$$anon$2$$anonfun$acquireFor$1.apply(ManagedResourceOperations.scala:40)
[error] resource.AbstractManagedResource$$anonfun$5.apply(AbstractManagedResource.scala:86)
[error] resource.AbstractManagedResource.acquireFor(AbstractManagedResource.scala:86)
[error] resource.ManagedResourceOperations$$anon$2.acquireFor(ManagedResourceOperations.scala:40)
[error] resource.DeferredExtractableManagedResource.acquireFor(AbstractManagedResource.scala:27)
[error] resource.ManagedResourceOperations$class.acquireAndGet(ManagedResourceOperations.scala:25)
[error] resource.DeferredExtractableManagedResource.acquireAndGet(AbstractManagedResource.scala:24)
[error] anorm.Sql$.as(Anorm.scala:427)
[error] anorm.Sql$class.as(Anorm.scala:329)
[error] anorm.SimpleSql.as(Anorm.scala:184)
[error] models.User$$anonfun$findAll$1.apply(User.scala:46)
[error] models.User$$anonfun$findAll$1.apply(User.scala:45)
[error] play.api.db.DefaultDatabase.withConnection(Database.scala:199)
[error] play.api.db.DB$.withConnection(DB.scala:59)
[error] models.User$.findAll(User.scala:45)
[error] InitialData$.insert(Global.scala:24)
[error] Global$.onStart(Global.scala:9)
[error] play.api.GlobalPlugin.onStart(GlobalSettings.scala:257)
[error] play.api.Play$$anonfun$start$1$$anonfun$apply$mcV$sp$1.apply(Play.scala:93)
[error] play.api.Play$$anonfun$start$1$$anonfun$apply$mcV$sp$1.apply(Play.scala:93)
[error] play.api.Play$$anonfun$start$1.apply$mcV$sp(Play.scala:93)
[error] play.api.Play$$anonfun$start$1.apply(Play.scala:93)
[error] play.api.Play$$anonfun$start$1.apply(Play.scala:93)
[error] play.utils.Threads$.withContextClassLoader(Threads.scala:21)
[error] play.api.Play$.start(Play.scala:92)
[error] play.api.test.PlayRunners$class.running(Helpers.scala:48)
[error] play.api.test.Helpers$.running(Helpers.scala:372)
[error] ApplicationSpec$$anonfun$1$$anonfun$apply$5.apply(ApplicationSpec.scala:16)
[error] ApplicationSpec$$anonfun$1$$anonfun$apply$5.apply(ApplicationSpec.scala:16)

Regards

Grzegorz Slowikowski

James Roper

oläst,
1 sep. 2014 00:59:322014-09-01
till play-framework, play-fram...@googlegroups.com
The samples have been super seeded by activator templates.  In some cases, the sample apps have been migrated to activator templates, such as the computer database sample:


In other cases, the sample apps were just deleted because there exist other activator templates that show the same things.

As for why the tests of zentasks are failing, I don't know, but I made it very clear that this release isn't production ready, and things are probably going to change massively (see my above email to Julien about testing) before the next release, so unless you can identify the root cause of the problem yourself, I'm not that interested in it.

Dominik Dorn

oläst,
14 sep. 2014 11:00:592014-09-14
till play-fr...@googlegroups.com, play-fram...@googlegroups.com
I'm trying to get 2.4.0-M1 (or the latest master from github) running but get 

[info] Done updating.
java.lang.NoSuchMethodError: play.PlayImport$PlayKeys$.playVersion()Lsbt/SettingKey;
at com.typesafe.sbt.SbtEchoPlay$.tracePlaySettings(SbtEchoPlay.scala:20)
at com.typesafe.sbt.SbtEchoPlay$.echoPlaySettings$lzycompute(SbtEchoPlay.scala:17)
at com.typesafe.sbt.SbtEchoPlay$.echoPlaySettings(SbtEchoPlay.scala:17)
at $654c7b75a7ba08f6551c$.$sbtdef(/home/domdorn/lyrix/lyrix_php/playlyrix/activator-sbt-echo-play-shim.sbt:1)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at sbt.compiler.Eval$.getValue(Eval.scala:420)
at sbt.compiler.Eval$$anonfun$4.apply(Eval.scala:87)
at sbt.compiler.Eval$$anonfun$4.apply(Eval.scala:87)
at sbt.EvaluateConfigurations$$anonfun$evaluateSetting$1.apply(EvaluateConfigurations.scala:150)
at sbt.EvaluateConfigurations$$anonfun$evaluateSetting$1.apply(EvaluateConfigurations.scala:148)
at sbt.EvaluateConfigurations$$anonfun$flatten$1$$anonfun$apply$5.apply(EvaluateConfigurations.scala:115)
at sbt.EvaluateConfigurations$$anonfun$flatten$1$$anonfun$apply$5.apply(EvaluateConfigurations.scala:115)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:251)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:251)
at scala.collection.AbstractTraversable.flatMap(Traversable.scala:105)
at sbt.EvaluateConfigurations$$anonfun$flatten$1.apply(EvaluateConfigurations.scala:115)
at sbt.EvaluateConfigurations$$anonfun$flatten$1.apply(EvaluateConfigurations.scala:115)
at sbt.EvaluateConfigurations$$anonfun$evaluateSbtFile$1.apply(EvaluateConfigurations.scala:110)
at sbt.EvaluateConfigurations$$anonfun$evaluateSbtFile$1.apply(EvaluateConfigurations.scala:110)
at sbt.Load$.sbt$Load$$loadSettingsFile$1(Load.scala:507)
at sbt.Load$$anonfun$sbt$Load$$memoLoadSettingsFile$1$1.apply(Load.scala:502)
at sbt.Load$$anonfun$sbt$Load$$memoLoadSettingsFile$1$1.apply(Load.scala:501)
at scala.Option.getOrElse(Option.scala:120)
at sbt.Load$.sbt$Load$$memoLoadSettingsFile$1(Load.scala:501)
at sbt.Load$$anonfun$loadSettings$1$2.apply(Load.scala:500)
at sbt.Load$$anonfun$loadSettings$1$2.apply(Load.scala:500)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:47)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
at sbt.Load$.loadSettings$1(Load.scala:500)
at sbt.Load$.sbt$Load$$expand$1(Load.scala:523)
at sbt.Load$.loadSettings(Load.scala:528)
at sbt.Load$.sbt$Load$$loadSbtFiles$1(Load.scala:464)
at sbt.Load$.defaultLoad$1(Load.scala:475)
at sbt.Load$.loadTransitive(Load.scala:478)
at sbt.Load$.loadProjects$1(Load.scala:418)
at sbt.Load$.loadUnit(Load.scala:419)
at sbt.Load$$anonfun$15$$anonfun$apply$11.apply(Load.scala:256)
at sbt.Load$$anonfun$15$$anonfun$apply$11.apply(Load.scala:256)
at sbt.BuildLoader$$anonfun$componentLoader$1$$anonfun$apply$4$$anonfun$apply$5$$anonfun$apply$6.apply(BuildLoader.scala:93)
at sbt.BuildLoader$$anonfun$componentLoader$1$$anonfun$apply$4$$anonfun$apply$5$$anonfun$apply$6.apply(BuildLoader.scala:92)
at sbt.BuildLoader.apply(BuildLoader.scala:143)
at sbt.Load$.loadAll(Load.scala:312)
at sbt.Load$.loadURI(Load.scala:264)
at sbt.Load$.load(Load.scala:260)
at sbt.Load$.load(Load.scala:251)
at sbt.Load$.apply(Load.scala:134)
at sbt.Load$.defaultLoad(Load.scala:37)
at sbt.BuiltinCommands$.doLoadProject(Main.scala:473)
at sbt.BuiltinCommands$$anonfun$loadProjectImpl$2.apply(Main.scala:467)
at sbt.BuiltinCommands$$anonfun$loadProjectImpl$2.apply(Main.scala:467)
at sbt.Command$$anonfun$applyEffect$1$$anonfun$apply$2.apply(Command.scala:60)
at sbt.Command$$anonfun$applyEffect$1$$anonfun$apply$2.apply(Command.scala:60)
at sbt.Command$$anonfun$applyEffect$2$$anonfun$apply$3.apply(Command.scala:62)
at sbt.Command$$anonfun$applyEffect$2$$anonfun$apply$3.apply(Command.scala:62)
at sbt.Command$.process(Command.scala:95)
at sbt.MainLoop$$anonfun$1$$anonfun$apply$1.apply(MainLoop.scala:100)
at sbt.MainLoop$$anonfun$1$$anonfun$apply$1.apply(MainLoop.scala:100)
at sbt.State$$anon$1.process(State.scala:179)
at sbt.MainLoop$$anonfun$1.apply(MainLoop.scala:100)
at sbt.MainLoop$$anonfun$1.apply(MainLoop.scala:100)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
at sbt.MainLoop$.next(MainLoop.scala:100)
at sbt.MainLoop$.run(MainLoop.scala:93)
at sbt.MainLoop$$anonfun$runWithNewLog$1.apply(MainLoop.scala:71)
at sbt.MainLoop$$anonfun$runWithNewLog$1.apply(MainLoop.scala:66)
at sbt.Using.apply(Using.scala:25)
at sbt.MainLoop$.runWithNewLog(MainLoop.scala:66)
at sbt.MainLoop$.runAndClearLast(MainLoop.scala:49)
at sbt.MainLoop$.runLoggedLoop(MainLoop.scala:33)
at sbt.MainLoop$.runLogged(MainLoop.scala:25)
at sbt.StandardMain$.runManaged(Main.scala:57)
at sbt.xMain.run(Main.scala:29)
at xsbt.boot.Launch$$anonfun$run$1.apply(Launch.scala:109)
at xsbt.boot.Launch$.withContextLoader(Launch.scala:129)
at xsbt.boot.Launch$.run(Launch.scala:109)
at xsbt.boot.Launch$$anonfun$apply$1.apply(Launch.scala:36)
at xsbt.boot.Launch$.launch(Launch.scala:117)
at xsbt.boot.Launch$.apply(Launch.scala:19)
at xsbt.boot.Boot$.runImpl(Boot.scala:44)
at xsbt.boot.Boot$.main(Boot.scala:20)
at xsbt.boot.Boot.main(Boot.scala)
[error] java.lang.NoSuchMethodError: play.PlayImport$PlayKeys$.playVersion()Lsbt/SettingKey;

When compiling from master, do I have to change anything else than 
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.4-SNAPSHOT")
?

Thanks,
Dominik

Christopher Hunt

oläst,
14 sep. 2014 15:39:182014-09-14
till play-fr...@googlegroups.com
Sounds like you may need to clean out your target folder.

Dominik Dorn

oläst,
14 sep. 2014 18:24:482014-09-14
till play-fr...@googlegroups.com
On Sunday, September 14, 2014 9:39:18 PM UTC+2, Christopher Hunt wrote:
Sounds like you may need to clean out your target folder.

nope... I found the problem.. its because of two things:
1. sbt-echo isn't ready for play 2.4 AND
2. play.PlayImport.PlayKeys is missing a 
val playVersion = SettingKey[String]("play.version")

which is used in sbt-echo.  

James Roper

oläst,
14 sep. 2014 22:23:082014-09-14
till play-framework
Use vanilla sbt instead.  Activator automatically includes sbt-echo, Play has no dependency on it and doesn't need it.  We might have to put playVersion back.

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Simon Ochsenreither

oläst,
16 sep. 2014 05:11:232014-09-16
till play-fr...@googlegroups.com, play-fram...@googlegroups.com
Really nice work!

One question: Why are the parentheses required after @Inject?
Imho, that looks really really ugly to the point of wishing to avoid DI completely.

James Roper

oläst,
16 sep. 2014 23:04:272014-09-16
till play-framework, play-fram...@googlegroups.com
Agree with the ugliness.  It's necessary because if you had this:

class Foo @Inject (bar: Bar) {
}

How would the scala compiler know whether to associate the (bar: Bar) as arguments to the annotation, or arguments to the constructor?  That is, should it be class Foo {} with its constructor annotated with @Inject(bar: Bar), or should it be Foo(bar: Bar) { } with it's constructor annotated with @Inject?  Hence Scala always forces annotations on the default constructor to include the parenthesis to avoid this ambiguity.

We're going to look into ways that we can make it nicer, either by creating a custom type level annotation for Guice, or by solving it in Scala.

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Pascal Voitot Dev

oläst,
17 sep. 2014 02:55:452014-09-17
till James Roper, play-framework, play-fram...@googlegroups.com
I couldn't participate to this discussion as I was busy on other subjects but the direction taken for compile-time injection (runtime is out of my scope) seems quite reasonable.
I need to test more & evaluate the most important cases (which aren't building the app itself but building fast modular test environments)

I'm also eager to see the router because I really would like to use "full code" router instead of the DSL one.

Pascal

--
You received this message because you are subscribed to the Google Groups "Play framework dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework-...@googlegroups.com.

Julien Richard-Foy

oläst,
17 sep. 2014 02:56:212014-09-17
till Pascal Voitot Dev, James Roper, play-framework, play-fram...@googlegroups.com
FYI the compile time router is available on github.

Pascal Voitot Dev

oläst,
17 sep. 2014 02:57:522014-09-17
till Julien Richard-Foy, James Roper, play-framework, play-fram...@googlegroups.com
On Wed, Sep 17, 2014 at 8:56 AM, Julien Richard-Foy <j...@zengularity.com> wrote:
FYI the compile time router is available on github.

Cool ;)

James Roper

oläst,
17 sep. 2014 21:29:522014-09-17
till Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
On Wed, Sep 17, 2014 at 4:54 PM, Pascal Voitot Dev <pascal.v...@gmail.com> wrote:
I couldn't participate to this discussion as I was busy on other subjects but the direction taken for compile-time injection (runtime is out of my scope) seems quite reasonable.
I need to test more & evaluate the most important cases (which aren't building the app itself but building fast modular test environments)

I'm also eager to see the router because I really would like to use "full code" router instead of the DSL one.

The new router still uses exactly the same routes file format, it's just that it extracts all the controllers out, and puts them as dependencies of the class.

If you want to implement a router with plain Scala code, we don't have any concrete plans to make these easier, except that the prefix is now much easier to handle, doesn't require mutating vars, eg:

case class MyRouter(fooDep: Foo, prefex: String = "/") extends Routes.Router {
  def withPrefix(prefix: String) = this.copy(prefix = prefix)
  def documentation = Nil
  def routes = {
    case ...
  }
}

As for defining the routes themselves, I've done some experimenting with some routing DSLs:


We're currently using this on playframework.com (with one change, it caches the compiled regular expressions in a global TrieMap, otherwise it would be very slow), it works pretty well.  It needs some more work before it could make it into Play, for example, it should handle url decoding, and we also need to work out how to handle query parameters nicely.  There's possibly also some macro magic that we could do to be able to extract out more than just Strings using PathBindable/QueryStringBindable, see Adrian's comment.  But at the moment we have no plans to actually do any of this work in any timeframe.

Greg Methvin

oläst,
19 sep. 2014 06:35:332014-09-19
till James Roper, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
In my most recent app I'm using the thin cake pattern for compile time DI (with MacWire). It seems pretty straightforward how to mix together traits to create the application, so that part is good.

My only confusion is, now that getControllerInstance is gone, how I should provide my controller instances to the application. Essentially I just need to pick the controllers out of a map compiled by the macro. Should I just be creating a new SimpleInjector?

The other thing that seems weird to me is that, in the GuiceApplicationLoader, the Guice "injector" is creating a new Application that contains an instance of the Play "injector", which is then used elsewhere to create instances dynamically, e.g. in Lang.availables(), Akka.system(), etc. Would my custom injector need to provide these as well?

I'd suggest we improve the docs for compile-time DI to discuss controllers, and also explain the purpose of the application's Injector and if/when you need to override it.

Thanks,
Greg

Julien Richard-Foy

oläst,
19 sep. 2014 07:30:172014-09-19
till Greg Methvin, James Roper, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
My only confusion is, now that getControllerInstance is gone, how I should provide my controller instances to the application. Essentially I just need to pick the controllers out of a map compiled by the macro. Should I just be creating a new SimpleInjector?

​That’s weird, in the rest of your message you are talking about Guice, which is for runtime DI.

If you want to achieve compile-time DI, you have to provide your own ApplicationLoader that creates your controllers, the Application and its Router, ​which uses your controllers.

Greg Methvin

oläst,
19 sep. 2014 07:58:342014-09-19
till Julien Richard-Foy, James Roper, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
On Fri, Sep 19, 2014 at 4:29 AM, Julien Richard-Foy <j...@zengularity.com> wrote:
​That’s weird, in the rest of your message you are talking about Guice, which is for runtime DI.

I was talking about Guice because that's the existing ApplicationLoader implementation, to understand what it's doing. I found it odd that the application has an instance of an injector, which is used to retrieve instances at runtime in parts of the Play codebase.

If you want to achieve compile-time DI, you have to provide your own ApplicationLoader that creates your controllers, the Application and its Router, ​which uses your controllers.

Maybe the Routes is the part I missed, which is obviously still being worked on.

Let me clarify what I'm trying to do. In my current apps I'm defining my controllers and their dependencies at compile time (wiring them up with Macwire), and then Play grabs the controller instances at runtime when it needs them. The only reason why that's done at runtime was because that was the easiest way to integrate with Play (through getControllerInstance). I was looking for how I (and other Macwire users) might migrate that approach to the new DI system.

Julien Richard-Foy

oläst,
19 sep. 2014 08:06:322014-09-19
till Greg Methvin, James Roper, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
Maybe the Routes is the part I missed, which is obviously still being worked on
​.

​Indeed, the injectable router has just been merged in trunk a few days ago.​

 
Let me clarify what I'm trying to do. In my current apps I'm defining my controllers and their dependencies at compile time (wiring them up with Macwire), and then Play grabs the controller instances at runtime when it needs them. The only reason why that's done at runtime was because that was the easiest way to integrate with Play (through getControllerInstance). I was looking for how I (and other Macwire users) might migrate that approach to the new DI system.

​But do you want to stick to compile-time DI or do you want to use Guice?​

Greg Methvin

oläst,
19 sep. 2014 18:25:312014-09-19
till Julien Richard-Foy, James Roper, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
On Fri, Sep 19, 2014 at 5:06 AM, Julien Richard-Foy <j...@zengularity.com> wrote:
​But do you want to stick to compile-time DI or do you want to use Guice?​
 
I'd like to do compile-time DI. I'm using this method in 2.3: http://www.warski.org/blog/2013/08/dependency-injection-in-play-with-macwire/. The controller instances are defined in a trait using thin cake pattern. It should be possible to either (a) provide Play with a map to access the classes of the trait, as is done currently, or (b) access the methods of my controllers trait in the routes file directly.

Does the current implementation require bypassing Play's built-in routes compiler completely to do what I'm trying to do?

Greg

Julien Richard-Foy

oläst,
20 sep. 2014 08:54:092014-09-20
till Greg Methvin, James Roper, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
Hi,

Ok, even though most of your wiring is manually done, the approach you were using with 2.3 still had a runtime level of indirection.

You can stick with this approach with 2.4. In this case, you have to define a Guice binding to resolve your manually wired components. See the “Providing custom bindings” section of the documentation: https://www.playframework.com/documentation/2.4.x/ScalaDependencyInjection

Or, you can switch to a complete compile-time DI solution. In this case, you have to provide your own ApplicationLoader. If your controllers are classes (instead of objects), you have to enable the injectable router generator and wire the router dependencies by yourself (or using macwire). See these pages:

Regards,
Julien

Greg Methvin

oläst,
21 sep. 2014 00:09:232014-09-21
till Julien Richard-Foy, James Roper, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
On Sat, Sep 20, 2014 at 5:53 AM, Julien Richard-Foy <j...@zengularity.com> wrote:
Or, you can switch to a complete compile-time DI solution. In this case, you have to provide your own ApplicationLoader. If your controllers are classes (instead of objects), you have to enable the injectable router generator and wire the router dependencies by yourself (or using macwire). See these pages:

Okay. Thanks for pointing out the injectable router generator. I set up a simple project (based on the 2.3 macwire example): https://github.com/gmethvin/play-macwire-di. I got the basics up and running, but I'm trying to solve a few issues:

1. The tests aren't working now because FakeApplication can't create GlobalSettings. It's trying to use the application's injector to do this. Is this supposed to work right now?

2. Play itself uses the application injector in a few places to get components, e.g. in the Crypto object, Lang.availables, Akka.system, Controller#requestToLang, etc. As long as those APIs exist, third-party modules for Play could use them, which means I need to provide an Injector which contains those instances. I tried to solve the problem by creating an injector which has a few of these instances, but it's tedious to do this considering we want the "default" instances anyway.

An inelegant but feasible solution for #2 would be to provide some easy way to fall back to the Guice injector, but it'd be nice to have a more lightweight way to provide the dependencies needed.

Greg


Greg Methvin

oläst,
21 sep. 2014 05:46:302014-09-21
till Julien Richard-Foy, James Roper, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
Actually, on second thought, we probably should remove or at least discourage the use of injector.instanceOf on the application. Blindly calling getInstance on the injector is generally considered an anti-pattern.

Still not sure how to solve the tests issue.

Greg 
 

Julien Richard-Foy

oläst,
21 sep. 2014 11:42:422014-09-21
till Greg Methvin, James Roper, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
2. Play itself uses the application injector in a few places to get components, e.g. in the Crypto object, Lang.availables, Akka.system, Controller#requestToLang, etc. As long as those APIs exist, third-party modules for Play could use them, which means I need to provide an Injector which contains those instances. I tried to solve the problem by creating an injector which has a few of these instances, but it's tedious to do this considering we want the "default" instances anyway.

​Did you have a look at the *Components classes? Notably BuiltInComponentsFromContext.​

Greg Methvin

oläst,
21 sep. 2014 14:12:132014-09-21
till Julien Richard-Foy, James Roper, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com

On Sun, Sep 21, 2014 at 8:42 AM, Julien Richard-Foy <j...@zengularity.com> wrote:
2. Play itself uses the application injector in a few places to get components, e.g. in the Crypto object, Lang.availables, Akka.system, Controller#requestToLang, etc. As long as those APIs exist, third-party modules for Play could use them, which means I need to provide an Injector which contains those instances. I tried to solve the problem by creating an injector which has a few of these instances, but it's tedious to do this considering we want the "default" instances anyway.

​Did you have a look at the *Components classes? Notably BuiltInComponentsFromContext.​

Those are what I was using (see https://github.com/gmethvin/play-macwire-di/blob/master/app/GreetingApplicationLoader.scala). They're great for compile-time DI in my own application, but don't add the components to the runtime injector used by Play to retrieve instances. I created a hack for doing this using the Macwire wiredInModule macro.

James Roper

oläst,
21 sep. 2014 21:29:332014-09-21
till Greg Methvin, Julien Richard-Foy, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
Hey Greg,

Thanks for trying things out.  As you've discovered, things are still in quite a state of flux.  The injectable routers were merged just last week, and right now I'm working on the docs for that.

For testing, this is still an area that needs a lot more work.  The end goal I think is to get rid of the requirement for FakeApplication.  FakeApplication should essentially just be a useful builder for applications when testing, allowing you to conveniently override configuration, provide additional routes, etc etc.  I would envision that some of this helper functionality will be pulled out of FakeApplication (eg the router), and that compile time injected applications wouldn't use FakeApplication at all, they'll just build their own application instances, utilising a few built in helper functions plus providing their own helper functions for their particular purposes.  One things for sure, this means our helpers need to be updated to depend on Application, not FakeApplication.

On the topic of things looking up components out of Injector all the time, this needs to be addressed on a case by case basis.  Take Lang.availables(), this should no longer be needed - I still need to update the docs for this.  The idea is that you should have a MessagesApi injected into you, and then either use the apply methods on it with an implicit lang that you've supplied, or use MessagesApi.preferred to get an instance of Messages for the preferred lang, which then has all the apply methods, but this time they don't take an implicit lang.  So this is what i18n might look like:

class Application(i18n: MessagesApi) extends Controller {
  def index = Action { req =>
    Ok(views.html.index(i18n.preferred(req)))
  }
}

index.scala.html:
@(messages: Messages) {
  <h1>@messages("title")</h1>
}

You could of course provide your own implicits there if you want to get rid of the boiler plate.  We may consider supplying some implicits in Play, but then I'm not sure - the implicit langs have been quite a source of confusion, for people that aren't familiar with Scala, it's very magic.  I'm not convinced that it's a good idea to supply these implicits by default in the framework - but this is a separate discussion.

There are a few places where it simply won't be possible to avoid accessing components via global state.  We have two options here, one is we can add methods to Application to provide access to them (expanding the Application API is not desirable though).  The other is we can make it easy to supply them via an injector.  So far I've gone with the latter, one example of this is access to Crypto (which things like the session needs via global state so that it can verify session signatures using the configured application secret).  On master, have a look at play.api.inject.SimpleInjector, and how play.api.BuiltInComponents uses that to provide Crypto.  There may be a few other things that we need to put in the SimpleInjector, my hope is that for Play 2.4, Play will handle this all transparently compile time injected applications don't need to worry at all about the injector.

In Play 3, a compile time injected application shouldn't need to provide an injector at all (session verification for example will probably be done up front, using header caching optimisations to compensate for the expense) but in Play 2.4, we'll be in an in between time where it will be needed for some things.

Cheers,

James



Greg Methvin

oläst,
21 sep. 2014 23:23:042014-09-21
till James Roper, Julien Richard-Foy, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
On Sun, Sep 21, 2014 at 6:28 PM, James Roper <ja...@typesafe.com> wrote:
For testing, this is still an area that needs a lot more work.  The end goal I think is to get rid of the requirement for FakeApplication.  FakeApplication should essentially just be a useful builder for applications when testing, allowing you to conveniently override configuration, provide additional routes, etc etc.  I would envision that some of this helper functionality will be pulled out of FakeApplication (eg the router), and that compile time injected applications wouldn't use FakeApplication at all, they'll just build their own application instances, utilising a few built in helper functions plus providing their own helper functions for their particular purposes.  One things for sure, this means our helpers need to be updated to depend on Application, not FakeApplication.

Maybe the helpers that initialize an application should take an ApplicationLoader? I'd think this would give you more control. I'm not sure we really need a FakeApplication in general, as long as we have easy ways to create applications with fake dependencies.

For runtime injection in tests we also should have a way to override bindings from the "default" injector. One solution is to just allow the user to configure their own injector (e.g. with Guice) and pass that in.

On the topic of things looking up components out of Injector all the time, this needs to be addressed on a case by case basis.  Take Lang.availables(), this should no longer be needed - I still need to update the docs for this.  The idea is that you should have a MessagesApi injected into you, and then either use the apply methods on it with an implicit lang that you've supplied, or use MessagesApi.preferred to get an instance of Messages for the preferred lang, which then has all the apply methods, but this time they don't take an implicit lang.

Great. I think getting the MessagesApi for a specific language is more clear than using the implicit lang.
 
There are a few places where it simply won't be possible to avoid accessing components via global state.  We have two options here, one is we can add methods to Application to provide access to them (expanding the Application API is not desirable though).  The other is we can make it easy to supply them via an injector.  So far I've gone with the latter, one example of this is access to Crypto (which things like the session needs via global state so that it can verify session signatures using the configured application secret).  On master, have a look at play.api.inject.SimpleInjector, and how play.api.BuiltInComponents uses that to provide Crypto.  There may be a few other things that we need to put in the SimpleInjector, my hope is that for Play 2.4, Play will handle this all transparently compile time injected applications don't need to worry at all about the injector.

I suppose if we have a lot more cases like this we'll just define more methods in our BuiltInComponents trait, so there will be no chance a compile-time DI user forgets to provide a component.

Thanks for your detailed reply addressing my concerns. It definitely seems like we're on the same page about where things are going.

Cheers,
Greg

James Roper

oläst,
21 sep. 2014 23:54:592014-09-21
till Greg Methvin, Julien Richard-Foy, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
On Mon, Sep 22, 2014 at 1:22 PM, Greg Methvin <greg.m...@gmail.com> wrote:
On Sun, Sep 21, 2014 at 6:28 PM, James Roper <ja...@typesafe.com> wrote:
For testing, this is still an area that needs a lot more work.  The end goal I think is to get rid of the requirement for FakeApplication.  FakeApplication should essentially just be a useful builder for applications when testing, allowing you to conveniently override configuration, provide additional routes, etc etc.  I would envision that some of this helper functionality will be pulled out of FakeApplication (eg the router), and that compile time injected applications wouldn't use FakeApplication at all, they'll just build their own application instances, utilising a few built in helper functions plus providing their own helper functions for their particular purposes.  One things for sure, this means our helpers need to be updated to depend on Application, not FakeApplication.

Maybe the helpers that initialize an application should take an ApplicationLoader? I'd think this would give you more control. I'm not sure we really need a FakeApplication in general, as long as we have easy ways to create applications with fake dependencies.

Taking an ApplicationLoader is definitely on the cards, and in fact Julien already submitted a pull request for this:


My main concern is that it makes things a little more complex - if I want an application that is customised for testing, then not only do I have to create something that wires that together, that thing has to implement ApplicationLoader.  Why not just take an application directly?  But, for the simple case where you don't want to customise the application for testing at all, taking an ApplicationLoader probably makes a lot of sense since you would already have one defined for dev mode.

I'd like to do a little more thinking/prototyping around the application customisation use cases, to work out what makes sense.  Since you're taking a look at this right now in the context of your applications, you may want to consider defining some helper/test APIs that would make testing your app simple, and then proposing them as pull requests in Play, or discussing them here first if you want feedback first.
 
For runtime injection in tests we also should have a way to override bindings from the "default" injector. One solution is to just allow the user to configure their own injector (e.g. with Guice) and pass that in.

That's one solution, there's also Julien's solution of being able to supply additional modules, there's also the possibility to allow override modules (this is a specific thing in Guice that's different to regular modules).  Since with runtime injection, Play provides most of the code to put your application together, this is where we need to do the most thinking around how users will want to customise the app.  Providing customisation here means opening up some of the internals of Play (not necessarily making things that are currently private public, but rather building the Play internals around how things are going to structured and potentially overridden in tests).  We want to ensure that whatever we provide gives a nice balance between the necessary power that people need in testing to mock things out in an easy to use, fluent API, while still keeping the core Play code clean and free of things that look weird at first until you realise that it's just there as a hook for testing.
 

On the topic of things looking up components out of Injector all the time, this needs to be addressed on a case by case basis.  Take Lang.availables(), this should no longer be needed - I still need to update the docs for this.  The idea is that you should have a MessagesApi injected into you, and then either use the apply methods on it with an implicit lang that you've supplied, or use MessagesApi.preferred to get an instance of Messages for the preferred lang, which then has all the apply methods, but this time they don't take an implicit lang.

Great. I think getting the MessagesApi for a specific language is more clear than using the implicit lang.
 
There are a few places where it simply won't be possible to avoid accessing components via global state.  We have two options here, one is we can add methods to Application to provide access to them (expanding the Application API is not desirable though).  The other is we can make it easy to supply them via an injector.  So far I've gone with the latter, one example of this is access to Crypto (which things like the session needs via global state so that it can verify session signatures using the configured application secret).  On master, have a look at play.api.inject.SimpleInjector, and how play.api.BuiltInComponents uses that to provide Crypto.  There may be a few other things that we need to put in the SimpleInjector, my hope is that for Play 2.4, Play will handle this all transparently compile time injected applications don't need to worry at all about the injector.

I suppose if we have a lot more cases like this we'll just define more methods in our BuiltInComponents trait, so there will be no chance a compile-time DI user forgets to provide a component.

Yes exactly.
 
Thanks for your detailed reply addressing my concerns. It definitely seems like we're on the same page about where things are going.

Cheers,
Greg

Yann Simon

oläst,
22 sep. 2014 05:28:042014-09-22
till James Roper, Greg Methvin, Julien Richard-Foy, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
I don't know if it is a limitation of Scala, but if I try to define an ApplicationLoader in another package as root, for example in globals, then the application cannot compile:

The code:
  lazy val routes: _root_.Routes = {
    val prefix = "/"
    wire[_root_.Routes]
  }

delivers the following error:

type Routes is not a member of package <root>
[error]   lazy val routes: _root_.Routes = {


--

Julien Richard-Foy

oläst,
22 sep. 2014 05:30:182014-09-22
till Yann Simon, James Roper, Greg Methvin, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
_root_.Routes is a value, not a type. What if you write _root.Routes.type instead?

Julien Richard-Foy

oläst,
22 sep. 2014 05:30:422014-09-22
till Yann Simon, James Roper, Greg Methvin, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
Anyway, what’s the point of defining the val prefix?

On Mon, Sep 22, 2014 at 11:29 AM, Julien Richard-Foy <j...@zengularity.com> wrote:
_root_.Routes is a value, not a type. What if you write _root.Routes.type instead?



Yann Simon

oläst,
22 sep. 2014 05:34:172014-09-22
till Julien Richard-Foy, James Roper, Greg Methvin, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
2014-09-22 11:29 GMT+02:00 Julien Richard-Foy <j...@zengularity.com>:
_root_.Routes is a value, not a type. What if you write _root.Routes.type instead?

Same problem:
object Routes is not a member of package <root>
[error]   lazy val routes: _root_.Routes.type = {

Yann Simon

oläst,
22 sep. 2014 07:37:112014-09-22
till Julien Richard-Foy, James Roper, Greg Methvin, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
I am to the point when the application compiles, but does not run.

$ sbt run
Detected sbt version 0.13.5
[info] Loading global plugins from /home/simon/.sbt/0.13/plugins
[info] Loading project definition from /home/simon/projects/play/apps/TPA/frontend/TBA_macwire/project
[info] Set current project to TBA_macwire (in build file:/home/simon/projects/play/apps/TPA/frontend/TBA_macwire/)

--- (Running the application from SBT, auto-reloading is enabled) ---

[info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:9000

(Server started, use Ctrl+D to stop and go back to the console...)


$ wget --no-proxy http://localhost:9000/
--2014-09-22 13:35:18--  http://localhost:9000/
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:9000... connected.
HTTP request sent, awaiting response... 

(wait wait... no response)

Do you have an idea where I should look at?

Greg Methvin

oläst,
22 sep. 2014 21:08:172014-09-22
till Yann Simon, Julien Richard-Foy, James Roper, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
It looks like there is a circular dependency. Your components should not depend on the application; they're injected into the application and your other components. For your WSClient I would suggest mixing in NingWSComponents. The WS.client(application) API is designed for applications that rely on global state to use after the application is created.

Julien Richard-Foy

oläst,
23 sep. 2014 02:53:322014-09-23
till Greg Methvin, Yann Simon, James Roper, Pascal Voitot Dev, play-framework, play-fram...@googlegroups.com
Maybe we should deprecate the WS.client method. Users should either use injector.instanceOf[WSApi] or NingWSComponents (regarding that they want to use either runtime or compile-time DI).

Looks like there will be a lot of changes with 2.4.

Simon Ochsenreither

oläst,
2 okt. 2014 17:17:572014-10-02
till play-fr...@googlegroups.com, play-fram...@googlegroups.com
I wonder if this could be improved somehow from a scalac POV. E. g. the compiler of course knows that @Inject doesn't take any arguments...

James Roper

oläst,
3 okt. 2014 00:58:122014-10-03
till play-framework, play-fram...@googlegroups.com
On Fri, Oct 3, 2014 at 7:17 AM, Simon Ochsenreither <simon.och...@gmail.com> wrote:
I wonder if this could be improved somehow from a scalac POV. E. g. the compiler of course knows that @Inject doesn't take any arguments...

It will be improved in Scala 2.12, I've recently talked to the Scala team about this, and they've said they will do it:


Once that's implemented, we'll be able to do something like this in Play:

package play.api

package object inject {
  type Inject = javax.inject.Inject @primaryConstructor 
}

Which will allow Play users to do this:

import play.api.inject.Inject

@Inject
class MyComponent(ws: WSClient) {
}

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Svara alla
Svara författaren
Vidarebefordra
0 nya meddelanden