Creating a Spring Bean using FactoryMethod with variable arguments from Spring? - spring

How can we create a bean using FactoryMethod with variable arguments.
public class ConnectionFactoryClass {
public static Connection composeConnection(final Property... properties) {
...
}
}
bean.xml
<bean id="Connection"
class="com.example.ConnectionFactoryClass"
factory-method="composeConnection"
scope="singleton">
<constructor-arg ref="Driver"/>
<constructor-arg ref="Pool"/>
</bean>
Spring is giving me an error saying,
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'Connection' defined in file [./beans.xml]: No matching factory method found: factory method 'composeConnection'

Try the following:
<bean id="Connection"
class="com.example.ConnectionFactoryClass"
factory-method="composeConnection"
scope="singleton">
<constructor-arg>
<array>
<bean ref="Driver" />
<bean ref="Pool" />
</array>
</constructor-arg>
</bean>
I think you are having a problem because the JVM turns a var arg params into an Object Array and you need to pass in a single paramater to the constructor which is the array of objects. I have not tried the above xml so I might have typos in it, but something like the above should work.

Related

How to set constructor based injection values

<bean id="someBean" class="someClass" >
<constructor-arg index="0" value=""/>
<constructor-arg index="1" value=""/>
</bean>
</beans>
How can I set values from java code?
You can pass the constructor arguments to getBean method as below. But this will work only if the scope of your bean is configured as prototype.
context.getBean("someBean" , new Object[] {"kswaughs", "Stackoverflow user"} );
If you try to call this method for singleton beans, Spring will throw below error.
org.springframework.beans.factory.BeanDefinitionStoreException: Can only specify arguments for the getBean method when referring to a prototype bean definition

How would I specify a bean reference as an argument-resolver, in Spring 3-1?

This is a syntax question about a Spring configuration (refer to spring-beans-3.1.xsd and spring-mvc-3.1.xsd).
I have a specific bean definition (id="SecurityRequestParametersArgumentResolver") that I want to register as a custom argument resolver. The xml fragment is:
<bean id="SecurityRequestParametersArgumentResolver"
class="xxx.security.web.SecurityRequestParametersArgumentResolver">
<property name="credentialsManager" ref="CredentialsManager" />
<property name="tokenService" ref="TokenService" />
</bean>
... AND I would like to use a bean reference. The following three lines don't obey the xsd-grammar ( what should be the correct tag declaration here? )
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean ref="SecurityRequestParametersArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
... All of the examples I have seen look like THIS, and thus are going after the default no-argument constructor
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="class="xxx.security.web.SecurityRequestParametersArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
Repeating the question, what should the Spring syntax be in order to use a bean reference as a custom argument resolver?
Thanks!
At least the constructor argument problem can be solved easily
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="class="xxx.security.web.SecurityRequestParametersArgumentResolver">
<constructor-arg value="123"/>
</bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>
But I do not know any way to use a reference instead of a bean within <mvc:argument-resolvers>. But depending on what you want to do, there are several workarrounds.
Use a Bean Factory
Create a proxy class that implements the HandlerMethodArgumentResolver and forward every call to an other instance, then you can have your own SecurityRequestParametersArgumentResolver like a normal bean and register the Proxy in the <mvc:argument-resolvers> section.
Proxy:
class HandlerMethodArgumentResolverProxy
implements HandlerMethodArgumentResolver{
HandlerMethodArgumentResolver delegate;
publicHandlerMethodArgumentResolverProxy
(HandlerMethodArgumentResolver delegate){
this.delegate=delegate;
}
public boolean supportsParameter(MethodParameter parameter) {
this.delegate.supportsParameter(parameter);
}
//delegate for resolveArgument
}
config:
<bean id="securityRequestParametersArgumentResolver"
class="xxx.security.web.SecurityRequestParametersArgumentResolver">
...
</bean>
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class "HandlerMethodArgumentResolverProxy">
<constructor-arg
ref="securityRequestParametersArgumentResolver"/>
</bean>
</mvc:argument-resolvers>
</mvc:annotation-driven>

How to add a param to a factory-method of a factory-bean in Spring?

let's say I have a factory bean:
<bean id="myFactory" class="com.company.MyFactory" lazy-init="true">
<property name="myProperty" ref="propA">
</bean>
Let's say propA is a bean injected by IOC used in the factory method. And I have 2 beans generated from this factory:
<bean id="bean1" factory-bean="myFactory" factory-method="instance"/>
<bean id="bean2" factory-bean="myFactory" factory-method="instance"/>
How can I make bean2 to use a different myProperty than bean1 without using a different factory method? Or, how can I pass propA as a parameter to the factory-method from the bean1 or bean2 configuration?
This can be achieved in a slightly different way:
class MyFactory {
public Bean instance(MyProperty myProperty) {
return //...
}
}
Now you can use counterintuitive syntax like following:
<bean id="bean1" factory-bean="myFactory" factory-method="instance">
<constructor-arg ref="propA"/>
</bean>
<bean id="bean2" factory-bean="myFactory" factory-method="instance">
<constructor-arg ref="propB"/>
</bean>
Believe it or not but propA and propB will be used as instance() method arguments.

constructor injection with value provided by another bean

I want to pass value to constructor(type string) with value provided by another bean.
Class BeanOne () {
BeanOne (String message) {
...
}
}
Below declaration will work
<bean id="beanOne"
class="com.abc.BeanOne">
<constructor-arg index="0" type="java.lang.String"
value="Hi There" /> // instead of value="Hi There", i want to use bean property (value="someBean.message")
</bean>
However I want another bean (say BeanTwo) to set value for message property for BeanOne. I tried nested property as given below but it does not work. Also message property is not visible directly in the class & is referred internally by another constructor & then by the method so i cannot use property injection& have to use only constructor injection
You can use the MethodInvokingFactoryBean to get your string value and then inject that into your bean.
<bean id="message" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject"><ref local="someBean"></property>
<property name="targetMethod"><value>getMessage</value></property>
</bean>
<bean id="beanOne" class="com.abc.BeanOne">
<constructor-arg index="0" type="java.lang.String" ref="message"/>
</bean>

How do you acess a property of a bean for reading in a spring xml config file?

I want to do something like the following in spring:
<beans>
...
<bean id="bean1" ... />
<bean id="bean2">
<property name="propName" value="bean1.foo" />
...
I would think that this would access the getFoo() method of bean1 and call the setPropName() method of bean2, but this doesn't seem to work.
What I understood:
You have a bean (bean1) with a
property called "foo"
You have another bean (bean2) with a
property named "propName", wich also
has to have the same "foo" that in
bean1.
why not doing this:
<beans>
...
<bean id="foo" class="foopackage.foo"/>
<bean id="bean1" class="foopackage.bean1">
<property name="foo" ref="foo"/>
</bean>
<bean id="bean2" class="foopackage.bean2">
<property name="propName" ref="foo"/>
</bean>
....
</beans>
Doing this, your bean2 is not coupled to bean1 like in your example. You can change bean1 and bean2 without affecting each other.
If you REALLY need to do the injection you proposed, you can use:
<util:property-path id="propName" path="bean1.foo"/>
You need to use PropertyPathFactoryBean:
<bean id="bean2" depends-on="bean1">
<property name="propName">
<bean class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetBeanName" value="bean1"/>
<property name="propertyPath" value="foo"/>
</bean>
</property>
</bean>
I think you have to inject bean1, then get foo manually because of a timing issue. When does the framework resolve the value of the target bean?
You could create a pointer bean and configure that.
class SpringRef {
private String targetProperty;
private Object targetBean;
//getters/setters
public Object getValue() {
//resolve the value of the targetProperty on targetBean.
}
}
Common-BeanUtils should be helpful.

Resources