I want to initialize a bean or an ArrayList like a list of key value pairs for all the drop downs in the application that can be used across sessions application wide. And Want to happen during the application start-up. I tried implementing the ServletContextListener and added the beans to the context, but it didn't work.
Any suggestions as to how I can achieve this. Thanks.
Ravi
Define a regular (singleton) Spring bean and initialize your values either in constructor, or #PostConstruct method:
import javax.annotation.PostConstruct;
#Component
public class AppBean {
#PostConstruct
protected void init() {
// executed after dependencies have been injected. initialize values here
}
}
See http://www.mkyong.com/spring/spring-postconstruct-and-predestroy-example/ for more detailed example
Related
I am using Vaadin Spring 1.0.0 and trying to figure out how could I inject beans that are available only within UI scope (when the user has the page opened) into classic spring #Component beans. Simple, let's have classes:
#Component
public class A {
#Inject
private IB b;
}
#UIScope
#SpringComponent
public class B implements IB {
}
And obviously during startup:
Caused by: java.lang.IllegalStateException: No VaadinSession bound to current thread
What is the normal way how to do it? I understand the whole concept, that beans are initialized on startup when UI scope is not available, but I use common libraries which are implemented in Spring with #Component and I want to implement some of the interfaces, but I can do it only in UI scope and not during startup.
Try injecting an aop scoped proxy instead.
For example:
#Scope(value="vaadin-ui", proxyMode=ScopedProxyMode.INTERFACES)
#SpringComponent
public class B implements IB {
}
I think that should work.
You need to get it from ApplicationContext itself:
#Component
public class A {
#Autowired
private ApplicationContext context;
public B getCurrentB(){
return context.getBean(B.class);
}
}
Note that it will throw exception if there is no UI bound to the current thread (normally). In other words, you MUST make sure this method only gets called during a UI request. Any kind of listener in Vaadin should be OK, as long as you're in the same thread with the request.
Assume there are two implementations of a single interface, and these beans are declared as beans in the spring configuration xml. Now, I would need only one implementation of the interface based on the system property. And, I don't wanna create the second implementation of the bean. How can I do this? I looked at this blog but then below snippet of the code from this blog uses "new" operate to create the beans. In my case the beans are declared in the spring configuration file.
http://www.intertech.com/Blog/spring-4-conditional-bean-configuration/
#CONFIGURATION
PUBLIC CLASS MYCONFIGURATION {
#BEAN(NAME="EMAILERSERVICE")
#CONDITIONAL(WINDOWSCONDITION.CLASS)
PUBLIC EMAILSERVICE WINDOWSEMAILERSERVICE(){
RETURN NEW WINDOWSEMAILSERVICE();
}
#BEAN(NAME="EMAILERSERVICE")
#CONDITIONAL(LINUXCONDITION.CLASS)
PUBLIC EMAILSERVICE LINUXEMAILERSERVICE(){
RETURN NEW LINUXEMAILSERVICE();
}
I have a spring config where I define hundreds of actions which extend MyAction. I have a pool where an execution service can look up actions. I can't use the appContext directly because each action has one or more "keys" which the execution service will use and pool cuts that dependency.
So the pool must be able to collect all beans of type MyAction (or rather beans that extend MyAction).
The method ApplicationContext.getBeansOfType() seems to do what I need but when can I safely call it?
It would be great if I could call it in a #PostConstruct method but is it guaranteed that the bean factory has seen added each and every bean from the config at that time?
Note: Almost all of my beans are #Lazy
You could use injection by constructor and passing a Collection of yours MyAction
Something like
#Component
public class Foo {
private final Set<MyAction> myActions;
#Inject
public Foo(Set<MyAction> myActions) { this.myActions = myActions; }
}
or
public class Foo {
private Set<MyAction> myActions;
#Inject
public void setMyActions(Set<MyAction> myActions) { this.myActions = myActions; }
}
Spring will take care of creating the set with all beans that extends MyAction.
In the first case, they are injected by constructor, you can safely use them in any method.
In the second case, Spring will eventually call the setter. You can either do any post processing in the setter or add a #PostConstruct method that works on myActions.
Try to use ListableBeanFactory like this. Also here is API documentation. Method getBeansOfType has parameter allowEagerInit which forces eager init of lazy object.
I use spring roo to build project and it's annotation driven, and there is no bean definition in XML file. All the configuration info is in *.aj file.
And now I want to set up an init method for a bean which don't have a default constructor (that bean is from the third party and it has a constructor with arguments, and I cannot remove them or give a default constructor to it.)
Is there anyone who can tell me how to do this, please?
The reason I want to do this is because I want to use applicationContext.getBean("thatBeanName") to dynamically get the bean and use it. Because the bean don't have a default constructor, I always get the error: java.lang.NoSuchMethodException: com.to.that.bean.<init>() and this is why I want to add the init-method to the bean.
Use #PostConstruct as shown in below example. It is equivalent to init-method="initialize()"
#PostConstruct
public void initialize() {
messages.put("English", "Welcome");
messages.put("Deutsch", "Willkommen");
}
#Bean(initMethod="init")
public MyBean getMyBean() {
...
}
In spring container it is "init" method that being called the last,
#postconstruct called before afterPropertiesSet. so it is safer if someone miss use.
"Multiple lifecycle mechanisms configured for the same bean, with different initialization methods, are called as follows:
1.Methods annotated with #PostConstruct
2.afterPropertiesSet() as defined by the InitializingBean callback interface
A custom configured init() method
[https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-java-lifecycle-callbacks][1]
Although, today I would prefer to be more Spring independent and use either #Postconstract, or even configure default init method recognition. to have only meaningful method name indicate that it should be used for initialization - clear from frameworks, clear from annotations.
As #Pangea has put in , #PostConstruct is the best choice. You could also implement initializingBean and do the initialization in afterPropertiesSet method .Check here for this approach.
I realized that there have been multiple answers trying to solve the problem. But with the newly introduced #Configuration which is popularly used within Spring Boot. Things are changed a little bit.
If you are using #Bean annotation in #Configuration annotated class like:
#Configuration
class FooClass {
#Bean
public Bar bar() {
return new Bar();
}
}
If you want to use an automatically called method on the bean instance during initialization, you have two options below:
Option1:
#Configuration
class FooClass {
#Bean(initMethod="init")
public Bar bar() {
return new Bar();
}
}
Option2:
#Configuration
class FooClass {
#Bean
public Bar bar() {
Bar bar = new Bar();
bar.init();
return bar;
}
}
BUT, as is explain in #Bean Java Doc here:
/**
* The optional name of a method to call on the bean instance during initialization.
* Not commonly used, given that the method may be called programmatically directly
* within the body of a Bean-annotated method.
* The default value is {#code ""}, indicating no init method to be called.
*/
The second is regarded as a better answer. See link here
I am using prototype scoped bean definitions in my Spring XML descriptors to configure the default properties (these beans have many properties) and then I call the application context with a getBean(beanName, ctorArgs[]) to create instances.
The bean definitions require 2-3 constructor arguments that supply logically unique keys used for things like key properties for the JMX ObjectName etc. Additionally, the variables that the constructor arguments are written to are final.
What I am seeing is that when the application context refreshes, it attempts to instantiate these prototypes, which seems completely the opposite of what you want prototypes to do. They're templates, not actual instances. To work around this, I have been configuring the prototypes with bogus ctor values so these bogus bean instances are instantiated and I simply filter out the created MBeans later in the code.
My question is, how do I configure the application context to register these prototype bean definitions, but not instantiate them until I make a getBean call ?
UPDATE:
The problem is a bit more complicated than I initialy thought. In fact, lazy is the default behaviour for prototype-scoped beans. I digged a bit and I managed to reproduce your problem and find the solution. So what is the problem?
You probably have <aop:scoped-proxy/> enabled or (#ComponentScan(scopedProxy=...) equivalent). During context refresh Spring wraps your prototype bean (ClosedMetricSubscriberFeed) with scoped proxy. It uses class proxy because (a) class proxies are chosen or (b) the class has no interfaces.
The class-based proxy is basically a CGLIB subclass of your bean that must call (due to JVM rules) a base class's constructor. And CGLIB generated class always calls no-arg constructor.
I know this sounds complicated, here's what you can do:
Disable <aop:scoped-proxy/>. Just like that.
Provide a dummy no-arg constructor and deprecate it just in case. Unfortunately you will have to discover such bogus instances manunally. Note that in this case the class will be of type: ``.
Extract an interface from your class and use interfaces for scoped proxies:
.
#Scope(
value = ConfigurableBeanFactory.SCOPE_PROTOTYPE,
proxyMode = ScopedProxyMode.INTERFACES)
Old answer:
Use lazy initialization with #Lazy annotation or lazy-init="true" (see 4.4.4 Lazy-initialized beans in reference documentation) configuration attribute.
<bean id="proto" class="MyPrototype" scope="prototype" lazy-init="true"/>
or:
#Service
#Scope("prototype")
#Lazy
public class MyPrototype {/*...*/}
I use a private, deprecated, no-arg constructor that throws an IllegalStateException. The context loads fine, getBean() with the constructor args works fine, and getBean() without args throws the exception.
package a;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
#Component("myCommand")
#Scope("prototype")
public class Command {
final protected String name;
#Deprecated
private Command() {throw new IllegalStateException("Only for Spring"); }
public Command(String name) {
super();
this.name = name;
}
#Override
public String toString() {
return "Command [name=" + name + "]";
}
}