Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document that Filter beans are eagerly initialized #17814

Closed
caspianb opened this issue Aug 8, 2019 · 1 comment
Closed

Document that Filter beans are eagerly initialized #17814

caspianb opened this issue Aug 8, 2019 · 1 comment
Labels
type: documentation A documentation update
Milestone

Comments

@caspianb
Copy link

caspianb commented Aug 8, 2019

See sample code in branch to reproduce issue: https://github.com/caspianb/SpringBootTest/tree/feature/filter-proxy-bug

I reproduced this issue in at least the following spring boot versions (2.1.0, 2.1.4, 2.1.6, 2.1.7).

Spring is not properly injecting the proxied threadLocalTargetSource for a prototype bean for the first Filter it injects the bean into. It seems ONLY Filter classes have this issue -- if I do not enable filters (e.g. remove @Component annotation from filters) in the above linked project the interceptor and user controller still work properly -- so it does not appear to simply be a "which class was loaded first" issue.

Starting the above sample application and accessing the root page will log output that demonstrates the issue:

  • The first filter loaded by Spring will contain the direct TenantStore bean.
  • Every other component (including the second filter) will properly have the proxiedLocalThreadTargetSource TenantStore bean.

Example of issue:

// First Request
[http-nio-8080-exec-1] INFO  AuthFilterA: 1. TenantStore@1363509553 tenant=null
[http-nio-8080-exec-1] INFO  AuthFilterA: 2. TenantStore@1363509553 tenant=John Doe
[http-nio-8080-exec-1] INFO  AuthFilterB: 1. TenantStore@1280546379 tenant=null
[http-nio-8080-exec-1] INFO  AuthFilterB: 2. TenantStore@1280546379 tenant=John Doe
[http-nio-8080-exec-1] INFO  AuthInterceptor: 1. TenantStore@1280546379 tenant=John Doe
[http-nio-8080-exec-1] INFO  AuthInterceptor: 2. TenantStore@1280546379 tenant=John Doe
[http-nio-8080-exec-1] INFO  AuthController: TenantStore@1280546379 tenant=John Doe
[http-nio-8080-exec-1] INFO  AuthInterceptor: 3. TenantStore@1280546379 tenant=John Doe
[http-nio-8080-exec-1] INFO  AuthInterceptor: 4. TenantStore@1280546379 tenant=null

// Second Request
[http-nio-8080-exec-3] INFO  AuthFilterA: 1. TenantStore@1363509553 tenant=John Doe
[http-nio-8080-exec-3] INFO  AuthFilterA: 2. TenantStore@1363509553 tenant=John Doe
[http-nio-8080-exec-3] INFO  AuthFilterB: 1. TenantStore@1703933351 tenant=null
[http-nio-8080-exec-3] INFO  AuthFilterB: 2. TenantStore@1703933351 tenant=John Doe
[http-nio-8080-exec-3] INFO  AuthInterceptor: 1. TenantStore@1703933351 tenant=John Doe
[http-nio-8080-exec-3] INFO  AuthInterceptor: 2. TenantStore@1703933351 tenant=John Doe
[http-nio-8080-exec-3] INFO  AuthController: TenantStore@1703933351 tenant=John Doe
[http-nio-8080-exec-3] INFO  AuthInterceptor: 3. TenantStore@1703933351 tenant=John Doe
[http-nio-8080-exec-3] INFO  AuthInterceptor: 4. TenantStore@1703933351 tenant=null

You can see AuthFilterA has a different TenantStore bean than all other beans. Further, this bean is maintained across all requests (since AuthFilterA is a singleton holding onto a simple prototype bean).

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 8, 2019
@caspianb caspianb changed the title ProxyFactoryBean / ThreadLocalTargetSource for prototype bean is being properly set on Filter ProxyFactoryBean / ThreadLocalTargetSource for prototype bean notbeing properly set on Filter Aug 9, 2019
@caspianb caspianb changed the title ProxyFactoryBean / ThreadLocalTargetSource for prototype bean notbeing properly set on Filter ProxyFactoryBean / ThreadLocalTargetSource for prototype bean not being properly set on Filter Aug 9, 2019
@snicoll
Copy link
Member

snicoll commented Aug 9, 2019

@caspianb thanks for the report and the sample. Discussing with @jhoeller, it looks like lifecycle semantics can be tricky here, since the Servlet container probably wants Filter instances registered, and that very early on. the Filter-as-a-bean model comes with early-init implications for the affected beans.

I've changed the constructor of both your filters to use @Lazy, e.g.

public AuthFilterA(@Lazy TenantStore tenantStore) {
	this.tenantStore = tenantStore;
}

and the same instance is now shared by both filters. Lazy retrieval of target beans is unavoidable in such a scenario. Let's turn this into a documentation issue.

@snicoll snicoll added type: documentation A documentation update and removed status: waiting-for-triage An issue we've not yet triaged labels Aug 9, 2019
@snicoll snicoll added this to the 2.1.x milestone Aug 9, 2019
@snicoll snicoll changed the title ProxyFactoryBean / ThreadLocalTargetSource for prototype bean not being properly set on Filter Document that Servlet and Filter beans are eagerly initialized Aug 9, 2019
@philwebb philwebb changed the title Document that Servlet and Filter beans are eagerly initialized Document that Filter beans are eagerly initialized Aug 31, 2019
@philwebb philwebb modified the milestones: 2.1.x, 2.1.8 Aug 31, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: documentation A documentation update
Projects
None yet
Development

No branches or pull requests

4 participants