Spring 3.x PropertyOverrideConfigurer insists on using set, not constructor - spring

Trying to use Spring PropertyOverrideConfigurer or some such subclass, to help
create the following bean:
public class Foo {
private final String name;
public Foo(String name) { this.name = name; }
public String getName() { return name; }
}
Suppose my bean definition is something like
<bean id="foo" class="Foo">
<constructor-arg name="name" value="abc">
</bean>
I've handed Spring a file foo.properties, in there it finds an entry
foo.name="def"
So the default name property for Foo bean is "abc", I want it overriden to be "def";
HOWEVER I do not want to have an explicit setName(String name) method hanging
off my Foo class, since despite what Spring thinks I consider this a terrible
idea in software development. I expect Spring to be able to pass the
overridden value as "def" to the constructor of Foo,
not call Foo later with setName("def").
I have not gotten this to work, is there a way? The only success I've had is
to add the method
public void setName(String name) { this.name = name; }
to the Foo class, which again I think is a terrible idea since it opens
up your class for unintentional side-effecting later.
Is there any hope? Can I modify the bean definition somewhere before
Spring creates Foo with the (wrong) "abc" name?

You can definitely do it. You xml should look somewhat like:
<bean id="foo" class="Foo">
<constructor-arg index="0" value="abc"/>
</bean>
Assuming that constructor has one parameter and "abc" is a value coming from your property file. In this case the setter is not needed.
More information is available in Spring documentation at http://static.springsource.org/spring/docs/3.0.x/reference/beans.html#beans-factory-collaborators

Related

Spring 3 constructor injection anomaly: documentation vs. reality

Facts
Spring 3.2 documentation (http://docs.spring.io/spring/docs/3.2.9.RELEASE/spring-framework-reference/htmlsingle/#beans-constructor-injection):
When another bean is referenced, the type is known, and matching can occur (as was the case with the preceding example). When a simple type is used, such as true, Spring cannot determine the type of the value, and so cannot match by type without help.
package examples;
public class ExampleBean {
// No. of years to the calculate the Ultimate Answer
private int years;
// The Answer to Life, the Universe, and Everything
private String ultimateAnswer;
public ExampleBean(int years, String ultimateAnswer) {
this.years = years;
this.ultimateAnswer = ultimateAnswer;
}
}
In the preceding scenario, the container can use type matching with simple types if you explicitly specify the type of the constructor argument using the type attribute. For example:
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
My class:
package client;
public class Client {
private int id;
private String name;
public Client(int id, String name, String email) {
super();
this.id = id;
this.name = name;
}
}
bean definition:
<bean id="someClient" class="client.Client">
<constructor-arg value="5"></constructor-arg>
<constructor-arg value="5"></constructor-arg>
<constructor-arg value="5"></constructor-arg>
</bean>
Problem
I would have expected that the Spring IoC container will fail to create the bean someClient, since as stated above, it should be unable to address the types of constructor arguments specified. But, again, according to the docs a bit earlier:
If no potential ambiguity exists in the constructor arguments of a bean definition, then the order in which the constructor arguments are defined in a bean definition is the order in which those arguments are supplied to the appropriate constructor when the bean is being instantiated.
But alas, Spring registers the someClient bean effortlessly. This seems like a contradiction to me.
Question
So what is an ambiguous situation, according to Spring? The above example is clearly not ambiguous, Spring happily supplies the arguments in the order as they are defined in the bean definition. When is it really useful to use name/index attributes in the bean definition?
Consider this
<constructor-arg value="5"></constructor-arg>
You haven't specified a type, but a 5 can easily be converted to a String, or any of the numerical types. Similarly, and as an example,
<constructor-arg value="java.lang.String"></constructor-arg>
Spring can produce a String or a Class object as an argument. If a constructor was available for each of those types, then there would be ambiguity. If only one constructor exists, then the appropriate conversion strategy for that constructor will be used.
There's no ambiguity if there is only one constructor.
What is the point to confuse Spring? My unique explanation is testing or research.
But for the real life, if you see the same code three months later. I am sure you are not going be able to figure out what you are trying to do, is not clear and not readable your own code.
Avoid complicate the things. You can use the index attribute and the name attribute. I used to work with the second.
Now, how a strong suggestion, use annotations instead.
Think that you are able to share your code.

How to pass parameter(s) via constructor to another object dynamically with spring annotation

Let say we have a simple class like below. We could use it within/without default constructor. I am really curious about is it possible to pass argument/parameter to another object via constructor in Spring framework. To explain what I want to do, please
see the code sample below.
#Component
public class Class{
String text = null;
String text2 = null;
Class( text, text2 ){
super();
this.text = text;
this.text2 = text2;
}
#Overide
public void toString(){
System.out.printf( "Text" + text + ", " + "Text2" + text2);
}
/** Methods and Setter/Getter etc. **/
}
After defining class and Spring annotations, I would like to call this object via Spring.
public class Usage{
#Autowired
Class classExample;
public void method(){
String text = "text";
String text2 = "text2";
/** One way can be using setters **/
classExample.setText(text);
classExample.setText2(text2);
System.out.println( classExample.toString() );
/** Another way can be using a method **/
classExample.set(text, text2);
System.out.println( classExample.toString() );
/**What I wanted is calling it via constructor injection dynamically**/
/** Normal way we could call this **/
//classExample = new Class(text, text2);
//System.out.println( classExample.toString() );
}
}
Is it possible to inject parameter(s) dynamically to another object.
If you use spring xml configuration you can use the constructor-arg parameter.
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="java.lang.String" value="42"/>
</bean>
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html#beans-factory-collaborators
But remember, the default scope of your bean is singleton!
Is it possible to inject parameter(s) dynamically to another object.
Lets create a "dynamic" bean, so lets set the scope of the bean to prototype to get a fresh instance evrytime it gets called.
<bean id="exampleBean" class="examples.ExampleBean" scope="prototype">
<constructor-arg type="int" value="#{getRandomNumber}"/>
</bean>
In this case, every time a new bean will be created with a new random number.
You should take a look at FactoryBean

Inject properties via annotation

I am new for spring security. I've seen many posts on how to inject values via annotation from external property file. I've tried many ways, but I always end up with java.lang.IllegalArgumentException: Could not resolve placeholder 'val.id' exception.
Can you provide me some tips how to handle this exception please?
My java class is the following one:
#Controller
public class Employee {
#Value("${val.id}")
public String valId;
public String getValId() {
return valId;
}
public void setValId(String valId) {
this.valId = valId;
}
My property file is called val.properties which is located under WEB-INF, and its content is
val.id=xyz
I put the following in my main context bean.
<context:property-placeholder location="/WEB-INF/*.properties" />
<bean id="valProp" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/val.properties"/>
A continuous question:
The injecting values from properties file to annotated beans works fine as I accepted the answer above. However, I cannot able to inject it to #PreAuthorize(...) annotation by following the same procedure.
Assume I want to secure a method called 'update'. This method is allowed if and only if valId is equal to empId. values of valId and empId are initialized in the val.properties file.
my java bean is:
public class Employee {
public String valId;
public String empId;
public String getValId() {
return valId;
}
public void setValId(String valId) {
this.valId = valId;
}
public String getEmpId() {
return empId;
}
public void setEmpId(String empId) {
this.empId = empId;
}
}
my property file contains:
val.id=nn
emp.id=nn
I have the place holder configuration in my main context file:
<context:property-placeholder location="/WEB-INF/*.properties" />
<bean id="valProp" class="org.springframework.beans.factory.config.PropertiesFactoryBean"
p:location="/WEB-INF/val.properties"/>
My PreAuthorize annotation (method security) is:
#PreAuthorize("(#{valProp['val.id']} == #{valProp['emp.id']})")
public boolean update(){
//if accessable
return true;
}
But the expression #{valProp['val.id']} == #{valProp['emp.id']} is not evaluated.
Did I do any mistake to inject values? It was worked when I annotate member variables, but it doesn't work here. Any idea please? Thanks in advance.
try to consider the following
1). change your annotation to:
#Value("#{valProp['val.id']}")
2). Replace PropertyPlaceholderConfigurer by PropertiesFactoryBean.
Hope this will resolve the exception.
The reason why the exception is thrown is, because the property placeholder by default throws an exception when a values cannot be resolved.
Furthermore you have two property placeholders, via which probably not all values can be resolved.
You can change this behaviour via setting the ignore-unresolvable property:
<context:property-placeholder location="/WEB-INF/*.properties" ignore-unresolvable="true" />
<bean id="valProp" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/val.properties" p:ignoreUnresolvablePlaceholders="true" />
Note however that b< turning off this feature typos in a property file will not be detected.

How to create dynamic beans which have only a constructor with args

I have a bean with final field.
public class Foo {
Service service;
final String bar;
public Foo(String bar){};
}
service is not final and has a setter. bar is final and can have many values. I cannot remove the final keyword. I try to create a spring factory that allows to create Foo's instances with injected service and dynamic bar value. factory.create(bar). Foo beans are instanciated at runtime because bar value is not known and unbounded
I have try:
#Configuration, but configuration does not allow parameters not managed by spring or dynamic parameter.
Lookup method needs a no-arg constructor.
Any idea ?
Thanks!
Take a look at ApplicationContext.getBean(String name, Object... args) method. You can pass arguments to bean creation with args parameter.
You can use constructor injection in the Application Context XML as one way to do this:
<bean name="foo" class="com.example.Foo">
<constructor-arg index="0">Bar</constructor-arg>
</bean>
EDIT: Missed that, check out this question: How to use #Autowired in spring
The second answer (not by me)
It looks like you might be able to use #Configurable annotation here.

How to bind a bean property to another one and observe changes in Spring Framework

I'm wondering that if there is a way for binding a spring bean's property to another bean's property so if any change on binded property occurs in runtime, what i expect is referencing bean's property also changes. I'll explain more with a little code snippet.
<bean id="johnHome" class="example.Contact">
<property name="phone" value="5551333" />
</bean>
<bean id="johnWork" class="example.Contact">
<property name="phone">
<util:property-path path="johnHome.phone" />
</property>
</bean>
OK. This works at initial bean wiring but what i exactly want is to bind property so if the property changes at runtime the referencing bean also changes. If i should like to show with a metaphor it will seem like this.
<bean id="johnHome" class="example.Contact">
<property name="phone" value="5551333" />
</bean>
<bean id="johnWork" class="example.Contact">
<property name="phone">
<util:bind path="johnHome.phone" />
</property>
</bean>
Am i overloading the spring's concept too much or is this possible without a lot of tricks?
Thanks..
Simplest way - make that property a bean which is referenced by the two other beans, e.g. for a String value have a StringHolder class:
public class StringHolder {
private String value;
// setter and getter elided due to author's lazyness
}
The whole idea behind Spring is (was?) to keep a clean object-oriented design consisting of plain old java objects and use the spring framework to handle the tedious object creation. As for AOP, this should only handle cross-cutting concerns. I'm not at all convinced that this is one of those cases where AOP is a good idea. Your application relies on the behaviour of these phone numbers getting synced to each other, it's one of the main functionalities. As such, your design should reflect this.
Probably the most logical way to handle this specific problem is to make phone numbers their own class (which is also handy if you ever want to distinguish different types of phone numbers).
If you have a PhoneNumber object which takes the number as a constructor argument the mapping becomes trivial:
<bean id="johnFirstPhone" class="example.PhoneNumber">
<constructor-arg value="5551333" />
</bean>
<bean id="johnHome" class="example.Contact">
<property name="phone" ref="johnFirstPhone" />
</bean>
<bean id="johnWork" class="example.Contact">
<property name="phone" ref="johnFirstPhone" />
</bean>
Of course whether you'd map it like this in a static file is another matter, but the thing is in this situation you pretty clearly just need a reference/pointer.
I don't think what you're doing is possible in Spring 2.5. It may be possible in Spring 3, using the new expression syntax, but I don't think so.
Even if it were, it'd be confusing, I think. Better to stick your shared value into its own class and inject an instance of that class into the other beans that need to share it.
I can think of two possibilities.
One is (it is kind of a hack), if you don't have very many beans that need to be linked like the ones in your example, you could inject johnWork into the johnHome bean, and in johnHome.setPhone you could update the johnWork phone property, something like:
public class Contact {
private Contact myWorkContact;
private String phone;
public void setPhone(String phone) {
this.phone = phone;
if (this.myWorkContact != null) {
this.myWorkContact.setPhone(phone);
}
}
public void setWorkContact(Contact c) {
this.myWorkContact = c;
}
}
Or you could have HomeContact and WorkContact both extend a class Contact and do the same injection with that.
If you have tons and tons of beans that will need this (like if your application actually IS dealing with contact information), with AOP (you'll need AspectJ for the example given) I think you could do something like this (it will be a bit memory intensive if you get a ton of objects, but you can see how something like it would work):
Warning: this actually got complicated fast, but I'm pretty sure it would work after you worked out a few kinks
public class Contact {
...
private String phone;
private String name;
private Integer id;
public Contact(Integer id, String name, String phone) {
this.phone = phone;
this.name = name;
this.id = id;
}
public void setPhone(String phone) {
this.phone = phone.
}
//Other getters, setters, etc
...
}
#Aspect
public class ContactPhoneSynchronizer {
//there is probably a more efficient way to keep track of contact objects
//but right now i can't think of one, because for things like a tree, we need to
//be able to identify objects with the same name (John Smith), but that
//have different unique ids, since we only want one of each Contact object
//in this cache.
private List<Contact> contacts = Collections.synchronizedList(new ArrayList<Contact>());
/**
This method will execute every time someone makes a new Contact object.
If it already exists, return it from the cache in this.contacts. Otherwise,
proceed with the object construction and put that object in the cache.
**/
#Around("call(public Contact.new(Integer,String,String)) && args(id,name,phone)")
public Object cacheNewContact(ProceedingJoinPoint joinPoint, Integer id, String name, String phone) {
Contact contact = null;
for (Contact c : contacts) {
if (id.equals(c.getId()) {
contact = c;
break;
}
}
if (contact == null) {
contact = (Contact) joinPoint.proceed();
this.contacts.add(contact);
}
return contact;
}
/**This should execute every time a setPhone() method is executed on
a contact object. The method looks for all Contacts of the same
name in the cache and then sets their phone number to the one being passed
into the original target class.
Because objects are passed by reference until you do a reassociation,
calling c.setPhone on the object in the cache should update the actual
instance of the object in memory, so whoever has that reference will
get the updated information.
**/
#After("execution(example.Contact.setPhone(String) && args(phone)")
public void syncContact(JoinPoint joinPoint, String phone) {
Contact contact = joinPoint.getTarget();
for (Contact c : this.contacts) {
if (c.getName().equals(contact.getName()) {
c.setPhone(phone);
}
}
}
}
Again, there is probably 100 ways you could optimize this, since I'm typing it off the top of my head; that is, if you wanted to go this route in the first place. In theory it should work but I haven't tested it at all.
Anyway, Happy Springing!

Resources