I am learning about bean scopes in Spring and going through this link it says the bean behaves as a singleton across multiple servlet-based applications running in the same ServletContext. I am confused about what does servlet context refer to. Does it refer to the container like tomcat because they refer to multiple servlet based applications. As i understand it, it means if i have multiple web apps deployed on a single tomcat instance and i want these apps to refer/share an object then i create an application scoped bean?
Please help if my understanding is correct.
5 Scopes of Spring Bean:
1.Singleton
2.Prototype
These scope will only work for a web application
3.Request
4.Session
5.Application
How to define scope in .xml configuration file:
Singleton bean:
By default ApplicationContext has a singleton scope.This means only one object will be c
created. And if we call 'n' number of getBean() then all the bean will point to the same
bean. Constructor will only be called once.
Prototype:
Will create a new bean each time getBean() is called.
Each bean will have its own hashcode.
#ApplicationScope:
Scopes a single bean definition to the lifecycle of a ServletContext.
Only valid in the context of a web-aware Spring ApplicationContext.
Bean Initialization:
When does a 'prototype' scoped bean and a singleton scoped bean gets initialized?
Singleton scoped beans initialize when the container starts.
Prototype scoped beans initialize when we ask for it using the getBean() method.
Prototype bean also gets intialize when it is used as a dependency inside a singleton
scoped bean.
How to inject security context into CDI #Named bean?
I need to perform some custom validations, like dynamic role names validation, so I need to inject SessionContext. This is done with this:
#Resource
javax.ejb.SessionContext context;
But this injection only works in EJB beans, so I need to create an #Stateless bean just to wrap SessionContext, then I can inject this stateless bean into named bean and use it to access the security context.
I have tried with #Inject javax.security.enterprise.SecurityContext also, but this do not work at all.
Obs. If there is another approach, this will be welcome too!
Environment:
Wildfly 24
Java SE 11
References
No EjbContext available
https://www.baeldung.com/java-ee-8-security
Recently, I came into the situation where I needed to reload the Spring Bean instance. Because this bean is using an external yml file which updates sometimes. The requirement is to reinitialize the bean instance after any change in the YML file.
Using Spring Boot 1.5.12, we create scoped proxies for #ConfigurationProperties beans. We do this so that we can effectively have property values that are scoped to the user/session/etc. We use a BeanFactoryPostProcessor to register a scoped proxy created by ScopedProxyUtils.createScopedProxy and change the scope of the target bean definition to our custom scope.
This worked great in Spring Boot 1.5.12. However, in Spring Boot 2, the introduction of the Binder API has made this stop working. This is because when Spring Boot binds #ConfigurationProperties in its ConfigurationPropertiesBindingPostProcessor, it uses Bindable.of(type).withExistingValue(bean) passing in a type (e.g. org.example.Foo) and the bean which is an instance of ScopedProxyFactoryBean. Bindable checks that bean is an instance of type which it's not and things blow up.
Does anyone know of a general way to accomplish this? Specifically, to replace the #ConfigurationProperties bean definition with a proxy while still allowing the properties to bind to the instance? I've considered delaying the creation of the proxy until after the target has already been bound by ConfigurationPropertiesBindingPostProcessor (i.e. in my own BeanPostProcessor). However, at this point the bean is instantiated and my proxy can only replace the bean. It can't really leave the original bean in the context as a target. So I'm struggling with how to do this using a BeanPostProcessor.
EDIT: I've created a simple example project that demonstrates the issue (with the ability to check out code that works on Spring Boot 1 and fails on Spring Boot 2).
I need to inject a Spring bean into a Seam context. Unless I declare the spring bean as a EJB, I cannot get it injected into other seam-managed components. But when I do this, all the spring injected fields are usless cause Seam creates new instances at run-time.
I also tried to add the <seam:component/> element to the spring bean definition and tried to inject it in the container with the #In("beanId") annotation in the target class but I always end up with a NullpointerException...
EDIT:
I read the online articles and did as they say. My spring component is also added to the seam context (I can tell, cause when I define one with the same ID in seam, it complains). Looks like #In is not picking up....
Have you read this chapter? It should tell you exactly what to do.
Raoul,
Although i do not use Seam along with Spring, chapter 15 of Seam In Action books talks about Spring integration. It is free and is updated.
You have said
I also tried to add the element to the spring bean definition and tried to inject it in the container with the #In("beanId")
Seam in Action book says
The EL expression used in the #In annotation, #{tournamentManager}, resolves to an equivalently named bean in the Spring container, courtesy of the delegating variable resolver
Do you have to use #In("#{beanId}") instead of #In("beanId"), do not ?
I have seen
By default, <seam:component/> will create a STATELESS Seam component with class and name provided in the bean definition.
<bean id="someSpringBean" class="SomeSpringBeanClass" scope="prototype">
<seam:component/>
</bean>
And
The scope attribute of <seam:component/> may be used if you wish the Spring bean to be
managed in a particular Seam scope. The Spring bean must be scoped to prototype if the
Seam scope specified is anything other than STATELESS.
Have you done as above ?
I have a project using Seam + Spring and I have to set #In(create=true) when I want to inject a Spring bean into my Seam component otherwise I get a NullPointerException, you should try it.
I got the same problem as yours. I followed strictly the "Chapter 27. Spring Framework integration" in seam ref. document. But my spring bean was never got injected to seam component. And finally, I found out I had the #BypassInterceptors in my seam component. By removing that annotation, my spring bean was successfully injected. Then I realized that, dependency injection is handled by seam BijectionInterceptor. Thus, the #BypassInterceptors will effectively bypass this filter :)