I'm trying to inject a property everytime a bean (myBean) is called using a lookup method and Spring dependency injection :
<bean id="myBean" class="com.myclass"
<property name="default" ref="myDefault" >
<lookup-method name="getUri" bean="defaultUri" />
</property>
</bean>
<bean id="defaultUri" scope="prototype" class="DefaultUri" >
</bean>
class myclass {
public String getUri(){
return "test"
}
}
Above XML returns this error on startup :
"XML document from PortletContext resource is invalied"
The error seems to be because <lookup-method name="getUri" bean="defaultUri" /> is configured incorrectly.
How can I configure a Spring lookup method within a String 'property' as I'm trying to implement in above XML ?
Lookup method injection is the ability of the container to override methods on container managed beans, to return the lookup result for another named bean in the container.
Now, suppose you want to get a new instance of DefaultUri (which is a prototype bean) every time you call a method (let it be createDefaultUri) in myclass (which is a singleton bean). Then you can define MyClass as this:
class abstract Myclass {
public String getUri(){
// create a new instance of DefaultUri
DefaultUri defaultUri = createDefaultUri();
return "test"
}
protected abstract DefaultUri createDefaultUri();
}
The Spring Framework will generate a dynamic subclass of Myclass that will override the createDefaultUri method to provide a new instance of DefaultUri every time it is requested for.
You can now define the name of lookup-method name in the Myclass bean definition as this:
<bean id="defaultUri" scope="prototype" class="DefaultUri">
</bean>
<bean id="myBean" class="com.myclass"
<lookup-method name="createDefaultUri" bean="defaultUri" />
</bean>
Suppose singleton bean A needs to use non-singleton (prototype) bean B, perhaps on each method invocation on A(getBeanB()), we expect to get new instance of bean B for every request. But The container only creates the singleton bean A 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. To get new new instance of bean B for every request we need to use lookup-method injection
Please refer to http://www.javapointer.com/spring/spring-core/spring-lookup-method-injection/
Related
I have some code that generates a class from an interface. I need to reference that interface in a Spring XML configuration. Is there a Spring 3 annotations I can use on the interface such that I can reference the generated implementation using <constructor-arg ref="myBeanInterface"/>?
I can reference it using <constructor-arg value="com.mysite.myBeanInterface"/>, however I want to refrence a bean name instead of an explicit class.
Details: The beans are generated by an extension of AbstractFactoryBean. I do not have access to the bean generating code.
Use the name of your factory bean. If you have something like:
<bean id="myBean class="MyBeanInterfaceFactoryBean>
...
</bean>
Then to inject the bean that was generated by the factory bean, just use myBean.
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 have configured a map in spring which returns me the instance based on key. But the thing is it always returns me the same instance of the map entries(plate, spoon, fork) instead of creating a new instance every time even though the bean is a prototype. What am i missing?
Please note i am working on a very old version of spring.
Here my configuration:
<bean id="plate" class="com.xyz.items" singleton="false"/>
<bean id="spoon" class="com.xyz.items" singleton="false"/>
<bean id="fork" class="com.xyz.items" singleton="false"/>
<bean id="ItemFactory" class="com.xyz.items.ItemFactory" >
<property name="registeredItems">
<map>
<entry key="spoon" value-ref="spoon"/>
<entry key="plate" value-ref="plate"/>
<entry key="fork" value-ref="fork"/>
</map>
</property>
</bean>
//Here's the stuff in java
public class ItemFactory {
private Map registeredItems;
private Item getItem(String item ){
Item item = (Item)registeredItems.get(item);
return item;
}}
|
I think that since ItemFactory is singleton it all it's life holds reference to same instance of Bean no matter that referenced bean is prototype scoped. Spring doesn't care about prototype scoped bean destruction, it simply creates new instance of bean when it's referenced from singleton and that's it.
You are referencing bean with smaller scope (prototype) from bean with larger scope (singleton), that's problematic.
See referencing prototype beans from singletons
There are two solution for this case:
Use method injection as described in link above.
In getItem() method retrieve beans directly from Spring application context.
I have a class
public class MakeMeBean {
#Autowired private IAmBean var1;
private IAmNOTBean var2;
public MakeMeBean() {}
public MakeMeBean(IAmNOTBean var) {
this.var2 = var;
}
}
I want to make this class as a bean so I make a wireup.xml as
<bean id="make-me-bean" class="com.blah.blah.MakeMeBean">
<constructor-arg index="0" ref=<PUT REFERENCE BEAN HERE>
<constructor-arg index="1" <I don't want to put anything>
</bean>
Question
a.) How can I make a bean in which one instance variable is a bean and another not? I don't want to inject var2(another bean in wireup.xml)
b.) <PUT REFERENCE BEAN HERE> is a bean imported from jar file, how can I make reference to this bean in wireup.xml
You can't just have some beans in context that you created and another half that spring created (at least not that simple), if you want to manage the instances over spring, spring should have the objects on its context. Of course you have the possibility to instantiate the objects in the context, and after the instantiation you could invoke some setters to set some properties.
In order to use another to user another bean, that I suppose comes from another Spring context, the other spring context needs to be imported in the first one. In order to import a context file you can use:
<import resource="resourcePath" />
When I call getBean(name) on a BeanFactory, I get back an instance of the bean defined in the application context. However, when I call getBean(name) again (with the same name,) I get the same instance of the bean back. I understand how this would be desirable in some (many?) cases, but how do I tell the BeanFactory to give me a new instance?
Example Spring configuration (tersely...I've left out some verbosity, but this should get the point across):
<beans>
<bean id="beanA" class="misc.BeanClass"/>
</beans>
Example Java:
for(int i = 0;i++;i<=1) {
ApplicationContext context = ClassPathXmlApplicationContext("context.xml");
Object o = context.getBean("beanA");
System.out.println(o.toString()); // Note: misc.BeanA does not implement
// toString(), so this will display the OOID
// so that we can tell if it's the same
// instance
}
When I run this, I get something like:
misc.BeanClass#139894
misc.BeanClass#139894
Note that both have the same OOID...so these are the same instances...but I wanted different instances.
You need to tell spring that you want a prototype bean rather than a singleton bean
<bean id="beanA" class="misc.BeanClass" scope="prototype"/>
This will get you a new instance with each request.
The default scope is singleton, but you can set it to prototype, request, session, or global session.