I have 20 beans in my application-context,I want to load a particular bean after all the beans are loaded. Is there a way for this?
You can use depends-on to force bean initialization order.
For example if bean1 depends on bean2 and bean3, you can put:
<bean id="bean1" class="YourBean" depends-on="bean2,bean3">
in your spring context.
As #skaffman said, this is a very strange requirement. Depending on your needs there are better solutions:
If you just need to start a process when Spring context is initialized, don't use a #PostConstruct annotated method (or an InitializingBean). ApplicationListener is probably what you need.
If you are worried because you need some beans injected in a #PostConstruct annotated method don't bother: Spring is usually smart enough for resolving such dependencies. If it isn't in your case, maybe you have an overcomplicated bean design.
If this isn't enough, you can follow #soulcheck instructions. This answer can probably help you in order to get cleaner configuration files.
If this don't help you, please give us some more information on what are you trying to achieve.
Related
I have picked up a project that uses #Autowired and dependency injection a lot. People have been saying all the nice things about them. It seems kind of like a magic.
I am new to Spring injection and #Autowired. My first glance of #Autowired is good, but when I work with them on Eclipse, I have difficulties tracing them around when debugging.
For example, is there an easy way in Eclipse that I can see where and how an #Autowired bean is initiated? How do I know if it is initiated correctly the way I want? Is there a way to trace the sequence of it being called/accessed?
Anybody has any tips or comments that may help me to debug #Autowired bean easier on Eclipse?
When a Spring application starts, it first creates instances of beans, either by scanning for annotations, or processing the XML Spring context definition. Some of those beans have to be created in a specific order, like if they use constructor injection. Once beans are created, wiring those beans together can happen.
If you want to see what happens when a bean is constructed, set a breakpoint in the constructors of the class. Look down the stacktrace to see what caused it to be constructed.
is it possible to inject spring beans into a polling filter class (FClass) controlled by a scheduler job?
i don't quite understand how singleton applies here.
i understand spring beans are singleton so in order to inject the spring beans into class FClass. i need to define FClass as a bean and add the DI as property etc..
so how do i know if FClass should be a singleton? i assume only classes that are singletons can be created and beans and have DI done to them.
my problem is :
i need to be able to inject my facade bean xfacade into FClass. x_facacde handles the dao object. it has Y_dao and a Z_hibernate session beans injected as DI.
when i tried to create a spring bean of StatusPollingFilter (FClass) and injected the facade bean - i got a null and the setter is never called for the injection in debug mode.
the problem:
i'm thought it might be something to do with the thread / scheduler nature of StatusPollingFilter, and since spring beans are singletons it might not work due to that.
i'm thinking of creating a factory for the StatusPollingFilter (FClass). but need to know if this is correct thing and i'm on right track before i do too much work and realize even that doesn't work as the problem might be somewhere else. ideally i just want to update a table in the easiest possible way. but i have to use hibernate as the DAO exists but hibernate is configured using
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
with /hibernate/TopoObject.hbm.xml
files.
so no matter how i try this i always get null pointer exception on session or injected facade bean.
reading some of the QA's here seems like because StatusPollingFilter is instantiated using the scheduler and not spring it cant be aware of the DI beans. so would the above factory pattern help here.
I may have an additional problem but i'll cross that bridge when i come to it. but just to mention briefly, in case anyone is aware of issues that i might hit ... not sure what / how the scheduler would invoke the factory for an instance as its all controlled by 3rd party api - which invokes a StatusPollingFilter but i'm assuming if i pass in the factory as the class and parameter it would find its way through... but initial part is the main question. please ignore the latter waffle. thanks in advance.
Actually :
i assume only classes that are singletons can be created
is where you are wrong.
A bean is just a class that you let spring instantiate. By default, they are created as singleton but you can specify the scope on your bean using the attribute scope (quite surprisingly). The value you can specify are those specified in the documentation here
So one thing you have to be careful with is the injection of beans scoped as prototype or request into singletons.
having read more - i have come across the ans.
because the StatusPollingFilter object is under control of scheduler (i knew that scheduler had something to do with it) then it is unaware of the spring beans which is why i keep getting null when i try injecting the bean.
i created a class:
ApplicationContextProvider implements ApplicationContextAware
added static access
private static ApplicationContext appContext;
did a setter for it :
public void setApplicationContext(ApplicationContext context)
{
appContext = context;
}
and added
public static Object getBean(String beanName) throws BeansException
{
return appContext.getBean(beanName);
}
used in code as :
EvoTAMDAOFacade evoDao = (EvoTAMDAOFacade) ApplicationContextProvider.getBean("evoDaoFacade");
i now have access to the facade bean and all injected beans into facade.
i still have an issue with hibernate session but thats prob due to some other issue.
pt here is i don't have access to the bean as its not in control of the spring container so i needed to somehow get it , probably could have done it via the factory method but why mess around when there a simpler way.
thanks for help by anyone who may have posted or tried to understand my problem.
When i want a bean say in the main method I ask for a getBean on the id. Does spring container do the same when we define properties as refs to other beans within a single bean ?
Does spring container do the same when we define properties as refs to
other beans within a single bean
Ultimately yes, Spring does find beans within the application container which match your bean definition. How it does it is something which shouldn't be too much of a concern to most users. Since it's usually enough to know that if you ask for a bean from Spring it'll come wired with all of it's dependencies.
If you're interested in the exact wiring mechanism the source code is the place to learn.
Is it possible to specify another bean to inject in case that the first intended bean to be injected fails?
Lets say we have Bean1, Bean2, and Bean3. Bean1 requires Bean2 but if Bean2 fails to be injected for some reason, then I want Bean3 to be injected instead. But each time Bean1 is retrieved from the container, it should always try to inject Bean2 first before attempting to inject Bean3. Is this possible? If not, what are my options?
Per me the question is flawed. In normal circumstances, Spring is supposed to be used for injecting the beans declaratively. So as pointed out by #Don Roby, #Adrian Shum the problem you are trying to solve is not for Spring.
Spring is not designed to resolve the dependency for you dynamically like a Service Locator.
I have a use case where I need to call a (non-static) method in the bean only-once at the ApplicationContext load up. Is it ok, if I use MethodInvokingFactoryBean for this? Or we have a some better solution?
As a side note, I use ConfigContextLoaderListener to load the Application Context in web application. And want, that if bean 'A' is instantiated just call methodA() once.
How can this be done nicely?
To expand on the #PostConstruct suggestion in other answers, this really is the best solution, in my opinion.
It keeps your code decoupled from the Spring API (#PostConstruct is in javax.*)
It explicitly annotates your init method as something that needs to be called to initialize the bean
You don't need to remember to add the init-method attribute to your spring bean definition, spring will automatically call the method (assuming you register the annotation-config option somewhere else in the context, anyway).
You can use something like:
<beans>
<bean id="myBean" class="..." init-method="init"/>
</beans>
This will call the "init" method when the bean is instantiated.
There are three different approaches to consider, as described in the reference
Use init-method attribute
Pros:
Does not require bean to implement an interface.
Cons:
No immediate indication in source code that this method is required after construction to ensure the bean is correctly configured.
Implement InitializingBean
Pros:
No need to specify init-method, or turn on component scanning / annotation processing.
Appropriate for beans supplied with a library, where we don't want the application using this library to concern itself with bean lifecycle.
Cons:
More invasive than the init-method approach.
Use JSR-250 #PostConstruct lifecyle annotation
Pros:
Useful when using component scanning to autodetect beans.
Makes it clearer that a specific method is to be used for initialisation. Intent is closer to the code.
Cons:
Initialisation no longer centrally specified in configuration.
You must remember to turn on annotation processing (which can sometimes be forgotten)
Have you tried implementing InitializingBean? It sounds like exactly what you're after.
The downside is that your bean becomes Spring-aware, but in most applications that's not so bad.
You could deploy a custom BeanPostProcessor in your application context to do it. Or if you don't mind implementing a Spring interface in your bean, you could use the InitializingBean interface or the "init-method" directive (same link).
To further clear any confusion about the two approach i.e use of
#PostConstruct and
init-method="init"
From personal experience, I realized that using (1) only works in a servlet container, while (2) works in any environment, even in desktop applications. So, if you would be using Spring in a standalone application, you would have to use (2) to carry out that "call this method after initialization.