I'd like to know what are the differences between the two examples below. One is using #PostConstruct init method to ensure autowired bean is initialized, and the other one is using constructor with #Autowired to ensure any needed beans are initialized.
I am curious
If there is any functional differences
If one is better than the other, why? (Maybe initialization speed, less call stack, less memory usage, etc.)
Thanks in advance :)
#Component
public class MyBean {
#Autowired
public MyBean(SomeOtherBean someOtherBean) {
...
}
...
}
#Component
public class MyBean {
#Autowired
private SomeOtherBean someOtherBean;
#PostConstruct
public void init() {
...
}
...
}
in the first case, if I'm going to use MyBean.class without in a none Spring framework project I'll need to pass SomeOtherBean so I know the object is created correctly. but in the second case, I would have done new MyBean() and then after I'll get NullPointerException when using it because the object depends on SomeOtherBean.
so the first one is much cleaner.
Autowired constructor will not create the instance unless it has someotherbean available, that means it fast fails and will not even try to create the instance before someotherbean is available. If you do not have an autowired constructor it will create the instance and the bean is available in container, then inject the someotherbean when it is available. Whatever inside the #PostConstruct annotated method will execute after the instance is created. Please read the following will get better idea
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#spring-core
Related
I have class which I created manually using new, because I needed to pass it some objects (not beans). It has 2 objects tough which I want to be autowired by spring. This is my class:
#Component
#Scope("prototype")
public class DayLayout extends VerticalLayout {
#Autowired
private SchedulingService schedulingService;
#Autowired
private GeneralService generalService;
.
.
.
}
But after creation of the class those objects are still null. I think it is because I have not obtained that bean via spring container. But is there any way how can I create object manually and all it's objects will be still autowired ?
So if you need to inject Autowired properties to an object created via new you could do the following:
DayLayout dl = new DayLayout(<whatever parameters go here>);
ctx.getAutowireCapableBeanFactory().autowireBean(dl); // Where ctx is Spring's application context
But if you need to do such things I think you might rethink what you are actually doing in your application.
Assuming that GeneralService is not a class annotated with #Component or other Spring stereotypes annotations: yes, there is.
#Configuration
public class ConfigClasses{
#Bean
public GeneralService generalService(){
return new GeneralService();
}
}
Obviously the same for SchedulingService, just add another method which produces that class.
I think you are misunderstanding some part of managed objects, but I am not sure what part that is.
Since you annotated the bean as #Prototype I assume you realize Spring will instantiate a new instance for you every time you request one. It would then be a trivial matter to call setters for your non-managed objects. You could even add a belt and suspenders approach and have your bean throw a IllegalStateException if the setters have not been called.
#Ivan is exactly correct on how you can manually request a bean. He is also exactly correct that if you are resorting to that your design is probably not the best.
If you do : Object obj = new Object(); , it won't autowire. If you want to create manually your object, you can use a config file with #Configuration and return a #Bean. https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html . If that is not what you want, can you provide how you create those two objects ? What do you pass to them ?
This is an example from the Spring documentation, section 6.12.5:
#Configuration
public class ServiceConfig {
#Autowired
private AccountRepository accountRepository;
#Bean
public TransferService transferService() {
return new TransferServiceImpl(accountRepository);
}
}
My question is: why must it happen that accountRepository is created before it's used by new TransferServiceImpl()? Offhand, I don't see how Spring could know that the second one depends on the first one being set up (unless it goes through the transferService() bytecode). Is it because something about the order in which Spring does things guarantees that the #Autowired variable is processed before the #Bean method could possibly be called? What is the processing order? What kinds of circumstances could cause Spring to process these out of order?
The reason I'm asking is that I have a case where something like this isn't working, i.e. the new is being executed with a null argument. Either the #Autowired variable is being set up too late, or it isn't set up at all (my guess is the latter, based on some log4j.logger.org.springframework.beans debugging output, but I'm not sure). The situation is of course much more complex--it's a largish application, and there are a few more #Autowired and #Bean definitions in the configuration class. Using #DependsOn hasn't helped. It will take a lot of time to narrow down the problem by deleting code until I can get a minimal example, but I wanted to see if I could get some insight into the problem by learning more details about how Spring processes things, before starting down the difficult code reduction path.
why must it happen that accountRepository is created before it's used
by new TransferServiceImpl()?
It doesn't. accountRepository may be seen to be null.
From the note in the documentation you linked (its more current version)
Make sure that the dependencies you inject that way are of the
simplest kind only. #Configuration classes are processed quite early
during the initialization of the context and forcing a dependency to
be injected this way may lead to unexpected early initialization.
Whenever possible, resort to parameter-based injection as in the
example above.
Also, be particularly careful with BeanPostProcessor and
BeanFactoryPostProcessor definitions via #Bean. Those should usually
be declared as static #Bean methods, not triggering the instantiation
of their containing configuration class. Otherwise, #Autowired and
#Value won’t work on the configuration class itself since it is being
created as a bean instance too early.
In summary, a Configuration class will end up being just another bean in the application context. As such, it will be processed by all registered BeanPostProcessor beans.
#Autowired is processed by AutowiredAnnotationBeanPostProcessor. Presumably, you're using AnnotationConfigApplicationContext which registers one automatically.
In your example, which is incomplete since
...but determining exactly where the autowired bean definitions are
declared is still somewhat ambiguous
However, we can assume some other configuration provided a bean definition for a AccountRepository bean. Once the application context instantiates the ServiceConfig bean, it can then post process it and inject #Autowired targets.
The only reason an #Autowired target could be null in a #Configuration bean instance is that you tried to read it before an AutowiredAnnotationBeanPostProcessor could process/inject it.
Consider a circular dependency. Take the #Configuration class in your snippet with an additional #ComponentScan of the following classes
#Component
class AccountRepository {
public AccountRepository(Foo foo) {}
}
#Component
class Foo {
public Foo(TransferService ts) {}
}
The #Configuration bean get initialized. AutowiredAnnotationBeanPostProcessor kicks off to process the accountRepository field. It looks for an AccountRepository bean and tries to initialize it. It needs a Foo bean to instantiate it (for constructor injection). It looks for a Foo bean and tries to initialize it. It needs a TransferService bean to instantiate it (for constructor injection). It looks for a TransferService bean and finds the #Bean factory method. It invokes it. The accountRepository hasn't been initialized yet, so remains null. You can verify this by putting a breakpoint in the #Bean method and browsing the stack trace.
Had you used a parameter injection as suggested in the quote above
Whenever possible, resort to parameter-based injection as in the example above.
Spring would've crashed and warned you
Caused by:
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'accountRepository': Requested bean is
currently in creation: Is there an unresolvable circular reference?
That's the workaround I ended up doing
I can't currently explain this.
I just move accountRepository to the method's param and annotated with #Autowired to solve this problem. But I don't know why. I think the reason is about Spring's init order.
#Configuration
public class ServiceConfig {
#Bean
public TransferService transferService(#Autowired AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
I'm working with some existing code and it is doing things I haven't seen before. I've dealt with autowiring prototype beans into singletons using method injection or getting the bean from the context using getBean(). What I am seeing in this code I am working on is a bean that is a prototype and retrieved using getBean(), and it has autowired dependencies. Most of these are singleton beans, which makes sense. But there is an autowire of another prototype bean, and from what I see, it does seem like it is getting a new bean. My question is when you autowire a prototype into a prototype, will that give you a new instance? Since the autowire request is not at startup but rather when this bean is created, does it go and create a new instance? This goes against what I thought about autowire and prototype beans and I wanted to hear an answer from out in the wild. Thanks for any insight. I'm trying to minimize my refactoring of this code as it is a bit spaghetti-ish.
example:
#Scope("prototype")
public class MyPrototypeClass {
#Autowired
private ReallyGoodSingletonService svc;
#Autowired
private APrototypeBean bean;
public void doSomething() {
bean.doAThing();
}
}
#Scope("prototype)
public class APrototypeBean {
private int stuffgoeshere;
public void doAThing() {
}
}
So when doSomething() in MyPrototypeClass is called, is that "bean" a singleton or a new one for each instance of MyPrototypeClass?
In your example, the APrototypeBean bean will be set to a brand new bean which will live through until the instance of MyPrototypeClass that you created is destroyed.
If you create a second instance of MyPrototypeClass then that second instance will receive its own APrototypeBean. With your current configuration, every time you call doSomething(), the method will be invoked on an instance of APrototypeBean that is unique for that MyPrototypeClass object.
Your understanding of #Autowired or autowiring in general is flawed. Autowiring occurs when an instance of the bean is created and not at startup.
If you would have a singleton bean that is lazy and that bean isn't directly used nothing would happen as soon as you would retrieve the bean using for instance getBean on the application context an instance would be created, dependencies get wired, BeanPostProcessors get applied etc.
This is the same for each and every type of bean it will be processed as soon as it is created not before that.
Now to answer your question a prototype bean is a prototype bean so yes you will receive fresh instances with each call to getBean.
Adding more explanation to #Mark Laren's answer.
As explained in Spring 4.1.6 docs
In most application scenarios, most beans in the container are
singletons. When a singleton bean needs to collaborate with another
singleton bean, or a non-singleton bean needs to collaborate with
another non-singleton bean, you typically handle the dependency by
defining one bean as a property of the other. A problem arises when
the bean lifecycles are different. Suppose singleton bean A needs to
use non-singleton (prototype) bean B, perhaps on each method
invocation on A. The container only creates the singleton bean A once,
and thus only gets one opportunity to set the properties. The
container cannot provide bean A with a new instance of bean B every
time one is needed.
Below approach will solve this problem, but this is not desirable because this code couples business code with Spring framework and violating IOC pattern. The following is an example of this approach:
// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;
// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class CommandManager implements ApplicationContextAware {
private ApplicationContext applicationContext;
public Object process(Map commandState) {
// grab a new instance of the appropriate Command
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
protected Command createCommand() {
// notice the Spring API dependency!
return this.applicationContext.getBean("command", Command.class);
}
public void setApplicationContext(
ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
So, there are 2 desirable ways to solve this problem.
1. Using Spring's method injection
As name suggests, Spring will implement & inject our abstract method by using #Lookup annotation from Spring 4 or tag if you use xml version. Refer this DZone article.
By using #Lookup.
from Java Doc...
An annotation that indicates 'lookup' methods, to be overridden by the
container to redirect them back to the BeanFactory for a getBean call.
This is essentially an annotation-based version of the XML
lookup-method attribute, resulting in the same runtime arrangement.
Since:
4.1
#Component
public class MyClass1 {
doSomething() {
myClass2();
}
//I want this method to return MyClass2 prototype
#Lookup
public MyClass2 myClass2(){
return null; // No need to declare this method as "abstract" method as
//we were doing with earlier versions of Spring & <lookup-method> xml version.
//Spring will treat this method as abstract method and spring itself will provide implementation for this method dynamically.
}
}
The above example will create new myClass2 instance each time.
2. Using Provider from Java EE (Dependency Injection for Java (JSR 330)).
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Component
public static class SomeRequest {}
#Service
public static class SomeService {
#Autowired
javax.inject.Provider<SomeRequest> someRequestProvider;
SomeRequest doSomething() {
return someRequestProvider.get();
}
}
The above example will create new SomeRequest instance each time.
My application context XML is simple:
<context:component-scan base-package="com.depressio.spring" />
In that package, I have my configuration:
package com.depressio.spring
#Configuration
#ComponentScan(basePackages = "com.depressio")
public class DepressioConfiguration
{
#Inject private ApplicationContext context;
}
Within com.depressio, there's a repository (DAO):
package com.depressio.dao;
#Repository
public class ParameterDAO
{
public Parameter getParameter(long ID) { ... }
}
... and a service where injection is working just fine (no NPE when parameterDAO is used):
package com.depressio.resource;
#Service
#Path("/depressio/parameters")
public class ParameterResource
{
#Inject private ParameterDAO parameterDAO;
#Path("{id}")
public Response getParameter(long parameterID)
{
return Response.ok(parameterDAO.getParameter(parameterID).legacyFormat()).build();
}
}
However, the legacyFormat() method call there constructs another object. Within that object, I have to inject a different DAO (also annotated with #Repository, though). That injection isn't working.
So, we have the original Parameter object:
package com.depressio.domain;
public class Parameter
{
...
public LegacyParameter legacyFormat()
{
return new LegacyParameter(this);
}
}
... and the LegacyParameter where the injection isn't working:
package com.depressio.domain.legacy;
public class LegacyParameter
{
#Inject private LegacyDAO legacyDAO;
....
public LegacyParameter(Parameter newParameter)
{
// NullPointerException when using the injected legacyDAO.
}
}
I've tried a few things, including:
Using an no-args constructor for LegacyParameter, then calling a populate method so I'm not using the injected DAO until after the object is constructed. This didn't work.
Injecting the LegacyDAO into the ParameterResource and passing it in. This worked, but isn't ideal since I have to pass it around a whole lot (which injection should help avoid, no?). It did prove that LegacyDAO is injectible... just not into LegacyParameter apparently.
Adding a #Service, #Component, or #Named annotation on LegacyParameter. All end up with the NullPointerException on the line I try to reference the injected legacyDAO.
What am I missing?
As Sotirios has pointed out, it can't work since you create a regular Java object and do not give Spring a chance to enhance it.
Either let Spring create objects for which you want to enjoy the Spring 'magic' (like setting #Inject dependencies etc).
Or create your own objects and set the dependencies yourself (yourObject.setDao(dao)).
That said, there are exceptional cases in which you still want to create your objects 'on the fly' by yourself but rely on Spring to inject dependencies to these objects. In this case you should call Spring explicitly:
LegacyParameter p = new LegacyParameter(...);
applicationContext.getAutowireCapableBeanFactory().autowireBean(p);
I don't think you really need it in your case.
(see this link inject bean reference into a Quartz job in Spring? for an example when this is really required).
In addition, I would advice to simplify your configuration.
Why do you use both xml-based and java-based configuration that do actually the same? In your example you could keep only one of them and have the same effect.
I am working on a simple Java EE application.
I have class like this:
import javax.annotation.PostConstruct;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
#Stateless
public class BlogEntryDao {
EntityManager em;
#PostConstruct
public void initialize(){
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Persistence");
em = emf.createEntityManager();
}
public void addNewEntry(){
Blogentry blogentry = new Blogentry();
blogentry.setTitle("Test");
blogentry.setContent("asdfasfas");
em.persist(blogentry);
}
}
So my managed bean calls this method. Until here no problems. But since the initialize method is not called, I am getting an NPE in em.persist.
Why is the initialize method not being called? I am running this on Glassfish server.
Regards.
The Java EE bean annotations such as #PostConstruct only apply to container-managed beans. If you are simply calling new BlogEntryDao yourself, the container isn't going to intercept the creation and call the #PostConstruct method.
(Furthermore, you'd be better off using #PersistenceContext or #PersistenceUnit instead of manually fetching the EntityManagerFactory in your initialize() method, and you should be creating an EntityManager for each call to addNewEntry(), since they're short-lived. Making these changes would eliminate the need for initialize() at all.)
I had the same problem in my application.
You didn't post your bean context configuration xml file (so I'm not sure if it's the same issue) but in my case adding this line:
<context:annotation-config/>
Solved my problem.
You need either <context:annotation-config/> or <context:component-scan/> to enable #PostConstruct annotation.
Since this question comes up first on Google for "postconstruct not called", another reason a #PostConstruct method might not be called besides using the new keyword instead of putting #PostConstruct in a Spring bean is if you have a circular dependency.
If this bean were to depend on another bean that depended on this bean, your other bean might call addNewEntry() before BlogEntryDao was initialized, even though BlogEntryDao is a dependency for that other bean.
This is because Spring didn't know which bean you wanted to load first due to the circular reference. In this case, one can remove the circular reference or use #AutoWired/#Value constructor parameters instead of member values or setters, or if using xml configuration, maybe you can swap the order in which the beans are defined.
In my case #PostConstruct was not called because my initialize() method was static and was also throwing an exception. In either case the method is ignored. I hope it helps someone else who made the same mistake.
This can be found in the console:
WARNING: JSF1044: Method '<XXX>' marked with the 'javax.annotation.PostConstruct' annotation cannot be static. This method will be ignored.
WARNING: JSF1047: Method '<XXX>' marked with the 'javax.annotation.PostConstruct' annotation cannot declare any checked exceptions. This method will be ignored.
When using Spring make sure you are using the right PostConstruct annotation from the right package.
javax.annotation.PostConstruct
should be the one. Not for example:
jakarta.annotation.PostConstruct
It took me a little while to figure out why only one of my PostConstruct didn't work.
In my case #PostConstruct method was not called because I was referencing to a public instance variable of the spring service bean directly in other service beans (ie myService.myProperty). When i made a public getter method for the property (ie getMyProperty()) and used that to get the property the #PostConstruct method was called again. Also I made myProperty private to prevent any accidental direct referencing in the future.
Also note that if you don't explicitly register the class with #Bean in a #Configuration annotated class and rely soley on #Autowired instead, the #PostConstruct method may not be executed immediately on startup. Only when one of the methods of the autowired class are referenced and called by another class will that class be loaded and only at that time will the #PostConstruct method be called. In other words, by only using #Autowired you are essentially lazy loading a class. If you want to load it at startup, register it with #Bean
Heres a good SO thread about the difference between #Bean and #Autowired Difference between #Bean and #Autowired
EDIT: One last remark. When you have a webapplication and decided to annotate your class with #RequestScope then the #Postconstruct annotated method will be called each time when a new request comes in. This is because #RequestScope instructs spring to create a new instance of the class every time a new request comes in. If you want all requests to use the same instance, then you could use #Bean as mentioned above, but you could also use the annotation #Singleton above your class. This will cause the class to be loaded eagerly upon startup.
Make sure the class having #Postconstruct method lies within the same package. I moved class file to main package and it worked.
In my case I had two instances of javax.annotation.PostConstruct inside classpath. One was bundled with the war package and another was provided by tomcat. When Spring is scanning for the #PostConstruct annotation it compares these two different instances. Therefore the #PostConstruct annotated method was not picked while scanning.
Providing only one instance of javax.annotation-api library solved the issue.
Since most of the ways are already mentioned. However one can also create a bean in the config file for the class
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
;
This will enable PostConstruct and PreDestroy annotations.
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"></bean>
Also for Predestroy one needs to call context.registerShutDownHook()