Spring Di via setter dynamic constructor parameters - java

I'm beginner with spring framework, and I'm following this tutorial to applicate DI via setter. All works fine, but I'd like add to my class CsvOutputGenerator a constructor with one dynamic parameter, passed on the fly while I getting bean from Application context.
How can I do that?
I've already change my spring configuration in this way:
...
<bean id="CsvOutputGenerator" class="com.mkyong.output.impl.CsvOutputGenerator">
<constructor-arg type="java.lang.String" value="Test"/>
</bean>
...
but in this way is static value for my constructor.

You can pass it via system property for example
<constructor-arg lazy-init="true" type="java.lang.String" value="#{ systemProperties['some.key']}"/>

Try something else, even though Spring isn't made to be used like this (note the "prototype" scope):
<bean id="CsvOutputGenerator" class="com.mkyong.output.impl.CsvOutputGenerator" scope="prototype" />
And then in your code you can do something like this:
CsvOutputGenerator myBean = (CsvOutputGenerator) context.getBean("CsvOutputGenerator", "testing testing");
This is the method in the API that I used above.

The below content is based on the above question and comments.
Say u have a class URLRepo with attribute String url. url is initialized to value.
Then you can do something like this, to wire your CsvOutputGenerator
public class URLRepo {
private String url = "your value";
getters and setters
}
<bean id="urlRepo" class="com.*.*.MyURLRepo"/>
<bean id="CsvOutputGenerator" class="com.mkyong.output.impl.CsvOutputGenerator">
<constructor-arg type="java.lang.String" value="urlRepo.url"/>
</bean>
hope this is what you are looking for.

Related

How to autowire a class with non-empty constructor?

I'd like to #Autowired a class that has a non-empty constructor.
Just the the following as an example, it does not necessairly have to be a view/service. Could be whatever component you like, having non-default constructor:
#Component
class MyViewService {
//the "datasource" to show in the view
private List<String> companies companies;
private MyObject obj;
public MyViewService(List<String> companies, MyObject obj) {
this.companies = companies;
this.obj = obj;
}
}
Of course I cannot just write
#Autowired
private MyViewService viewService;
as I'd like to use the constructor with the list. But how?
Are there better approaches than refactoring these sort of constructors to setters? I wouldn't like this approach as ideally the constructor forces other classes to provide all objects that are needed within the service. If I use setters, one could easily forget to set certain objects.
If you want Spring to manage MyViewService you have to tell Spring how to create an instance of it. If you're using XML configuration:
<bean id="myViewService" class="org.membersound.MyViewService">
<constructor-arg index="0" ref="ref_to_list" />
<constructor-arg index="1" ref="ref_to_object" />
</bean>
If you're using Java configuration then you'd call the constructor yourself in your #Beanannotated method.
Check out the Spring docs on this topic. To address a comment you made to another answer, you can create a List bean in XML as shown in the Spring docs. If the list data isn't fixed (which it's probably not) then you want to use an instance factory method to instantiate the bean.
In short, the answers you seek are all in the Spring docs :)
If a component has a non-default constructor then you need to configure the constructor in the bean configuration.
If you are using XML,
it might look like this (example from the spring reference document):
<beans>
<bean id="foo" class="x.y.Foo">
<constructor-arg ref="bar"/>
<constructor-arg ref="baz"/>
</bean>
<bean id="bar" class="x.y.Bar"/>
<bean id="baz" class="x.y.Baz"/>
</beans>
The key here is constructor wiring of the bean that will be used for the #AutoWire.
The way you use the bean has no impact.

pass "HardCoded" Constructor Arg Class<T> to bean via Spring Config

I have a generic type that I am injecting into a service. Because of the way generics are implemented in Java, I need to have a constructor arg (or property setter) that holds the Class information of the generic type parameter.
My question is -- Can I, via property injection or specifying a constructor arg, pass in an instance of Class with spring?
I DO know the type of T before run time so I know specifically what the Type parameter will be.
I was thinking it would look something like this:
<bean id="dataMartService" class="com.someclass">
<constructor-arg value="java.lang.class<com.someotherclass>" />
</bean>
Am I completely off in how this should happen?
Try:
<bean id="dataMartService" class="com.someClass">
<constructor-arg>
<value type="java.lang.Class">someotherclass</value>
</constructor-arg>
</bean>
Use spring el:
<constructor-arg value="#{ T(java.lang.Math) }" />
(you'll need spring 3.0 for this)
That being said, if you pass a string into an argument where a class is expected during a property set, spring should automatically convert it, though i'm not sure how this works when matching constructors. The above approach is much more concise.
You can use:
//for constructor
public CheckSpell(SpellCheker spellCheker){
this.spellCheker=spellCheker;
}
//Use object reference as bean
<bean id="textEditor" class="com.sring.spellCheck">
<constructor-arg ref="spellChecker"/>
</bean>
<bean id="spellCheker" class="com.spring.SpellCheker"/>

Java Spring Injection String

How do I inject a String into a class. I Have seen plenty of examples of how to inject a class but can't find any for a String.
An example: If your field is called "name" and your class is called "Person" you can use setter injection like this:
<bean id="personBean" class="example.Person">
<property name="name" value="Paul" />
</bean>
It should be as simple as that. You will obviously need setter methods in your Person class for name.
Let Spring know where to find your properties file (in this case myProperties.properties):
<!-- Spring will replace ${} keys with values from the file used by the propertyConfigurer -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="location" value="classpath:myProperties.properties"/>
</bean>
In your class, you can inject like this:
#Value("${web.theme}")
private String theme;
In this case, the property defined bye "web.theme" in myProperties.properties will be injected into the "theme" member variable. But you can also inject in the constructor or setter as well.
If you don't want to use annotations, you can use it in your xml file as well.

Spring: Inject URL for classpath resource

I want to inject the URL of a classpath resource in a way that does not create a dependency on Spring in the Bean. Meaning, the bean should not use Spring's interfaces/classes. How can I do that?
Spring is able to convert classpath:... values into java.net.URL implicitly:
public class Foo {
private URL url;
...
}
.
<bean class = "Foo">
<property name = "url" value = "classpath:..." />
</bean>
Following on from axtavt's answer, if you will allow yourself Spring annotations in the bean, you can do it like this:
#Value("classpath:myClasspathLocation") private URL url;
create your own implementation of a spring resource by extending the org.springframework.core.io.ClassPathResource like MyClasspathResource extends ClassPathResource and inject this type into your bean. Like this you do not have any dependency to spring and can later reimplement your resource with something else.
<bean class="myBean">
<property name="classPathType">
<bean class="org.test.bla.MyClasspathResource">
<constructor-arg index="0" value="classpath:/org/test/bla/MyUrl" />
</bean>
</property>
</bean>
There is hardly anything non-spring that's equivalent to Spring's resource concept.
You could for example use Guava's InputSupplier as an alternative, but you are missing powerful standard spring features if you do.

How can I inject a property value into an annotation configured spring mvc 3.0 controller

First: I'm using Spring 3.0
I have a problem when configuring my controller class. The controller uses a web service which I want to define the endpoint address using a .properties file.
#Controller
public class SupportController {
#Value("#{url.webservice}")
private String wsEndpoint;
...
In my application context xml-file, I've defined this:
<context:property-placeholder location="/WEB-INF/*.properties" />
I've been reading the documentation, trying different approaches (like adding prefix systemProperties.),but I keep getting an error message telling me that it doesn't exist.
Field or property 'url' cannot be
found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext'
Ok. I've figured it out.
Now, in the controller:
#Value("#{settings['url.webservice']")
Then in the context configuration I have this "helper bean":
<util:properties id="settings"
location="/WEB-INF/supportweb.properties"></util:properties>
This should work, too:
#Value("${url.webservice}")
private String wsEndpoint;
I have this configuration and it works fine:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
</bean>
and I iniejct the property in this way
#Value("${root.log.level}")
private String prop;
the field is correctly initialized to "DEBUG" value.
you should check that the
<context:property-placeholder location="/WEB-INF/*.properties" />
is defined in webmvc-config.xml where you create instances of the #Controllers

Categories

Resources