I have this requirement: I have a singleton bean and I have a method annotated with #PostConstruct where I perform some initialization. One of the initialization is to read some values from a DB, so I want to inject in this method a Stateless bean which is a service bean that access the DB. I don't want to inject the stateless bean as a field in the singleton bean because it is needed only in this method (nowhere else in the singleton bean). To do so I did wrote this in singleton bean:
#Singleton
public class MySingletonBean {
#PostConstruct
#EJB
public void init(SLSBService service) { /* use service to read from DB */ };
...
}
The problem is that the Singleton bean can not be instantiated. Any idea? Thank you in advance.
As the #PostConstruct annotated (callback) method is actually called after all references are resolved (all beans injected) I do not think this construct works.
What you could do or try out is to remove the #PostConstruct and using normal setter injection. However, be aware that other injected resources have not necessarily been resolved at this time.
#EJB
public void setService(SLSBService service){
service.doSmg();
}
#Stateless
public class SLSBService{
#PersistenceContext
private EntityManager em;
#TransactionAttribute(TransactionAttributeType.MANDATORY)
public void doSmg() {
Member member = new Member();
member.setEmail("bla#bla.de");
member.setName("fubu");
member.setPhoneNumber("453454534535");
em.persist(member);
}
}
/* edit */
Just had some time for trying it out. The construct should be usable for DAOs, as the method is executed within a transaction and also the EntityManager (within the SLBService) is injected properly. And as expected references to other EJBs have not be resolved yet, so be aware of that.
Related
It is a best practice to use constructor injection. However I can't acheive this with #PersistenceContext.
I would like to have the following constructor:
private final EntityManager entityManager;
#Autowired
public MyService(#PersistenceContext EntityManager entityManager) {
this.entityManager = entityManager;
}
But I can't since #PersistenceContext is only applicable to TYPE, METHOD and FIELD.
Q: How do I inject a container-managed EntityManager through constructor injection?
You seem to be using spring so your solution will be rather easy :
#Component
#Scope("prototype")
public class MyPersistenceContainer
{
#PersistenceContext
private EntityManager em;
public EntityManager getEntityManager()
{
return em;
}
}
And now you can simply inject an instance of this class in your constructor, it will always hold a valid EntityManager (because of the bean scope). Mind you : in a web environment you probably should use #SessionScope or even #RequestScope instead of prototype, this will save resources
But there is something to consider :
When using singleton-scoped beans that have dependencies on beans that
are scoped as prototypes, please be aware that dependencies are
resolved at instantiation time. This means that if you dependency
inject a prototype-scoped bean into a singleton-scoped bean, a brand
new prototype bean will be instantiated and then dependency injected
into the singleton bean... but that is all. That exact same prototype
instance will be the sole instance that is ever supplied to the
singleton-scoped bean, which is fine if that is what you want.
However, sometimes what you actually want is for the singleton-scoped
bean to be able to acquire a brand new instance of the
prototype-scoped bean again and again and again at runtime. In that
case it is no use just dependency injecting a prototype-scoped bean
into your singleton bean, because as explained above, that only
happens once when the Spring container is instantiating the singleton
bean and resolving and injecting its dependencies. If you are in the
scenario where you need to get a brand new instance of a (prototype)
bean again and again and again at runtime, you are referred to the
section entitled Section 4.3.7, “Method Injection”
So if you want to inject your "entity manager container-bean" into singleton beans (which is the default scope), have a look at https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-method-injection
Its rather important to set your scopes correctly, otherwise you might have (and will have) database inconsistencies, deadlocks or worse
It sould be possible using Spring Data. But if you would not like to use Spring Data in your project for some reason (e.g. you're just making a legacy project a bit better), you can create the following FactoryBean to make EntityManager injectable via constructor injection:
/**
* Makes the {#link EntityManager} injectable via <i>#Autowired</i>,
* so it can be injected with constructor injection too.
* (<i>#PersistenceContext</i> cannot be used for constructor injection.)
*/
public static class EntityManagerInjectionFactory extends AbstractFactoryBean<EntityManager> {
#PersistenceContext
private EntityManager entityManager;
#Override
public Class<?> getObjectType() {
return EntityManager.class;
}
#Override
protected EntityManager createInstance() {
return entityManager;
}
}
Please note, that because we use the #PersistenceContext annotation internally, the returned EntityManager will be a proper thread-safe proxy, as it would have been injected directly at the place of usage with field injection.
I am trying to inject a prototype bean in a singleton bean such that every new call to a singleton bean method has a new instance of the prototype bean.
Consider a singleton bean as below:
#Component
public class SingletonBean {
#Autowired
private PrototypeBean prototypeBean;
public void doSomething() {
prototypeBean.setX(1);
prototypeBean.display();
}
}
I expect that every time the doSomething() method is called, a new PrototypeBean instance is utilized.
Below is the prototype bean:
#Component
#Scope(value="prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class PrototypeBean {
Integer x;
void setX(Integer x) {
this.x = x;
}
void display() {
System.out.println(x);
}
}
What seems to be happening is that spring is being overeager in handing over a new instance of PrototypeBean in the doSomething() method. That is, the 2 lines of code in the doSomething() method are creating a new instance of prototypeBean in each line.
And so in the 2nd line - prototypeBean.display() prints NULL.
What is missing in configuration for this injection?
From Spring documentation:
You do not need to use the <aop:scoped-proxy/> in conjunction with
beans that are scoped as singletons or prototypes. If you try to
create a scoped proxy for a singleton bean, the BeanCreationException
is raised.
It seems the documentation has changed a bit for version 3.2 documentation where you can find this sentence:
You do not need to use the <aop:scoped-proxy/> in conjunction with
beans that are scoped as singletons or prototypes.
It seems that its not expected you use a proxied prototype bean, as each time it is requested to the BeanFactory it will create a new instance of it.
In order to have a kind of factory for your prototype bean you could use an ObjectFactory as follows:
#Component
public class SingletonBean {
#Autowired
private ObjectFactory<PrototypeBean> prototypeFactory;
public void doSomething() {
PrototypeBean prototypeBean = prototypeFactory.getObject();
prototypeBean.setX(1);
prototypeBean.display();
}
}
and your prototype bean would be declared as follows:
#Component
#Scope(value="prototype")
public class PrototypeBean {
// ...
}
Singleton bean is created only once so the prototype bean which is injected also will be created once at the instantiation of singleton bean.The same instance of prototype bean will be used for every request.
If new instance of prototype bean will be created for each request at runtime ,the below method Injection can be used
Example
public class Singleton {
private Prototype prototype;
public Singleton(Prototype prototype) {
this.prototype = prototype;
}
public void doSomething() {
prototype.foo();
}
public void doSomethingElse() {
prototype.bar();
}
}
public abstract class Singleton {
protected abstract Prototype createPrototype();
public void doSomething() {
createPrototype().foo();
}
public void doSomethingElse() {
createPrototype().bar();
}
}
<bean id="prototype" class="ch.frankel.blog.Prototype" scope="prototype" />
<bean id="singleton" class="sample.MySingleton">
<lookup-method name="createPrototype" bean="prototype" />
</bean>
Right way to achieve it - use lookup method injection and everywhere where you used beans use lookup method invocation (detailed answer)
Since Spring 4.1 you can use annotation #Lookup
#Lookup
public PrototypeBean getPrototypeBean() {
return null;
}
Every time you will call method getPrototypeBean() - you will receive new prototype bean instance.
Don't worry about empty method realization: Spring will override it for you.
Read more in official documentation.
Spring wires up your beans in a pretty straight forward way. I'm working in a large commercial application, and I inserted the following code snippets to verify the load order.
1) All of your singleton bean class structures are initially loaded by Spring (as long as Spring is aware of them via annotations and/or xml). This only ever happens once. You can test this by logging or printing in a static block:
static {
log.info("#### classNameHere loaded"); //or println if no log setup
}
2) Spring creates all singleton instances that it is aware of (but not prototypes! Prototype instances WILL be created IF they are referenced inside a singleton bean - there class structures are of course loaded first). You can test this by adding this method to each class:
#PostConstruct
public void methodHitAfterClassInstantiation() {
LOGGER.info("#### instance of classNameHere");
}
So in your example, the class structures of SingletonBean is loaded when Spring starts up. A new instance of SingletonBean is created.
And because PrototypeBean is Autowired inside of SingletonBean, its class structure is loaded and an instance of it is created. Now, if there was another bean, say AnotherSingletonBean, with an Autowired PrototypeBean inside
of it, then a DIFFERENT instance of PrototypeBean would be created (no need to load the class structure again). So there is only ever 1 SingletonBean, and inside of it is a PrototypeBean, which
will always point to the same bean. Because of this, singletons should always be stateless, as all of your other beans that use a singleton will be pointing at the
same object. But you CAN maintain state in a prototype bean, because wherever you create a new reference, you will be pointing at another bean object.
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-scopes-prototype
I am trying to inject a prototype bean in a singleton bean such that every new call to a singleton bean method has a new instance of the prototype bean.
Consider a singleton bean as below:
#Component
public class SingletonBean {
#Autowired
private PrototypeBean prototypeBean;
public void doSomething() {
prototypeBean.setX(1);
prototypeBean.display();
}
}
I expect that every time the doSomething() method is called, a new PrototypeBean instance is utilized.
Below is the prototype bean:
#Component
#Scope(value="prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class PrototypeBean {
Integer x;
void setX(Integer x) {
this.x = x;
}
void display() {
System.out.println(x);
}
}
What seems to be happening is that spring is being overeager in handing over a new instance of PrototypeBean in the doSomething() method. That is, the 2 lines of code in the doSomething() method are creating a new instance of prototypeBean in each line.
And so in the 2nd line - prototypeBean.display() prints NULL.
What is missing in configuration for this injection?
From Spring documentation:
You do not need to use the <aop:scoped-proxy/> in conjunction with
beans that are scoped as singletons or prototypes. If you try to
create a scoped proxy for a singleton bean, the BeanCreationException
is raised.
It seems the documentation has changed a bit for version 3.2 documentation where you can find this sentence:
You do not need to use the <aop:scoped-proxy/> in conjunction with
beans that are scoped as singletons or prototypes.
It seems that its not expected you use a proxied prototype bean, as each time it is requested to the BeanFactory it will create a new instance of it.
In order to have a kind of factory for your prototype bean you could use an ObjectFactory as follows:
#Component
public class SingletonBean {
#Autowired
private ObjectFactory<PrototypeBean> prototypeFactory;
public void doSomething() {
PrototypeBean prototypeBean = prototypeFactory.getObject();
prototypeBean.setX(1);
prototypeBean.display();
}
}
and your prototype bean would be declared as follows:
#Component
#Scope(value="prototype")
public class PrototypeBean {
// ...
}
Singleton bean is created only once so the prototype bean which is injected also will be created once at the instantiation of singleton bean.The same instance of prototype bean will be used for every request.
If new instance of prototype bean will be created for each request at runtime ,the below method Injection can be used
Example
public class Singleton {
private Prototype prototype;
public Singleton(Prototype prototype) {
this.prototype = prototype;
}
public void doSomething() {
prototype.foo();
}
public void doSomethingElse() {
prototype.bar();
}
}
public abstract class Singleton {
protected abstract Prototype createPrototype();
public void doSomething() {
createPrototype().foo();
}
public void doSomethingElse() {
createPrototype().bar();
}
}
<bean id="prototype" class="ch.frankel.blog.Prototype" scope="prototype" />
<bean id="singleton" class="sample.MySingleton">
<lookup-method name="createPrototype" bean="prototype" />
</bean>
Right way to achieve it - use lookup method injection and everywhere where you used beans use lookup method invocation (detailed answer)
Since Spring 4.1 you can use annotation #Lookup
#Lookup
public PrototypeBean getPrototypeBean() {
return null;
}
Every time you will call method getPrototypeBean() - you will receive new prototype bean instance.
Don't worry about empty method realization: Spring will override it for you.
Read more in official documentation.
Spring wires up your beans in a pretty straight forward way. I'm working in a large commercial application, and I inserted the following code snippets to verify the load order.
1) All of your singleton bean class structures are initially loaded by Spring (as long as Spring is aware of them via annotations and/or xml). This only ever happens once. You can test this by logging or printing in a static block:
static {
log.info("#### classNameHere loaded"); //or println if no log setup
}
2) Spring creates all singleton instances that it is aware of (but not prototypes! Prototype instances WILL be created IF they are referenced inside a singleton bean - there class structures are of course loaded first). You can test this by adding this method to each class:
#PostConstruct
public void methodHitAfterClassInstantiation() {
LOGGER.info("#### instance of classNameHere");
}
So in your example, the class structures of SingletonBean is loaded when Spring starts up. A new instance of SingletonBean is created.
And because PrototypeBean is Autowired inside of SingletonBean, its class structure is loaded and an instance of it is created. Now, if there was another bean, say AnotherSingletonBean, with an Autowired PrototypeBean inside
of it, then a DIFFERENT instance of PrototypeBean would be created (no need to load the class structure again). So there is only ever 1 SingletonBean, and inside of it is a PrototypeBean, which
will always point to the same bean. Because of this, singletons should always be stateless, as all of your other beans that use a singleton will be pointing at the
same object. But you CAN maintain state in a prototype bean, because wherever you create a new reference, you will be pointing at another bean object.
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-scopes-prototype
I'm learning spring and in my first application I have different kind to bean (#Repository,#Service). Now I read that the default scope for these bean is singleton.
My situation is the following, I have two services where I'm injecting the same Dao.
#Service
public class MyFirtsServiceImpl implements MyFirtsService{
#Autowired
UserDao userDao
}
#Service
public class MySecondServiceImpl implements MySecondService{
#Autowired
UserDao userDao
}
#Repository
public class UserDao {
//methods to manage the persistence
}
Now I have some doubts about this situation. Being userDao a singleton bean then the instance to UserDao injected in both services is the same? How the container manage this?
first of all the meaning of singleton design pattern is only one instance per appliction and spring container manage singleton design pattern.
When a bean is a singleton, only one shared instance of the bean will be managed, and all requests for beans with an id or ids matching that bean definition will result in that one specific bean instance being returned by the Spring container.
To put it another way, when you define a bean definition and it is scoped as a singleton, then the Spring IoC container will create exactly one instance of the object defined by that bean definition. This single instance will be stored in a cache of such singleton beans,
and all subsequent requests and references for that named bean will result in the cached object being returned.
for more help go here
Isn't singleton scope the easiest case for the controller to manage?
It creates a bean for your:
#Repository
public class UserDao {
Also #Autowire is by type. So when it sees this:
#Autowired
UserDao userDao
it finds that there is only one bean it has created(or will create) of type UserDao, and there is no ambiguity in which one to inject. So it injects that bean here.
When it encounters the second identical #Autowire situation, it repeats the decision and so injects the same bean. It is not even an interesting decision.
I have a resource (Spring bean) which has some of its fields injected by Spring, for example:
#Repository(value="appDao")
public class AppDaoImpl implements AppDao {
#PersistenceContext
EntityManager entityManager;
public Resource() {
... use entityManager ... // doesn't work
}
}
I know that I can't access the injected entityManager in the constructor and should use a #PostConstruct annotation on a different method. But what are the reasons for this?
Because Spring can't access any fields or methods before the object is created (which is done through the constructor). So Spring instantiates the object using the constructor and then injects the properties.
The only way around this is to use Constructor Injection (which can be cumbersome if you have multiple dependencies). I think what you should do is move your code out of the constructor and into an initialization method using the #PostConstruct annotation:
#PostConstruct
public void init(){
// do stuff with entitymanager here
}
The reason is in the lifecycle of the bean:
The container (spring application context) instantiates the object
then it sets all the dependencies (incl. the entityManager in your example)
after all dependencies have been set, it invokes the #PostConstruct method, if any.
Spring (and no one) can set fields to an object before actually constructing that object.
You can use constructor-injection - passing the dependencies to a non-default constructor, but it is not possible with #PersistenceContext