I have spring bean called Executor I need this executor to be Injected in two classes one is session scoped and the other is singleton, So I use #Autowired annotation to inject it in both, it works very fine, But for the session bean the executor is only one for all sessions, and I understand this is how it should work.
How can I make the executor take the scope of the bean its injected into ? now all I could do is use two different classes for each.
And I cant realy understand the effect of setting the attribute scoped-proxy in
<context-component-scan /> to targetClass.
EDIT
Here is my try out for prototype scope:
suppose this is my session soped bean
#Component
#Scope("session")
public class WebExecutor(){
#Autowired
private ExecutorService executor;
#Async
public void startCalc(){
executor.start("now");
}
}
And this is my ExecutorService class
#Component
#Scope("prototype")
public class ExecutorService{
private int progress;
public void start(String when){
//do some stuff and increment the progress
}
//getter and setter for progress
}
I also have another component with default singleton scope which autowires the executor as well, so the executor can't be session scoped.
So now I have one class needed to have the scope of the bean it is being autowired in, So I tried the prototype scope.
How this should work in the Web versions is like this
You click a link that begins the execution which calls the method start of the WebExecutor
Then I get the progress from the ExecutorService using the WebParser and pass it back to the user to report the progress.
This was working great before prototype but the ExecutorService was one for all sessions,
so the I used prototype but now the progress is always 0, and when I debugged the Executor I found that it was incrementing but apprentally the WebExecutor could not see the increment.
U can use prototype scope. Then it will inject new instance of Executor when the Bean is constructed. So Executor starts its lifecycle when the bean is created.
scoped-proxy=target-class creates CGLIB wrapper around your bean. So other beans holds reference only to this wrapper, and the right bean with right scope is dynamically injected into this wrapper.
i.e. you don't hold very old expired request scoped bean in your session scoped bean, probably injected when the session was created . Instead new bean for current request is injected every time new request is created. This way you can access beans whith shorter life from beans with longer life i.e. your request scoped bean from your session scoped bean.
Related
I am porting an existing JBOSS JEE application to Quarkus. I am using a number of HV custom validators that require injection.
For that purpose I've defined all custom validators that require injection as bean in my libraries like this:
#ApplicationScoped
public class SomeValidator implements ConstraintValidator<SomeValidation, AnObject> {
#Inject
public BeanUsingEntityManager bean;
Note: It is common code, so it should remain working on JBOSS as well
Next I defined a REST service. The REST service makes use of an application scoped bean like this.
#ApplicationScoped
public class ApplicationContext {
#PersistenceContext( unitName = "A" )
EntityManager em;
#Produces
#EnityManagerA // required qualifier to make datasource unique in JEE context (there are more)
public EntityManager produce() {
return em;
}
// NOTE: quarkus does not allow the #Produces on a field, which is allowed in JBOSS hence the method
#Produces
public BeanUsingEntityManager createBeanUsingEntityManager () {
// some logic that requires the entity manager.
}
}
Now the problem is simplified, but I keep on running into an error message.
Caused by: javax.enterprise.inject.CreationException: Synthetic bean instance for javax.persistence.EntityManager not initialized yet: javax_persistence_EntityManager_b60c51739990fc921960fc78caeb075a811a91a6
- a synthetic bean initialized during RUNTIME_INIT must not be accessed during STATIC_INIT
- RUNTIME_INIT build steps that require access to synthetic beans initialized during RUNTIME_INIT should consume the SyntheticBeansRuntimeInitBuildItem
at javax.persistence.EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.create(EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.zig:167)
at javax.persistence.EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.create(EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.zig:190)
at io.quarkus.arc.impl.AbstractSharedContext.createInstanceHandle(AbstractSharedContext.java:96)
at io.quarkus.arc.impl.AbstractSharedContext.access$000(AbstractSharedContext.java:14)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:29)
at io.quarkus.arc.impl.AbstractSharedContext$1.get(AbstractSharedContext.java:26)
at io.quarkus.arc.impl.LazyValue.get(LazyValue.java:26)
at io.quarkus.arc.impl.ComputingCache.computeIfAbsent(ComputingCache.java:69)
at io.quarkus.arc.impl.AbstractSharedContext.get(AbstractSharedContext.java:26)
at javax.persistence.EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.get(EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.zig:222)
at javax.persistence.EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.get(EntityManager_e1903961aa3b05f292293ca76e991dd812f3e90e_Synthetic_Bean.zig:238)
at nl.bro.gm.gmw.dispatch.resources.ApplicationContext_Bean.create(ApplicationContext_Bean.zig:131)
... 59 more
I'm new to Quarkus. So, not sure to how to handle this issue or even if I make the correct assumptions. I can imagine that Quarkus wants to give me a fresh entitymanager each request (which I understand), but that poses a problem for my application scoped beans.
What am I doing wrong here?
So, the full answer is that the EntityManager is created at the runtime init phase whereas the ValidatorFactory (and the ConstraintValidators) are created at static init time.
The Quarkus bootstrap goes static init -> runtime init.
So in your case, you can't access a #Singleton bean which uses the EntityManager during static init as it's not yet available.
Making your bean #ApplicationScoped will create a proxy and avoid this chicken and egg problem.
You will have only one BeanUsingEntityManager for your whole application.
The EntityManager is a bit different because we wrap it and you will get one new EntityManager/Session per transaction, which is what is expected as EntityManagers/Sessions are not thread safe.
I'm a bit confused about using method injection (lookup-method) and aop scoped-proxy (Since both used for different scoped beans injection) so
1) When to use method injection and when to use aop-scoped proxy ?
2) What is the reason why a aop-scoped proxy will not be used for a prototype bean ?
Both lookup method injection and scoped proxy are means to inject shorter lived beans into longer lived beans. However, they serve different use cases.
Method injection is useful in cases where a singleton-scoped bean has a dependency on a prototype-scoped bean.
A proxy gets injected in place of the desired bean and provides that bean depending on the context. For example, if a singleton bean (such as a Spring MVC controller) auto-wires a session scoped bean, then the proxy delivers that bean belonging to the current HTTP session.
Such a proxy doesn't apply well to a situation where a prototype bean shall be obtained at runtime. Lookup method injection is one way to obtain prototype instances at runtime.
However, method injection has limitations because it builds upon abstract methods. Hence, certain things like writing unit tests are more cumbersome, as you need to provide a stub implementation of the abstract method. Component scanning doesn't work with abstract classes either.
One alternative to method injection is Spring's ObjectFactory, or its JSR equivalent Provider.
Another, straightforward way of creating prototype bean instances at runtime (which even makes it possible to provide constructor arguments) is to implement a bean factory like the following:
#Configuration
public class MyProvider {
#Bean
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public MyThing create(String name) {
return new MyThing(name);
}
}
Usage:
#Component
public class MySingleton {
#Autowired
private MyProvider myProvider;
public void doStuffThatNeedsAPrototypeBeanInstance() {
MyThing thing = myProvider.create("some name");
...
}
}
For the question 1. When to use method injection and when to use aop-scoped proxy?
Let's say you have a singleton bean A has dependency on the prototype bean B. A has a method m which has B involved.
You got the object a of A and execute the method m several times. Every time m executing, a new object b of B needs to inject to a. That's the time you use the method injection.
Besides, if you have a singleton bean A has dependency on the session bean B. A has a method m which has B involved.
You got the object a of A and execute the method m several times. As long as the execution time is in a same session, a has the same object b of B. That's the time you use proxy.
How many times Spring is calling single Singleton constructor?
In which cases constructor can be called more than one time (for bean with the same id)?
EDIT:
HERE is an answer that user is telling that can be more than once - I need more explanation for that.
How many times Spring is calling single Singleton constructor?
Only once; The default Bean Scope is singleton.
In which cases constructor can be called more than one time (for bean with same id)?
Take a look at Bean Scopes
Scope Description
singleton
Scopes a single bean definition to a single object instance per Spring IoC container.
prototype
Scopes a single bean definition to any number of object instances.
request
Scopes a single bean definition to the lifecycle of a single HTTP request; that is each and every HTTP request will have its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
session
Scopes a single bean definition to the lifecycle of a HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
global session
Scopes a single bean definition to the lifecycle of a global HTTP Session. Typically only valid when used in a portlet context. Only valid in the context of a web-aware Spring ApplicationContext.
What you need is scope prototype
So add a #Scope("prototype") to your bean definition like this:
#Bean
#Scope("prototype") //add this
public MyBean myBean()
{
return new MyBean();
}
I am studying for the Spring Core certification an I have some doubts about how Spring handle the beans lifecycle and in particular about the bean post processor.
So I have this schema:
It is pretty clear for me what it means:
The following steps take place in the Load Bean Definitions phase:
The #Configuration classes are processed and/or #Components are
scanned for and/or XML files are parsed.
Bean definitions added to BeanFactory (each indexed under its id)
Special BeanFactoryPostProcessor beans invoked, it can modify the definition of any bean (for example for the property-placeholder values replacements).
Then the following steps take place in the beans creation phase:
Each bean is eagerly instantiated by default (created in right order with its dependencies injected).
After dependency injection each bean goes through a post-processing
phase in which further configuration and initialization may occur.
After post processing the bean is fully initialized and ready for use (tracked by its id until the context is destroyed)
Ok, this is pretty clear for me and I also know that there are two types of bean post processors which are:
Initializers: Initialize the bean if instructed (i.e. #PostConstruct).
and All the rest: that allow for additional configuration and that may run before or after the initialize step
And I post this slide:
So it is very clear for me what does the initializers bean post processors (they are the methods annotated with #PostContruct annotation and that are automatically called immediately after the setter methods (so after the dependency injection), and I know that I can use to perform some initialization batch (as populate a cache as in the previous example).
But what exactly represents the other bean post processor? What do we mean when we say that these steps are performed before or after the initialization phase?
So my beans are instantiated and its dependencies are injected, so then the initialization phase is completed (by the execution of a #PostContruct annotated method). What do we mean by saying that a Bean Post Processor is used before the initialization phase? It means that it happens before the #PostContruct annotated method execution? Does it means that it could happen before the dependency injection (before that the setter methods are called)?
And what exactly do we mean when we say that it is performed after the initialization step. It means that it happens after that the execution of a #PostContruct annotated method, or what?
I can easily figure into my head why I need a #PostContruct annotated method but I can't figure some typical example of the other kind of bean post processor, can you show me some typical example of when are used?
Spring doc explains the BPPs under Customizing beans using BeanPostProcessor. BPP beans are a special kind of beans that get created before any other beans and interact with newly created beans. With this construct, Spring gives you means to hook-up to and customize the lifecycle behavior simply by implementing a BeanPostProcessor yourself.
Having a custom BPP like
public class CustomBeanPostProcessor implements BeanPostProcessor {
public CustomBeanPostProcessor() {
System.out.println("0. Spring calls constructor");
}
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
System.out.println(bean.getClass() + " " + beanName);
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out.println(bean.getClass() + " " + beanName);
return bean;
}
}
would be called and print out the class and bean name for every created bean.
To undersand how the method fit the bean's lifecycle, and when exactly the method's get called check the docs
postProcessBeforeInitialization(Object bean, String beanName) Apply
this BeanPostProcessor to the given new bean instance before any bean
initialization callbacks (like InitializingBean's afterPropertiesSet
or a custom init-method).
postProcessAfterInitialization(Object bean, String beanName) Apply
this BeanPostProcessor to the given new bean instance after any bean
initialization callbacks (like InitializingBean's afterPropertiesSet
or a custom init-method).
The important bit is also that
The bean will already be populated with property values.
For what concerns the relation with the #PostConstruct note that this annotation is a convenient way of declaring a postProcessAfterInitialization method, and Spring becomes aware of it when you either by registerCommonAnnotationBeanPostProcessor or specify the <context:annotation-config /> in bean configuration file. Whether the #PostConstruct method will execute before or after any other postProcessAfterInitialization depends on the order property
You can configure multiple BeanPostProcessor instances, and you can
control the order in which these BeanPostProcessors execute by setting
the order property.
The typical example for a bean post processor is when you want to wrap the original bean in a proxy instance, e.g. when using the #Transactional annotation.
The bean post processor will be handed the original instance of the bean, it may call any methods on the target, but it also gets to return the actual bean instance that should be bound in the application context, which means that it can actually return any object it wants. The typical scenario when this is useful is when the bean post processor wraps the target in a proxy instance. All invocations on the bean bound in application context will pass through the proxy, and the proxy then gets to perform some magic before and/or after invocations on the target bean, e.g. AOP or transaction management.
The difference is BeanPostProcessor will hook into context initialization then call postProcessBeforeInitialization and postProcessAfterInitialization for all defined beans.
But #PostConstruct is just used for the specific class you want to customize bean creation after constructor or set method.
I have build a web application and scheduled cron job using cron4j. While executing the cron the run() method is calling and in the run() method all other bean objects are showing null. Hence, I am getting NullPointerException. Below is my sample code.
class Employee{
#autowired
IEmployeeService employeeService;
public void run() {
employeeService.getEmployeeDetails();
}
}
The above example employeeService object getting null and all other bean objects inside getEmployeeDetails(); are getting null and getJdbcTemplate() is also null.
How to initialize bean objects in spring while executing cron using cron4j.
You can use #BeanFactoryPostProcessor annotation to order creation of beans and create/run your job at the end of bean initialization.
The definition of BeanFactoryPostProcessor to bean (configuration metadata) processing. That is to say, the Spring IoC container allows configuration of BeanFactoryPostProcessor metadata in the container before the actual read instantiate any other bean, and may modify it. If you want, you can configure multiple BeanFactoryPostProcessor. You can control the BeanFactoryPostProcessor by setting the'order'attribute of the execution order.
From Spring documentation:
The next extension point that we will look at is the org.springframework.beans.factory.config.BeanFactoryPostProcessor. The semantics of this interface are similar to those of the BeanPostProcessor, with one major difference: BeanFactoryPostProcessor operates on the bean configuration metadata; that is, the Spring IoC container allows a BeanFactoryPostProcessor to read the configuration metadata and potentially change it before the container instantiates any beans other than BeanFactoryPostProcessors.
Please find more information on Spring docs: http://docs.spring.io/spring/docs/4.1.3.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#beans-factory-extension-factory-postprocessors