I have declared a bean which is instantiated via a factory method. The factory method invokes some remote services. So, the method has been declared to throw Exception.
The bean is correctly being instantiated when everything works fine. However, when the factory method throws exception, then everything starts going wrong. because my declared bean is referenced from another bean.
I want to set a default value, if the factory method throws Exception.
Part of my config file is as follows :
<bean id="Helper" class="com.test.Helper">
<constructor-arg ref="myBean" />
</bean>
<bean id="myBean" class="com.test.Factory" factory-method="getBean" />
the getBean() method is as follows:
Factory {
public static Bean getBean() throws Exception{
//Invokes some Remote Services and does some processing
....
....
//returns bean object
}
}
Please help me how I can solve this. I am not allowed to modify the factory method.
If bean or factory method throws an exception during creation, the whole application context startup fails (I guess this is what you mean by "everything starts going wrong"). There is nothing you can do about it on the Spring side.
If you want to return some default value, simply catch the exception in your custom factory, log it and return that default. If you cannot modify the existing factory, consider #Configuration approach:
#Configuration
public SafeCfg {
#org.springframework.context.annotation.Bean
public Bean bean() {
try {
return Factory.getBean();
} catch(Exception e) {
return //some default Bean
}
}
}
It works since Spring 3.0. Just place it somewhere so that the application context can pick it up.
But I doubt this is what you want. Even when the external system becomes available, you'll be still using the default, fallback value. Do you expect it to work like this? More advanced approach is to use lazy proxy (Spring has support for that: Is there a spring lazy proxy factory in Spring?) and initialize it only when needed and refresh when broken.
Related
Is there a way where I can create a runtime bean on spring. I needed this to happen since the values of the bean will be injected by the external entity through RESTful service. Is it possible for the runtime bean to still be autowired?
It is perfectly possible
In your Controller (or in your Factory would be more elegant) you need to inject your Application context
#Autowired
private ApplicationContext applicationContext;
You can create your beans like this:
YourClassBean yourObject = this.applicationContext.getBean(YourClassBean.class, params);
In your Spring configuration do this:
#Bean
#Scope(value = "prototype")
YourClassBean yourClassBean(String params) {
return new YourClassBean(params);
}
And your are done.
In that example the Scope is Prototype which means that you will get a new object every time you call the method yourClassBean.
Also in that example the params are a String (it is like the initialization parameters of your bean, but that is totally optional, and of course you might need or want more parameters in there and it is totally find)
I am new to Spring and trying to understand the concept "Injecting a prototype bean into a singleton bean". As per my understanding In singleton, only a single instance per Spring IoC container, no matter how many time you retrieve it. validator.validate(requestId);, because still private RequestValidator validator not instantiated.
I developed below example where in a singleton bean I give a reference of prototype bean like below:
<bean id="requestProcessor" class="com.injection.testing.RequestProcessor">
<property name="validator" ref="validator" />
</bean>
<bean id="validator" class="com.injection.testing.RequestValidator" scope="prototype" />
RequestProcessor.java
public class RequestProcessor {
private RequestValidator validator;
public RequestProcessor(){
System.out.println("Constructor:: RequestProcessor instance created!");
}
public void handleRequest(String requestId){
System.out.println("Request ID : "+ requestId);
validator.validate(requestId);
}
public RequestValidator getValidator() {
return validator;
}
public void setValidator(RequestValidator validator) {
this.validator= validator;
}
}
RequestValidator.java
public class RequestValidator {
private List<String> errorMessages = new ArrayList<String>();
public RequestValidator() {
System.out.println("Constructor:: RequestValidator instance created!");
}
// Validates the request and populates error messages
public void validate(String requestId){
System.out.println("RequestValidator :"+requestId);
}
public List<String> getErrorMessages() {
return errorMessages;
}
}
Now when I called the main method I see the following output:
MainDemo.java
public class MainDemo {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
RequestProcessor processor = (RequestProcessor) context.getBean("requestProcessor");
processor.handleRequest("1212");
System.out.println("------------------------");
processor.handleRequest("1213");
}
}
the output is:
Constructor:: RequestProcessor instance created!
Constructor:: RequestValidator instance created!
Request ID : 1212
RequestValidator :1212
------------------------
Request ID : 1213
RequestValidator :1213
Now looking at the output, it looks like for the 2nd call processor.handleRequest("1213"); bean is not instantiated, instead already instantiated bean gets used thats why constructor wont get called again. So Prototype bean validator acting as a singleton bean only.
To me : it is expected that when ever I fetch requestProcessor from application context, it will be wired with a new validator as we declared the validator bean is of prototype scope. But this does not happen.
How to solve it ? Is my understanding correct ?
Another way:
<!-- Lookup way -->
<bean id="requestProcessor" class="com.injection.testing.RequestProcessor" >
<lookup-method name="getValidator" bean="validator" />
</bean>
<bean id="validator" class="com.injection.testing.RequestValidator" scope="prototype" />
If I call my main method I see below output + error: Here code validator.validate(requestId); executes, private RequestValidator validator; is not instatiated and whats why null pointer exception coming.
I've shown in the below code:
public class MainDemo {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
RequestValidator requestValidator = (RequestValidator) context.getBean("validator");
RequestProcessor processor = (RequestProcessor) context.getBean("requestProcessor");
processor.handleRequest("1212");
System.out.println("------------------------");
processor.handleRequest("1213");
}
}
Now I see the below error:
Constructor:: RequestProcessor instance created!
Constructor:: RequestValidator instance created!
Request ID : 1212
Exception in thread "main" java.lang.NullPointerException
at com.injection.testing.RequestProcessor.handleRequest(RequestProcessor.java:12)
at com.injection.testing.MainDemo.main(MainDemo.java:14)
Injection happens only once, when the Spring context is started. If bean has prototype scope, Spring will create new prototype bean for every injection. But prototype bean will not be created every time you call its methods. Lets consider next example:
<bean id="firstRequestProcessor" class="com.injection.testing.RequestProcessor">
<property name="validator" ref="validator" />
</bean>
<bean id="secondRequestProcessor" class="com.injection.testing.RequestProcessor">
<property name="validator" ref="validator" />
</bean>
<bean id="validator" class="com.injection.testing.RequestValidator" scope="prototype" />
In this case both of RequestProcessor beans will have its own instance of RequestValidator bean.
Lookup method is the method, you should call every time when you need new instance of prototype bean. It's better to make this method abstract, because anyway Spring will override this method automatically. For example:
public class abstract RequestProcessor {
public void handleRequest(String requestId){
System.out.println("Request ID : "+ requestId);
RequestValidator validator = createValidator(); //here Spring will create new instance of prototype bean
validator.validate(requestId);
}
protected abstract RequestValidator createValidator();
}
Note, that createValidator returns instance of RequestValidator and has not any parameters. Also you don't need private class variable validator. In this case bean's configuration will looks like:
<bean id="requestProcessor" class="com.injection.testing.RequestProcessor" >
<lookup-method name="createValidator" bean="validator" />
</bean>
<bean id="validator" class="com.injection.testing.RequestValidator" scope="prototype" />
Now every time you call createValidator method, Spring will create new instance of validator bean.
You can find more details in documentation.
When spring creates the context, it will instantiate an instance of the RequestProcessor. During the instantiation of that instance, an instance of the RequestValidator is created and injected in the RequestProcessor.
Because any subsequent reference to the RequestProcessor Bean will access the same instance of the RequestProcessor in the context - and it is already fully constructed - there will never be a call to create a new instance of a RequestValidator. Although your Validator is scoped to be a prototype - in the example above - you only ever ask for a single copy - when you create the RequestProcessor singleton.
For the second part of your question - you misunderstand the use of the lookup-method. Spring allows you to override the method on your RequestProcessor - so when you call requestProcessor.getValidator() - spring will return a new instance of that RequestValidator. However - during the construction of your requestProcessor instance - you never initialized the validator field. Nor did spring inject a validator during instantiation. Hence the NullPointerException.
Lookup method injection
As noted earlier, lookup method injection is an advanced feature that
you should use rarely. It is useful in cases where a singleton-scoped
bean has a dependency on a prototype-scoped bean. Using Java for this
type of configuration provides a natural means for implementing this
pattern.
public abstract class CommandManager {
public Object process(Object commandState) {
// grab a new instance of the appropriate Command interface
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
// okay... but where is the implementation of this method?
protected abstract Command createCommand();
}
Using Java-configuration support , you can create a subclass of
CommandManager where the abstract createCommand() method is overridden
in such a way that it looks up a new (prototype) command object:
#Bean
#Scope("prototype")
public AsyncCommand asyncCommand() {
AsyncCommand command = new AsyncCommand();
// inject dependencies here as required
return command;
}
#Bean
public CommandManager commandManager() {
// return new anonymous implementation of CommandManager with command() overridden
// to return a new prototype Command object
return new CommandManager() {
protected Command createCommand() {
return asyncCommand();
}
}
}
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 creates the singleton bean A only 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.
A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it.
With this approach , our business logic is get coupled with Spring conatiner (Application Context) which does not looks to be a good Solution. An alternate of this is Lookup Method Injection.
in a project there is several applicationContext.xml file. there isn't any lazy definition for defined beans. then all singleton scoped beans instantiate in runtime.
Oops. it's very bad for development phase. near 2 minutes take time that server startup. Now i will know is there any solution for active lazy-instantiate in spring. For example a configuration in web.xml that set bean default-lazy-init="true".
Implement a custom BeanFactoryPostProcessor that sets lazy to true, e.g.:
public class BeanFactoryPostProcessorImpl implements BeanFactoryPostProcessor {
#Override
public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (String beanName : beanFactory.getBeanDefinitionNames()) {
beanFactory.getBeanDefinition(beanName).setLazyInit(true);
}
}
}
To get it working, all you need to do then is to add it to your application context as a standard bean:
An ApplicationContext will detect any beans which are deployed into it
which implement the BeanFactoryPostProcessor interface, and
automatically use them as bean factory post-processors, at the
appropriate time. Nothing else needs to be done other than deploying
these post-processor in a similar fashion to any other bean.
In applicationContext.xml files you can add default-lazy-init attribute with value true on the <beans/> element. See reference.
I am working with Spring JMS 4.1 to register messages listeners
In my xml configuration file, I have defined a bean named "jmsListenerContainerFactory":
<bean id="jmsListenerContainerFactory"
class="org.springframework.jms.config.DefaultJmsListenerContainerFactory"...p:concurrency="3-5".../>
First question : with Spring 4.x version, isn't it better to declare this factory this way : <jms:listener-container ... />
Second and main question : as stated in official doc (24.6.1) : by default, the infrastructure looks for a bean named jmsListenerContainerFactory as the source for the factory to use to create message listener containers. Is it also the case when programmatically registering endpoints this way:
.
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setDestination("...");
endpoint.setMessageListener(message -> {...});
registrar.registerEndpoint(endpoint);
or do we have to set it explicitly this way for example : registrar.setContainerFactoryBeanName("jmsListenerContainerFactory");
Thanks
I don't understand your first question; in the first case, you are defining a DefaultJmsListenerContainerFactory (a factory that creates listener containers) whereas the XML is creating a listener container directly.
The factory is useful if you need to create lots of containers with similar properties.
For simple container configuration, when you are not using annotated listeners, it certainly might be simpler to use traditional XML, or #Bean definitions for the container.
For the second question, the default registrar is already populated with the container factory bean name when it is passed into the configureListeners method; you don't have to set it.
SimpleJmsListenerEndpoint always looks for named bean "jmsListenerContainerFactory". so even there is no explicitly setting:
registrar.setContainerFactoryBeanName("jmsListenerContainerFactory");
JmsListenerEndpoint still can find the JmsListenerContainerFactory if there exists bean "jmsListenerContainerFactory".
Mean that in case you need to apply JmsListenerContainerFactory with different bean name, then setting on method registrar.setContainerFactoryBeanName("") doesn't effect at all.
Code below for the work and not working cases:
// config factory class
#Bean(name = "customJMSListenerContainerFactory")
public DefaultJmsListenerContainerFactory
listenerQueueFactory() {
DefaultJmsListenerContainerFactory factory = new
DefaultJmsListenerContainerFactory();
//more configs...
return factory;
}
// on consumer class
#Configuration
#EnableJms
public class MyConsumer implements JmsListenerConfigurer {
#Override
public void configureJmsListeners(JmsListenerEndpointRegistrar registrar) {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
registrar.registerEndpoint(endpoint);
// this setting will not work => Spring JMS bug
registrar.setContainerFactoryBeanName("customJMSListenerContainerFactory");
// but this setting works
registrar.setContainerFactory(listenerQueueFactory());
}
}
This is bug of spring jms.
Has anyone tried to auto-wire different beans into a Spring-managed bean based on a condition? For e.g. if some condition is met, inject class A, else B? I saw in one of the Google search results that it is possible with SpEL (Spring Expression Language), but could not locate a working example.
There are multiple ways to achieve this. Mostly this depends on the conditioning you want to perform.
Factory bean
You can implement simple factory bean to do the conditional wiring. Such factory bean can contain complex conditioning logic:
public MyBeanFactoryBean implements FactoryBean<MyBean> {
// Using app context instead of bean references so that the unused
// dependency can be left uninitialized if it is lazily initialized
#Autowired
private ApplicationContext applicationContext;
public MyBean getObject() {
MyBean myBean = new MyBean();
if (true /* some condition */) {
myBean.setDependency(applicationContext.getBean(DependencyX.class));
} else {
myBean.setDependency(applicationContext.getBean(DependencyY.class));
}
return myBean;
}
// Implementation of isSingleton => false and getObjectType
}
Maybe a bit better approach is if you use factory bean to create the dependency bean in case you want to have only one such bean in your application context:
public MyDependencyFactoryBean implements FactoryBean<MyDependency> {
public MyDependency getObject() {
if (true /* some condition */) {
return new MyDependencyX();
} else {
return new MyDependencyY();
}
}
// Implementation of isSingleton => false and getObjectType
}
SpEL
With SpEL there are many possibilities. Most common are system property based conditions:
<bean class="com.example.MyBean">
<property name="dependency" value="#{systemProperties['foo'] == 'bar' ? dependencyX : dependencyY}" />
</bean>
Property placeholder
You can have property placeholder resolve your bean reference. The dependency name can be part of the application configuration.
<bean class="com.example.MyBean">
<property name="dependency" ref="${dependencyName}" />
</bean>
Spring profiles
Usually the condition you want to evaluate means that a whole set of beans should or should not be registered. Spring profiles can be used for this:
<!-- Default dependency which is referred by myBean -->
<bean id="dependency" class="com.example.DependencyX" />
<beans profile="myProfile">
<!-- Override `dependency` definition if myProfile is active -->
<bean id="dependency" class="com.example.DependencyY" />
</beans>
Other methods can mark the bean definition as lazy-init="true", but the definition will be still registered inside application context (and making your life harder when using unqualified autowiring). You can also use profiles with #Component based beans via #Profile annotation.
Check ApplicationContextInitialier (or this example) to see how you can activate profiles programatically (i.e. based on your condition).
Java config
This is why Java based config is being so popular as you can do:
#Bean
public MyBean myBean() {
MyBean myBean = new MyBean();
if (true /* some condition */) {
myBean.setDependency(dependencyX());
} else {
myBean.setDependency(dependencyY());
}
return myBean;
}
Of course you can use more or less all configuration methods in the java based config as well (via #Profile, #Value or #Qualifier + #Autowired).
Post processor
Spring offers numerous hook points and SPIs, where you can participate in the application context life-cycle. This section requires a bit more knowledge of Spring's inner workings.
BeanFactoryPostProcessors can read and alter bean definitions (e.g. property placeholder ${} resolution is implemented this way).
BeanPostProcessors can process bean instances. It is possible to check freshly created bean and play with it (e.g. #Scheduled annotation processing is implemented this way).
MergedBeanDefinitionPostProcessor is extension of bean post processor and can alter the bean definition just before it is being instantiated (#Autowired annotation processing is implemented this way).
UPDATE Oct 2015
Spring 4 has added a new method how to do conditional bean registration via #Conditional annotation. That is worth checking as well.
Of course there are numerous other ways with Spring Boot alone via its #ConditionalOn*.
Also note that both #Import and #ComponentScan (and their XML counterparts) undergo property resolution (i.e. you can use ${}).
I had a case where I needed to inject different beans depending on property: "my.property". In my case this solution was successful:
<property name="name" ref="#{ ${my.property:false}==true ? 'bean1' : 'bean2' }"/>
I needed to add the apostrophes around bean names in order to make it work.
In your #Configuration class declare a bean to be conditionally created:
#Bean
#Conditional(CustomFeatureCondition.class)
public Stuff stuff() {
return new Stuff ();
}
In the place of using just #Autowire it with required = false option:
#Component
#Setter(onMethod_ = #Autowired(required = false))
public class AnotherStuff {
private Stuff stuff;
// do stuff here
}
This way you'll get Stuff bean if it exists in the context and stuff = null if it doesn't.
I suppose the simpest way:
#Autowired #Lazy
protected A a;
#Autowired #Lazy
protected B b;
void do(){
if(...) { // any condition
// use a
} else {
// use b
}
}
In case you do not declare nessassary bean, Spring throws at runtime NoSuchBeanDefinitionException