berndhopp / guice

guice-integration for the vaadin-framework
https://vaadin.com/directory#!addon/guice-vaadin-integration
10 stars 7 forks source link

Filter support #15

Closed bcmedeiros closed 6 years ago

bcmedeiros commented 6 years ago

I'm trying to set up some security javax.servlet.Filters in Vaadin 10 and I realized that injector is being created in servlet init(), not in a context listener, thus not available during the filter init().

Is it really by design? Is there any way to set a filter using the injector that would be able to filter the VaadinServlet itself?

berndhopp commented 6 years ago

It is by design, because the web.xml-parameters like 'packages-to-scan' are not available at earlier stages, AFAIK.

bcmedeiros commented 5 years ago

@berndhopp, after having a deeper look at this, I don't think I agree with this design.

Having the injector creation being performed at servlet init phase prevent to both:

  1. Have a filter that also needs to inject some fields using the injector.
  2. Use the guice-servlet extension, which someone might one to use.

In my case here I need to put a filter on /* for security purposes and I simply can't achieve that as the injector is not even created when the filter is initialized.

I have forked the project and created a branch with the approach I believe is a better choice, can you have a look at that?

https://github.com/brunojcm/guice/tree/config-with-listener

I'm happy to fix the tests and provide a proper PR if you like it.

With the approach in this branch, I can do the following (kotlin code):

@WebListener
@PackagesToScan(
        "com.company.internal.p.core.inject",
        "com.company.internal.p.auth",
        "com.company.internal.p.ui"
)
class ApplicationVaadinListener: GuiceVaadinListener()

@WebFilter(urlPatterns = ["/*"])
class ApplicationShiroFilter: AbstractShiroFilter() {
    override fun init() {
        val injector = getContextAttribute(Injector::class.java.name) as Injector
        this.securityManager = injector.getInstance(WebSecurityManager::class.java)
        this.filterChainResolver = injector.getInstance(FilterChainResolver::class.java)
        super.init()
    }
}

@WebServlet(urlPatterns = ["/*"])
@com.vaadin.guice.annotation.PackagesToScan(
        "com.company.internal.p.ui"
)
class ApplicationVaadinServlet: com.vaadin.guice.server.GuiceVaadinServlet()

In this approach, @PackagesToScan is performing two roles here, in the Listener it's scanning Guice modules only, whereas in the Servlet it is looking for UIs, VaadinServiceInitListeners, etc.

berndhopp commented 5 years ago

Could you create a PR please? Makes it easier to discuss. It is however required that we maintain Api compatibility, so that a plain guicevaadinservlet will still work.