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.
Related
I need to inject a object of a java class in spring controller through applicaionContext.xml. My controller will be ,
#Controller
public class SpringController{
private MyClass obj;
}
I know I can do it with #Autowired annotation.
Is this really good to create a object for a controller through applicaionContext.xml ? Also can I inject a object of a class in controller using the <property> tag inside a <bean> tag ?
Is this really possible ? or please forgive me if it is a stupid question.
I need to know the possible ways for how to inject a object of a class in Spring controller ?
You can of course use #Autowired annotation to autowire the relationships, which can reduce the need to define the properties and constructor arguments for the controller in your applicationContext.xml file. And also to add a dependency to a class, you don't need to modify the configuration files.
But it has some disadvantages too, like if you use #Autowired, there will not be any explicit documentation for the wiring details between Spring managed beans. And to know the relationships between the beans, you have to go through your managed beans. But, if you use configuration files to define the relationships, the relationship details can be found in one place.
You can inject an object of a class into your controller through your applicaionContext.xml as below:
Constructor based injection:
#Controller
public class SpringController{
private MyClass obj;
public SpringController(MyClass obj){
this.obj=obj;
}
}
<bean id="myClassImpl" class="x.y.z.MyClassImpl"></bean>
<bean id="springController" class="x.y.z.web.controllers.SpringController">
<constructor-arg ref="myClassImpl"></constructor-arg>
</bean>
Setter based injection:
#Controller
public class SpringController{
private MyClass obj;
public void setObj(MyClass obj){
this.obj=obj;
}
public MyClass getObj(){
return obj;
}
}
<bean id="myClassImpl" class="x.y.z.MyClassImpl"></bean>
<bean id="springController" class="x.y.z.web.controllers.SpringController">
<property name="obj" ref="myClassImpl"></property>
</bean>
If you want to inject an object in a controller and you particularly want to you use xml,then instead of component scanning of Controller you should create a bean of the controller class of singleton scope in the application context.
Your controller class need not be annotated with #Controller.
you then have to you extend some Controller also like AbstractCommandController, AbstractController, AbstractFormController, AbstractWizardFormController, BaseCommandController, CancellableFormController, MultiActionController SimpleFormController, UrlFilenameViewController
Now to inject a particular object you can use Either Constructor and Setter based injection.
or you can use Autowring by name or type to auto inject the object.
Make sure that you have also declared the bean of that object also in Application Context.
After a DispatcherServlet has received a request and has done its work to resolve locales, themes and suchlike, it then tries to resolve a Controller, using a HandlerMapping. When a Controller has been found to handle the request, the handleRequest method of the located Controller will be invoked; the located Controller is then responsible for handling the actual request and - if applicable - returning an appropriate ModelAndView.
Thats it.
Actually, injection with xml and annotation is same behind the scene. Xml is old fashion while annotations are newer.
Basically, there are 2 types of injection types.
byName
Autowiring by property name. Spring container looks at the properties
of the beans on which autowire attribute is set to byName in the XML
configuration file. It then tries to match and wire its properties
with the beans defined by the same names in the configuration file.
You can give explicit names to beans both with xml and annotation.
#Service("BeanName")
#Component("BeanName")
#Controller("BeanName")
<bean name="BeanName" class="someclass"></bean>
and inject beans by using #Qualifier annotation.
#Autowired
#Qualifier("BeanName")
and with xml
<bean id="MyBean2" class="MyBean2 class">
<property name="Property of MyBean2 which refers to injecting bean" ref="BeanName" />
</bean>
byType
Autowiring by property datatype. Spring container looks at the
properties of the beans on which autowire attribute is set to byType
in the XML configuration file. It then tries to match and wire a
property if its type matches with exactly one of the beans name in
configuration file. If more than one such beans exists, a fatal
exception is thrown.
Default auto wiring mode is byType, so spring will look for matching type in auto wiring. However, older versions of Spring has default behavior none on injection. If you want to inject byType using xml, you should tell spring contaioner explicitly.
For example MyBean2 has a reference to MyBean, by setting autowired attribute to byType it handles injection automatically.
<bean id="MyBean" class="MyBean class">
<property name="Property of MyBean2 which refers to injecting bean" ref="BeanName" />
</bean>
<bean id="MyBean2" class="MyBean2 class"
autowire="byType">
</bean>
It also depends on where the injection take place in your code. There are 2 types, setter getter injection and constructor injection.
Note : There is no difference in #Controller since they are already in spring context.
See also
Spring Beans Auto wiring
I ran into such problem. I was getting "Ambiguous mapping found". (I use xml configuration as well and i am injecting a bean into my controller)
Then looking at my console i realized that my controller was being instantiated twice.
In more detailed look i noticed that my annotation
#Controller(value = "aController")
(Note value = "aController")
was different from my xml configuration where i was instatiating the same controller with different bean id
<bean id="aControleRRRRR" class="package.ControllerClassName"
p:property-ref="beanToInject" />
(Note id="aControleRRRRR")
So in conclusion your #Controller name (value = "aController") needs to be exactly the same as the name you give in the XML configuration (id="aControleRRRRR"), so that Spring can manage to distinct that they refer to the same bean (instance)
Hope this helps
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.
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.
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?
Normally dependencies are injected via setters by the following configuration (http://static.springsource.org/sprin...beans-beanname) :
<bean id="exampleBean" class="examples.ExampleBean">
<!-- setter injection using the nested <ref/> element -->
<property name="beanOne"><ref bean="anotherExampleBean"/></property>
<!-- setter injection using the neater 'ref' attribute -->
<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
Lets say the class examples.ExampleBean has a collection listeners objects, and the method addListener(SomeListenerInterface) is the only possible way add listeners. Can I inject listeners declaratively in xml like its done with property setters?
You could probably conjure up some baroque mechanism for doing this all in XML, but the cleanest way to do this is to use a FactoryBean. You write a class which implement FactoryBean, and which is responsible for constructing and configuring your target object (see Spring docs). Your FactoryBean would have the required getters/setters/autowiring, and injects them into the target object.
This is often the cleanest way to handle non-javabeans in Spring, particularly if you cannot modify the target class.
Here goes property Element definition
Property elements correspond to JavaBean setter methods exposed by the bean classes.
To get your goal, you can use #Autowired annotation. It works even when using an arbitrary name
#Autowired
public void inject(SomeListenerInterface someListenerInterface) {
this.someListenerInterface = someListenerInterface;
}