Deadbolt depends on global state :(
Closed this issue · 8 comments
Hi Steve,
if you set play.allowGlobalApplication = false
in your application.conf
apps using deadbolt helpers will break.
You probably already know that.
That's because all your helpers import the current play application:
https://github.com/schaloner/deadbolt-2-java/blob/v2.5.5/code/app/be/objectify/deadbolt/java/views/restrict.scala.html#L5
which unfortunately is needed for the implicit import one line above - which then boils down to this here:
https://github.com/schaloner/deadbolt-2-java/blob/v2.5.5/code/app/be/objectify/deadbolt/java/ViewAccessPoint.scala#L31-L33
How can we get rid of the global app dependency in deadbolt?
I've been thinking about this, and I don't want to break backwards compatibility. I think the way forward is to extract anything linked to global state into a separate companion library and have purely DI components in the core. This means, off the top of my head, ViewAccessPoint and all templates. The new DI templates that will exist in the core will have a package shift to views.di.XXX to avoid conflicts.
Any thoughts on this approach?
I think this is a very good approach. Actually I was thinking in the same direction during I put #38 together.
Hi,
I've pulled out the global state (mostly views) into this library: https://github.com/schaloner/deadbolt-2-java-global-state
The templates in this library are now in views.di
. All tests, etc, updated but there's probably a bunch more stuff I need to do, like expose the templates via a module. I'll get on this and documentation tomorrow.
This is really awesome, thanks! I will try and give you feedback as soon as possible (probably Monday)
I've also added you as a collaborator for the new repo
Hi,
I am currently migrating from Play 2.5 to 2.6 and have to upgrade Deadbolt too.
In my project I am using template constraints like @restrict
and want to continue to use them. I have seen that you removed the way they worked before in favor of injected templates what I think is the right way to go. However I have no clue what I have to inject so I would appreciate it if you could give an example how to do that. Your manual is mentioning that I could still use the Global State by importing another dependency but I do not want to do that so my project is as future-proof as possible.
Hi,
to use dependency injection in templates, you have to have your templates injected into your controllers. For example, if you have a controller that uses a template called foo
, under the 2.5 way of doing things, you would have something like
import com.example.views.html.foo;
public class Bar extends Controller {
public Result somethingFoo() {
return ok(foo.render())
}
}
Under 2.6 with dependency injection, you just need to change this to
import com.example.views.html.foo;
public class Bar extends Controller {
private final foo fooTemplate;
@javax.inject.Inject
public Bar(final foo fooTemplate) {
this.fooTemplate = fooTemplate;
}
public Result somethingFoo() {
return ok(fooTemplate.render())
}
}
This means you're calling ´render´ on an instance of ´foo´.
Within the foo
template, you also need to add what you essentially thing of as a constructor. So, instead of
@import be.objectify.deadbolt.java.views.html.subjectPresent
@subjectPresent() {
something
}
instead, you need to inject Deadbolt support like this
@this(subjectPresent: be.objectify.deadbolt.java.views.html.subjectPresent)
@subjectPresent() {
something
}
I dropped the import in the second example to make it clearer what you're importing.
I hope this helps, and if something still isn't clear then please let me know. This example will be going into the documentation, so thanks for triggering that.
Regards,
Steve
@schaloner Thanks for this, the DI approach is working great for me!