Spring Config file consisting of List of Implementations - java

I Am very new to Spring. I have an Interface (MessageHandler ) which has a get method, this method returns a list of Implementations of another interface (messageChecker).
public interface MessageHandler {
public void process(BufferedReader br);
public void setMessageCheckerList(List mcList);
[B]public List getMessageCheckerList();[/B]
}
In my Spring XML configuration , i have something like this ,along with other beans
<bean id="messageHandler" class="com.XXX.messagereceiver.MessageHandlerImpl">
<property name="messageCheckerList" ref="checkerList"/>
</bean>
<bean id="checkerList" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="HL7Checker"/>
</list>
</constructor-arg>
</bean>
<bean id="HL7Checker" class="com.XXX.messagereceiver.HL7CheckerImpl">
<property name="messageExecutor" ref="kahootzExecutor"/>
</bean>
Here i am passing a checkerlist - which is a list of Implementations ( For now i have only 1) of the Interface (messageChecker)
Checkerlist is containing references to Bean Id's which are actual implementaions.
HL7Checker is an implementation of an Interface messageChecker.
But when i run the main program, When i inject the bean "messageHandler" and call the getMessageCheckerList, It returns a null value. These getter and setter methods are working fine without using spring.
I am not sure what seems to be the problem.

I don't know the answer for you troubles, but I would check:
is the setter setMessageCheckerList(List) in messageHandler bean called? (either using some debugger or some trace output like System.out...). If it's not, there's probably something wrong with your Spring XML configuration setup. The bean definition you posted requires the property to be set and Spring wouldn't create the messageHandler bean without setting the property.
who calls the setMessageCheckerList(List) setter? Or even more precise, what code writes to the field which stores the value of the property? Maybe the field is initialized properly by Spring but gets overwritten to null later on?
are you sure you call the getMessageCheckerList on the very same object Spring has configured for you (that is, the messageHandler bean). The definition you have posted clearly states an instance of MessageHandlerImpl is created by Spring, but it doesn't prevent other instances to be created in other ways. So maybe the instance created by Spring holds the proper value, but you run the get... on a wrong instance?

Related

How Spring loads properties file in memory?

Am really new to spring, so please don't get angry and bear with me for a while.
I'm trying to understand how application.properties or any other external config file values gets associated with the places where config file's keys (value="${log4j.configuration}") are mentioned to consume their values from file itself.
For example below is spring bean xml file:
<bean id = "propertiesToBeTaken"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:application.properties</value>
<value>classpath*:*keys.properties</value>
</list>
</property>
</bean>
<bean id="log4jLoader" class="my.loader.Log4jLoader">
<property name="log4jCongif" value="${log4j.configuration}" />
</bean>
As you can see, propertiesToBeTaken is an instance of class org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.
And in second case ,log4jLoader is an instance of class my.loader.Log4jLoader, where log4j.configuration key's value is assigned to Log4jLoader class's instance variable log4jCongif.
My questions are below:
There is no locations variable in class PropertyPlaceholderConfigurer, then what is locations here and from where it came ? How can I relate locations to class's instance propertiesToBeTaken?
If lets say, application.properties key value pairs gets loaded into memory, then who or I mean which method loads that ? And even if it gets loaded then how those key value pairs of application.properties file are accessible to Log4jLoader's instance variables...?
Last but I think it could very stupid question, In class log4jLoader class, there is a setLog4jConfig(String log4jpropertiesLocation), but I really cant see who is calling this method. Just correct me here, Its not true, that In spring what ever the beans of object we have created, calls automatically class's instance methods. RIGHT ? I need to search more in code. CORRECT ?
Please put some light on my doubts here. Read about this alot on spring docs and online as well, but could not understand. Really want to understand how it's happening.
Thanks
Answers to your questions:
locations in bean config XML is referring to the setLocations method of PropertiesLoaderSupport class which Set locations of properties files to be loaded. PropertiesLoaderSupport is parent class of PropertyPlaceholderConfigurer in multi-level inheritance. See Official Document
When PropertyPlaceholderConfigurer gets instantiated by Spring IoC, these properties are set in the bean, now any other bean in the config XML asks for property values using ${key.name}, spring injects the value from the bean having value for this key. In your case Log4jLoader requires ${log4j.configuration} so it's value will be injected by PropertyPlaceholderConfigurer or it's any parent class.
setLog4jConfig spring calls this method when it has to give value to one of the property of the class Log4jLoader. In your case because of <property name="log4jCongif" value="${log4j.configuration}" /> configuration spring will call setter method of the property log4jCongif to inject the value. Yes spring can call instance methods (specially setter) as per the configuration.

Spring method to get all beans of a given type

I am trying to get all the beans of the same type from an FileSystemXmlApplicationContext.
I was using factory.getBeansOfType(SomeType.class) but I have noticed it only returns top-level beans, is there any other method I can use that would return all the beans of a given type, even nested beans?
Example usage:
<bean name="topLevelBean" class="SomeClass">
<property name="someProperty">
<bean bean="nestedBean" class="SomeClass">
</property>
</bean>
Calling factory.getBeansOfType(SomeClass.class) returns only topLevelBean but not nestedBean.
Documentation of getBeansOfType says it only returns top-level beans.
My question is: is there any method that returns all beans of the desired type.
I can get access to all the beans by implementing the BeanPostProcessor interface and adding it to the spring context file.
I'm not sure but possibly BeanFactoryUtils#beansOfTypeIncludingAncestors() might return those (doc doesn't say).

Spring injecting one property dynamically

I am new to Spring and i am stuck with a scenario where i need help.
My Scenario is i have a bean definition for some specific module like this.
<bean name="ruleEngineAction" class="com.xxxxx.yyyy.UserAction" scope="prototype">
<property name="userManager">
<ref bean="userManager" />
</property>
<property name="userDto">
<ref bean="userDto" />
</property>
</bean>
now within this bean i want to use one more property but that depends on the application flow like
<property name="roleManager">
<ref bean="roleManager">
</property>
so should i include this property with in the bean definition itself or i can do it dynamically in code because i don't want this property to be used a lot.
Please suggest me the right and efficient approach.
From what I understood from question, there is only one bean of type roleManager but the usage of roleManager is based on application flow.
In this scenario, I would recommend you to inject roleManager to ruleEngineAction as you would do with any other bean but use the bean only when it is necessary.
It is a bad practice to needless dependency to spring in normal classes like adding reference to applicationContext for fetching the bean dynamically at runtime.
Whether or not, you inject this bean, it'll anyways be created by Spring. Why not just include the property in your UserAction and whether to use it or not, can be decided in your class. No harm in having the bean injected, because you'll anyways use it for some scenarios.
Had the scenario been like, the object won't be created, if you don't inject/use, then it would make sense to consider this situation, but since Spring will create the object anyways, it really shouldn't be a problem to just inject it.
Well you need to add new property with getter and setter in your class com.xxxxx.yyyy.UserAction for roleManager like :
class UserAction {
// your previous properties userManager, userDto, etc.
private RoleManager roleManager; // assuming interface/class as RoleManager for roleManager
// getter and setter for roleManager
// your other action methods which will use roleManager
}
There is no problem if you inject also.Whenever you access that class only it will create the object of that class.

Setting Values of enum via Spring Integration

I have a system where I have an enum of Shops for example. These shows each have their own ShopCommand property (some of which share the same type of command class). from a method in the command class I then want to call send on a Spring Integration gateway. Where I'm confused is how to actually insantiate this gateway in spring. Ideally what I want is to construct the enum via XML configuration with command property being created also in spring, which has the property outGateway set via Spring. I'm not sure if I've made myself very clear with this descrition, if clarification is needed then just ask!
I think this is what you are asking for:
Say I have an enum for ShopType
public enum ShopType {
GROCERY, DEPARTMENT, MALL;
}
Then I have some Store bean that I want to setup via spring configuration. You can instantiate and use the enum like this:
<bean id="DEPTARTMENT_STORE" class="my.package.ShopType" factory-method="valueOf">
<constructor-arg value="DEPARTMENT"/>
</bean>
<bean id="searsStore" class="my.package.Store">
<property name="shopType" ref="DEPTARTMENT_STORE"/>
</bean>
The factory-method points to a static method that is used to create the object. So you can use the enum's method "valueOf" as a factory method.

Are there Compound property values in Spring

I read about Compound property names in the "The Spring Framework (2.5) - Reference Documentation - chapter 3.3.2.7"
Can i use the same concept to set values of properties? Can i use a compound string as a value expression?
<bean id="service1" class="a.b.c.Service1Impl" scope="prototype">
<property name="service2" ref="service2"/>
<property name="service2.user" value="this-service1-instance.user"/>
</bean>
<bean id="service2" class="a.b.c.Service2Impl" scope="prototype">
...
</bean>
User is a property of a.b.c.Service1Impl which is not in control of Spring. I want to forward this property to a.b.c.Service2Impl.
Rather than use a plain old factory bean, rather use a factory method to create the bean of the property and then inject that result...
iow
in your case, it would look something like this...
<!-- the bean to be created via the factory bean -->
<bean id="exampleBean"
factory-bean="serviceLocator"
factory-method="createInstance"/>
So the bean of id is created by calling createInstance on bean serviceLocator.
Now spring does not support nested properties out of the box, though you could look at creating a custom editors which might provide that support - possible but tricky. Possibly not worth the effort.
One mechanism you could look at using is nesting using the factory-bean factory-method technique...
Something like:
<bean id="c" class="C" />
<bean id="b" factory-bean="c" factory-method="getB"/>
<bean id="a" factory-bean="b" factory-method="getA"/>
This will effectively expose: a.b.c where C has a method getB and A has a method getB
I had to do something similar, and I'm afraid it's not possible. I had to write a [FactoryBean][1] to expose the property.
It would look something like this:
public class UserFactory implements BeanFactory {
private Service2 service2;
// ... setter and getter for service2
public Object getObject() {
return getService2().getUser();
}
public Class getObjectType() {
return User.class;
}
public boolean isSingleton() {
// Since it's a prototype in your case
return false;
}
}
Come to think of it, in your case, you'd probably define the factory itself as a prototype, in which case your isSingleton() may return true, you'll need to play around with this a little bit.
Spring's XML wiring syntax supports lists, maps and properties objects, and you can create other 'data' objects via property editors.
Edit: (Oh I see what you are asking.) I think that the answer is no. I don't recall having seen any mention of calling getters on a bean or non-bean object in the Spring documentation, let alone a syntax for doing this in the wiring file. It tends to go against the grain. Spring wiring is declarative, and calling a getter would lead to patterns that are bordering on procedural.

Categories