Inject Dynamic Values for the property in Spring - spring

I am very new to Spring and while going through the DI topic through various sources (Book & Internet) I have seen the following pattern of defining bean configuration:
For example we have a class "SampleApp"
public class SampleApp
{
private int intValue;
private float floatValue;
public SampleApp(int value)
{
intValue = value;
}
public void setIntValue(int value)
{
intValue = value;
}
public void setFloatValue(float floatValue)
{
this.floatValue = floatValue;
}
}
Corresponding bean configuration is as follows:
<bean class="somepackage.SampleApp" id="samplebeanapp">
<constructor-arg value="15" />
<property value="0.5" name="floatValue"></property>
</bean>
We have been hard-coding the value here to 15 & 0.5.
Here are my questions :
Is it possible to pass those values as run time parameter with scope as prototype?
If yes, how can we do it? and please elaborate with some example.

Spring configuration files are processed at startup, and Spring singleton beans are instantiated too in that moment. They are not processed again during the application lifecycle, in normal conditions.
You can use such type of property injection to pass configuration values, while you can use injection of object references to determine the structure of your application.
To avoid hardcoding the values inside the XML files, you can extract them in property files using a PropertyPlaceholderConfigurer.
The principle is to program to interfaces as much as possible, so you don't tie yourself to any specific implementation. However, for the case you're thinking, you'll just pass the values at runtime.
Example: BeanA needs the services of DaoBean, but the DaoBean won't be instantiated by BeanA. It will be passed to BeanA through dependency injection and BeanA will only talk to a DaoInterface.
At this point if BeanA want to save 15 and 0.5, will call the methods with the actual values (or more commonly variables).
daoInterface.saveInt(15);
daoInterface.saveFloat(0.5);
I don't use dependency injection to pass the values in this case. Dependency injection is a great tool, but doesn't meant that it has to be used everywhere.

Related

What is the correct way in Spring WS to configure own replacement of DefaultMethodEndpointAdapter?

We have the situation we need to read the parameters sent to the Spring Ws endpoint before the endpoint method is reached. For this purpose we made a descendant of the class
org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter, for example in this way:
public class MyMethodEndpointAdapter extends DefaultMethodEndpointAdapter {
#Override
protected Object[] getMethodArguments(
MessageContext aMessageContext, MethodEndpoint aMethodEndpoint) throws Exception {
Object[] locResult = super.getMethodArguments(aMessageContext, aMethodEndpoint);
MethodParameter[] parameters = aMethodEndpoint.getMethodParameters()
Object locPayloadObject = null;
for (int i = 0; i < parameters.length; i++) {
if (parameters[i].hasParameterAnnotation(RequestPayload.class)) {
locPayloadObject = locResult[i];
break;
}
}
// ... some custom code here dealing with resolved request payload object
}
}
The solution works well, but the real issue here is the configuration. We use the XML configurations to make the things more transparent and manageable, so we defined in the configuration file for web service following settings:
<bean id="defaultMethodEndpointAdapter"
class="somepackage.MyMethodEndpointAdapter"/>
but still after specifying it in this way, the original implementation DefaultMethodEndpointAdapter is instantiated too. Then there are two adapters which are checked and it depends on the order of the configuration loading, which one gets instantiated first - and which one then gets the request when the correct handling instance is evaluated. Even the definition of the bean with name instead of Id
<bean name="defaultMethodEndpointAdapter"
class="somepackage.MyMethodEndpointAdapter"/>
did not help.
Going through with debugger I found out, there is generated the bean name for instantiation of the singletons, named org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter#0 which is used by the instantiated default instance. So, finally, after specification of the bean definition like
<bean id="defaultMethodEndpointAdapter"
name="org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter#0"
class="somepackage.MyMethodEndpointAdapter"/>
We were able to bring Spring to the situation, only one (our) adapter is instantiated and we get the expected behavior.
But this seems to be ugly to us, the dynamically generated name
org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter#0 seems to be a unstable way how to reference the replaced adapter implementation.
Is there some better way how to do it to bring Spring to the situation not to instantiate the default adapter at all?

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 can I inject "nulls" into autowired spring beans?

I am writing unit-tests and have a quite complex setting.
A dependent bean sets up some listeners and passes them autowired services.
I want to test that the listeners are present, but not call them, so I want to pass 'null' instead of the autowired service. (specifically: I do not have setters ...)
#Autowired
SomeService1 service1
#Autowired
SomeService2 service2
public List getListeners() {
List l = new ArrayList();
l.add(new AaaListener(service1));
l.add(new BbbListener(Service2));
return l;
}
#Test
public void testListeners() {
int exptecedSize = 2;
sut.doSomething();
List l = sut.getX().getY().getListeners()
assertEquals(expectedSize,l.size());
}
Note that the SUT does depend indirectly from the class that returns the listeners.
Since this is a very small example from a big setting, I do specifically do not want to use mocks here as I want to test only presence not behavior of the listeners.
Mocking 20 or 30 of such services will slow down the tests massively.
Question: What is the easiest way to inject these nulls into the autowired instance variables?
A) Add setters ?
B) ReflectionUtils ?
C) java-config + #Beans + return null ?
They're already null when the class is instantiated ... or are you actually running them in a spring context?
You can set properties to null in the xml config like this (from the documentation)
<bean class="ExampleBean">
<property name="email"><null/></property>
</bean>
Don't use the Spring context and create the class manually
Use ReflectionTestUtils to set the field. ReflectionTestUtils allows for the setting of private fields where ReflectionUtils does not.

Spring configuration calling more than one method

I have code which looks like the following:
MyContext context = new MyContext();
context.start();
MyEntity entity = context.getEntity();
I want to inject the MyEntity instance into various classes.
But I don't know how to setup my Spring configuration, where I first create an object, then call a method on it and then finally call another method which returns the entity I want to inject.
EDIT 2 - removed the Strings altogether
The most common type of dependencies injected using Spring don't depend on the user input for their construction. This includes data access objects, services etc.,
You are talking about injecting domain objects whose construction depends on the user input either directly or indirectly.
Spring provides #Configurable annotation to inject such domain objects that are created using new operator. You can search for "#Configurable Domain Driven Design" on the internet to get examples of how this can be implemented. I myself used it in one my applications and wrote a simple post here that might help you get started.
Edit:
To create a bean of type MyEntity as per the specification in your updated question, you would need to
define a bean of type MyContext
Create a MyEntityFactory class that would depend on the MyContext bean.
The factory method would take the MyContext bean as argument, calls context.start() on it and returns an instance of MyEntity.
You would define the MyEntity bean using this factory class.
The MyEntityFactory class would be as follows:
public class MyEntityFactory
{
public static MyEntity getMyEntity(MyContext context)
{
context.start();
return context.getEntity();
}
}
The spring bean configuration will be as follows:
<bean id="myContext" class="FQCN.Of.MyContext" />
<bean id="myEntity" class="FQCN.Of.MyEntityFactory" factory-method="getMyEntity">
<constructor-arg ref="myContext" />
</bean>
Since MyEntity is a singleton bean, the factory method will be called only once, btw.
More on creating beans using factory methods here.

How to inject a value to bean constructor using annotations

My spring bean have a constructor with an unique mandatory argument, and I managed to initialize it with the xml configuration :
<bean name="interfaceParameters#ota" class="com.company.core.DefaultInterfaceParameters">
<constructor-arg>
<value>OTA</value>
</constructor-arg>
</bean>
Then I use this bean like this and it works well.
#Resource(name = "interfaceParameters#ota")
private InterfaceParameters interfaceParameters;
But I would like to specify the contructor arg value with the annocations, something like
#Resource(name = "interfaceParameters#ota")
#contructorArg("ota") // I know it doesn't exists!
private InterfaceParameters interfaceParameters;
Is this possible ?
Thanks in advance
First, you have to specify the constructor arg in your bean definition, and not in your injection points. Then, you can utilize spring's #Value annotation (spring 3.0)
#Component
public class DefaultInterfaceParameters {
#Inject
public DefaultInterfaceParameters(#Value("${some.property}") String value) {
// assign to a field.
}
}
This is also encouraged as Spring advises constructor injection over field injection.
As far as I see the problem, this might not suit you, since you appear to define multiple beans of the same class, named differently. For that you cannot use annotations, you have to define these in XML.
However I do not think it is such a good idea to have these different beans. You'd better use only the string values. But I cannot give more information, because I dont know your exact classes.
As Bozho said, instead of constructor arg you could set the property...#PostConstruct will only get called after all the properties are set...so, you will still have your string available ...

Resources