I want to inject a dependency into a custom spring modules validation function. I have tried using #Autowired on the setter, but it has no effect. Does anyone know if or how this can be done?
Here is my valang validator:
<bean id="resellerValidator" class="org.springmodules.validation.valang.ValangValidator">
<property name="customFunctions">
<map>
<entry key="isValidResellerId" value="com.myproject.valang.IsValidResellerIdFunction" />
</map>
</property>
<property name="valang">
<value>
<![CDATA[
{resellerId: ? IS BLANK OR isValidResellerId(?) IS TRUE : '' : 'field.badFormat'}
]]>
</value>
</property>
</bean>
And here is the custom function:
public class IsValidResellerIdFunction extends AbstractFunction {
private ResellerService resellerService;
#Autowired
public void setResellerService(ResellerService resellerService) {
this.resellerService = resellerService;
}
public IsValidResellerIdFunction(Function[] arguments, int line, int column) {
super(arguments, line, column);
definedExactNumberOfArguments(1);
}
#Override
protected Object doGetResult(Object o) throws Exception {
String resellerId = (String) getArguments()[0].getResult(o);
return resellerService.isValidResellerId(resellerId);
}
}
Add this to your application context:
<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
I actually wound up finding the answer here. In summary, 2 things were needed:
Create a FunctionWrapper bean and inject my custom function into the wrapper with scope="prototype". This allows me to inject any dependency I want into my custom function.
Implement the ConfigurableFunction interface so it works with FunctionWrapper.
The FunctionWrapper is automatically discoverable by all valang validators, so no need to declare the custom function explicitly with the customFunction property, and the name of the function is just the bean name you give the FunctionWrapper:
<bean id="resellerValidator" class="org.springmodules.validation.valang.ValangValidator">
<property name="valang">
<value>
<![CDATA[
{resellerId: ? IS BLANK OR isValidResellerId(?) IS TRUE : '' : 'field.badFormat'}
]]>
</value>
</property>
</bean>
<bean id="isValidResellerId"
class="org.springmodules.validation.valang.functions.FunctionWrapper"
scope="prototype">
<aop:scoped-proxy/>
<property name="function">
<bean id="isValidResellerIdFunction"
class="com.myproject.valang.IsValidResellerIdFunction"
scope="prototype">
<property name="resellerService" ref="resellerService"/>
</bean>
</property>
</bean>
The function:
public class IsValidResellerIdFunction extends AbstractFunction implements ConfigurableFunction {
private ResellerService resellerService;
public void setResellerService(ResellerService resellerService) {
this.resellerService = resellerService;
}
public IsValidResellerIdFunction() {}
#Override
public int getExpectedNumberOfArguments() {
return 1;
}
#Override
public void setArguments(int expectedNumberOfArguments, Function[] arguments,
int line, int column) {
super.setTemplate(line, column);
super.setArguments(arguments);
super.definedExactNumberOfArguments(expectedNumberOfArguments);
}
#Override
protected Object doGetResult(Object o) throws Exception {
String resellerId = (String) getArguments()[0].getResult(o);
return resellerService.isValidResellerId(resellerId);
}
}
I am having one method and it contains some business logic like , creating the protocols using some domain specific servers and so.I need to run the method once when my application starts.
How can I achieve my below requirement ?
This is what I have already did. I created the bean for a business class and also for controller in applicationContext.xml and inject the business class bean in the controller .
My applicationContext.xml will be,
<bean id="configInfo" class="com.pointel.Agent_Chat.ServerInfo.ConfigServerInfo">
<property name="configurationServer_name" value="${CS_NAME}"></property>
<property name="configurationServer_host" value="${CS_IPADDRESS}"></property>
</bean>
<bean id="config_con" class="com.pointel.Agent_Chat.ServerConnection.ConfigServerConnection" >
<property name="info" ref="configInfo"></property>
</bean>
<bean id="init_Server" class="com.pointel.Agent_Chat.Initialiser.Initialize_Servers">
<property name="connection" ref="config_con"></property>
</bean>
<bean id="initCon" class="com.pointel.Agent_Chat.controllers.InitServerController">
<property name="init_Server" ref="init_Server"></property>
</bean>
My Controller will be,
#Controller
public class InitServerController {
public static int count = 0;
private Initialize_Servers init_Server;
public InitServerController(){
count++;
System.out.println("Init Controller "+count+" time");
}
public void setInit_Server(Initialize_Servers init_Server) {
this.init_Server = init_Server;
initializeServers();
}
private void initializeServers() {
ServerStatus.config_status = init_Server.initialize_Config_Server();
System.out.println("config_status : "+ServerStatus.config_status);
}
}
My Business class will be ,
public class Initialize_Servers {
private ConfigServerConnection connection;
private InteractionServerConnection interConnection;
private UCSConnection ucsConnection;
public Initialize_Servers(){
System.out.println("Initialize_Servers class instance was created !");
}
public ConfigServerConnection getConnection() {
return connection;
}
public void setConnection(ConfigServerConnection connection) {
this.connection = connection;
}
public boolean initialize_Config_Server(){
try{
ConfServerProtocol protocol = connection.getConnection();
if(protocol != null){
System.out.println("Config server Protocol is not null");
return true;
}
}catch(Exception e){
return false;
}
}
}
Is this the right way ? or any other perfect way to do this ?
Good answers are definitely appreciated.
You can set the bean in the xml file to have an init method using the init-method attribute on the bean XML element, like so:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="myBean" class="com.myjunk.MyBean"
init-method="myInit" >
</bean>
</beans>
This would call the myInit() method on MyBean after the bean was initialized. This happens after the properties were wired together. If you are using Annotations to wire stuff, there are annotations you can use as well, but I don't know them off the top of my head. The method must take no parameters.
The other option is to implement ApplicationContextAware, which provides hooks into getting the application context during the wiring process. Again, this happens after the properties are set on the object.
I have a User factory which simply gets a User from a UserStore:
public class UserFactory
{
#Autowired
private UserStore userStore;
public User getUserFromId(String Id)
{
User foundUser = this.userStore.findUser(Id);
return foundUser;
}
}
Here's my User object:
public class User implements Serializable
{
#Autowired
private List<Announcer> announcers; //I want this injected
private String twitterId;
private String facebookId;
public List<Announcer> getAnnouncers()
{
//lazy init?
return this.announcers;
}
}
Each instance in announcers is dependent on a corresponding service ID such as twitterId, facebookId... I could build it lazily in the getter, but I'm curious if there's a way to set of a factory to inject it. I could also expose a setter, and set it in the UserFactory... but trying to limit exposure.
Take a look at this link:
http://www.tutorialspoint.com/spring/spring_injecting_collection.htm
See the section named "Injecting Bean References".
I am not aware of a method for doing it without xml config, what I do in these cases is to define the itens to be injected in the list in a xml file and then I inject the beans to the list.
Something like:
<bean id="an1" class="FBAnnouncer"/>
<bean id="an2" class="TWAnnouncer"/>
<bean id="user" class="User">
<property name="announcers">
<list>
<ref bean="an1"/>
<ref bean="an2"/>
</list>
</property>
</bean>
I have a singleton bean definition like this:
<bean id="exampleBean" class="com.examples.ExampleBean">
<property name="exampleBean2">
<bean class="com.examples.ExampleBean2" />
</property>
</bean>
where ExampleBean could be:
public class ExampleBean {
private ExampleBean2 exampleBean2;
public ExampleBean() { }
public ExampleBean2 getExampleBean2() { return exampleBean2; }
public void setExampleBean2(ExampleBean2 exampleBean2) { this.exampleBean2 = exampleBean2; }
}
The problem is that, in certain conditions, the com.examples.ExampleBean2 class might not exist at runtime witch will cause an error when the IoC tries to instantiate exampleBean.
What I need is to ignore this error from IoC and allow the exampleBean to be created but leaving the exampleBean2 property null.
So the question is: is this possible in any way?
Thanks for all your help.
If you use autowire, what you wish to achieve is possible.
<bean class="com.examples.ExampleBean" autowire="byType" />
<bean class="com.examples.ExampleBean2" />
Or via annotations
#Autowired(required=false)
ExampleBean2 exampleBean2;
Is it an option to declare an init-method on your ExampleBean, and in this init-method check if the class ExampleBean2 exists, and if so setting it?
<bean id="exampleBean" class="com.examples.ExampleBean" init-method="init"/>
Maybe a better way of doing things here would be to use some form of the NullPattern, where you always provide an implementation of ExampleBean2, even if it only is its 'null' value.
If I got it right ExampleBean2 isn't loaded when Spring tries to instantiate the beans. Is this correct? In that case I don't thing you could do much with Spring's built in capabilities.
Perhaps you could create a container class that will always be present. This class will check if ExampleBean2 is loaded and if yes, it will instantiate an instance of it. The container class will have an Object property that could either be null or the instance of the ExampleBean2.
maybe lazy-init will do it, but i think spring will at least check if the bean implementation class is available at creation of the application context
Perhaps this will work:
public class NullFactoryBean implements FactoryBean {
#Override
public Object getObject() throws Exception {
return null;
}
#Override
public Class<?> getObjectType() {
return Object.class;
}
#Override
public boolean isSingleton() {
return false;
}
}
And then...
public class ClassNotFoundPostProcessor implements BeanFactoryPostProcessor {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanDefinitionName);
String beanClassName = beanDefinition.getBeanClassName();
try {
Class.forName(beanClassName);
} catch (ClassNotFoundException e) {
beanDefinition.setBeanClassName(NullFactoryBean.class.getName());
}
}
}
}
And then...
<beans>
<bean id="exampleBean" class="com.examples.ExampleBean">
<property name="exampleBean2">
<bean class="com.examples.ExampleBean2" />
</property>
</bean>
<bean class="ClassNotFoundPostProcessor" />
</beans>
EDIT: Sorry about that, it appears that this did not catch the inner beans. I missed this detail when I tested it. It only catches top-level beans. By the way, com.examples.ExampleBean probably won't load anyway because it itself depends directly upon the ExampleBean2 class, which the virtual machine won't find, causing an Error
I have a bunch of Spring beans which are picked up from the classpath via annotations, e.g.
#Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
// Implementation omitted
}
In the Spring XML file, there's a PropertyPlaceholderConfigurer defined:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
I want to inject one of the properties from app.properites into the bean shown above. I can't simply do something like
<bean class="com.example.PersonDaoImpl">
<property name="maxResults" value="${results.max}"/>
</bean>
Because PersonDaoImpl does not feature in the Spring XML file (it is picked up from the classpath via annotations). I've got as far as the following:
#Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
#Resource(name = "propertyConfigurer")
protected void setProperties(PropertyPlaceholderConfigurer ppc) {
// Now how do I access results.max?
}
}
But it's not clear to me how I access the property I'm interested in from ppc?
You can do this in Spring 3 using EL support. Example:
#Value("#{systemProperties.databaseName}")
public void setDatabaseName(String dbName) { ... }
#Value("#{strategyBean.databaseKeyGenerator}")
public void setKeyGenerator(KeyGenerator kg) { ... }
systemProperties is an implicit object and strategyBean is a bean name.
One more example, which works when you want to grab a property from a Properties object. It also shows that you can apply #Value to fields:
#Value("#{myProperties['github.oauth.clientId']}")
private String githubOauthClientId;
Here is a blog post I wrote about this for a little more info.
Personally I love this new way in Spring 3.0 from the docs:
private #Value("${propertyName}") String propertyField;
No getters or setters!
With the properties being loaded via the config:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:propertyFile.properties" name="propertiesBean"/>
To further my glee I can even control click on the EL expression in IntelliJ and it brings me to the property definition!
There's also the totally non xml version:
#PropertySource("classpath:propertyFile.properties")
public class AppConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
There is a new annotation #Value in Spring 3.0.0M3. #Value support not only #{...} expressions but ${...} placeholders as well
<context:property-placeholder ... /> is the XML equivalent to the PropertyPlaceholderConfigurer.
Example:
applicationContext.xml
<context:property-placeholder location="classpath:test.properties"/>
Component class
private #Value("${propertyName}") String propertyField;
Another alternative is to add the appProperties bean shown below:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
<bean id="appProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true"/>
<property name="properties">
<props>
<prop key="results.max">${results.max}</prop>
</props>
</property>
</bean>
When retrieved, this bean can be cast to a java.util.Properties which will contain a property named results.max whose value is read from app.properties. Again, this bean can be dependency injected (as an instance of java.util.Properties) into any class via the #Resource annotation.
Personally, I prefer this solution (to the other I proposed), as you can limit exactly which properties are exposed by appProperties, and don't need to read app.properties twice.
As mentioned #Value does the job and it is quite flexible as you can have spring EL in it.
Here are some examples, which could be helpful:
//Build and array from comma separated parameters
//Like currency.codes.list=10,11,12,13
#Value("#{'${currency.codes.list}'.split(',')}")
private List<String> currencyTypes;
Another to get a set from a list
//If you have a list of some objects like (List<BranchVO>)
//and the BranchVO has areaCode,cityCode,...
//You can easily make a set or areaCodes as below
#Value("#{BranchList.![areaCode]}")
private Set<String> areas;
You can also set values for primitive types.
#Value("${amount.limit}")
private int amountLimit;
You can call static methods:
#Value("#{T(foo.bar).isSecurityEnabled()}")
private boolean securityEnabled;
You can have logic
#Value("#{T(foo.bar).isSecurityEnabled() ? '${security.logo.path}' : '${default.logo.path}'}")
private String logoPath;
I need to have two properties files, one for production and an override for development (that will not be deployed).
To have both, a Properties Bean that can be autowired and a PropertyConfigurer, you can write:
<bean id="appProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="singleton" value="true" />
<property name="ignoreResourceNotFound" value="true" />
<property name="locations">
<list>
<value>classpath:live.properties</value>
<value>classpath:development.properties</value>
</list>
</property>
</bean>
and reference the Properties Bean in the PropertyConfigurer
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="appProperties" />
</bean>
You also can annotate you class:
#PropertySource("classpath:/com/myProject/config/properties/database.properties")
And have a variable like this:
#Autowired
private Environment env;
Now you can access to all your properties in this way:
env.getProperty("database.connection.driver")
Before we get Spring 3 - which allows you to inject property constants directly into your beans using annotations - I wrote a sub-class of the PropertyPlaceholderConfigurer bean that does the same thing. So, you can mark up your property setters and Spring will autowire your properties into your beans like so:
#Property(key="property.key", defaultValue="default")
public void setProperty(String property) {
this.property = property;
}
The Annotation is as follows:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.FIELD})
public #interface Property {
String key();
String defaultValue() default "";
}
The PropertyAnnotationAndPlaceholderConfigurer is as follows:
public class PropertyAnnotationAndPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
private static Logger log = Logger.getLogger(PropertyAnnotationAndPlaceholderConfigurer.class);
#Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties properties) throws BeansException {
super.processProperties(beanFactory, properties);
for (String name : beanFactory.getBeanDefinitionNames()) {
MutablePropertyValues mpv = beanFactory.getBeanDefinition(name).getPropertyValues();
Class clazz = beanFactory.getType(name);
if(log.isDebugEnabled()) log.debug("Configuring properties for bean="+name+"["+clazz+"]");
if(clazz != null) {
for (PropertyDescriptor property : BeanUtils.getPropertyDescriptors(clazz)) {
Method setter = property.getWriteMethod();
Method getter = property.getReadMethod();
Property annotation = null;
if(setter != null && setter.isAnnotationPresent(Property.class)) {
annotation = setter.getAnnotation(Property.class);
} else if(setter != null && getter != null && getter.isAnnotationPresent(Property.class)) {
annotation = getter.getAnnotation(Property.class);
}
if(annotation != null) {
String value = resolvePlaceholder(annotation.key(), properties, SYSTEM_PROPERTIES_MODE_FALLBACK);
if(StringUtils.isEmpty(value)) {
value = annotation.defaultValue();
}
if(StringUtils.isEmpty(value)) {
throw new BeanConfigurationException("No such property=["+annotation.key()+"] found in properties.");
}
if(log.isDebugEnabled()) log.debug("setting property=["+clazz.getName()+"."+property.getName()+"] value=["+annotation.key()+"="+value+"]");
mpv.addPropertyValue(property.getName(), value);
}
}
for(Field field : clazz.getDeclaredFields()) {
if(log.isDebugEnabled()) log.debug("examining field=["+clazz.getName()+"."+field.getName()+"]");
if(field.isAnnotationPresent(Property.class)) {
Property annotation = field.getAnnotation(Property.class);
PropertyDescriptor property = BeanUtils.getPropertyDescriptor(clazz, field.getName());
if(property.getWriteMethod() == null) {
throw new BeanConfigurationException("setter for property=["+clazz.getName()+"."+field.getName()+"] not available.");
}
Object value = resolvePlaceholder(annotation.key(), properties, SYSTEM_PROPERTIES_MODE_FALLBACK);
if(value == null) {
value = annotation.defaultValue();
}
if(value == null) {
throw new BeanConfigurationException("No such property=["+annotation.key()+"] found in properties.");
}
if(log.isDebugEnabled()) log.debug("setting property=["+clazz.getName()+"."+field.getName()+"] value=["+annotation.key()+"="+value+"]");
mpv.addPropertyValue(property.getName(), value);
}
}
}
}
}
}
Feel free to modify to taste
Spring way:
private #Value("${propertyName}")
String propertyField;
is a new way to inject the value using Spring's "PropertyPlaceholderConfigurer" class.
Another way is to call
java.util.Properties props = System.getProperties().getProperty("propertyName");
Note: For #Value, you can not use static propertyField, it should be non-static only, otherwise it returns null. To fix it a non static setter is created for the static field and #Value is applied above that setter.
A possible solutions is to declare a second bean which reads from the same properties file:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/app.properties" />
</bean>
<util:properties id="appProperties" location="classpath:/WEB-INF/app.properties"/>
The bean named 'appProperties' is of type java.util.Properties and can be dependency injected using the #Resource attruibute shown above.
If you are stuck using Spring 2.5 you could define a bean for each of your properties and inject them using qualifiers. Like this:
<bean id="someFile" class="java.io.File">
<constructor-arg value="${someFile}"/>
</bean>
and
#Service
public class Thing
public Thing(#Qualifier("someFile") File someFile) {
...
Its not super readable but it gets the job done.
Autowiring Property Values into Spring Beans:
Most people know that you can use #Autowired to tell Spring to inject one object into another when it loads your application context. A lesser known nugget of information is that you can also use the #Value annotation to inject values from a property file into a bean’s attributes.
see this post for more info...
new stuff in Spring 3.0
|| autowiring bean values
||autowiring property values in spring
For me, it was #Lucky's answer, and specifically, the line
AutowiredFakaSource fakeDataSource = ctx.getBean(AutowiredFakaSource.class);
from the Captain Debug page
that fixed my problem. I have an ApplicationContext-based app running from the command-line, and judging by a number of the comments on SO, Spring wires up these differently to MVC-based apps.
I think it's most convenient way to inject properties into bean is setter method.
Example:
package org.some.beans;
public class MyBean {
Long id;
String name;
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Bean xml definition:
<bean id="Bean1" class="org.some.beans.MyBean">
<property name="id" value="1"/>
<property name="name" value="MyBean"/>
</bean>
For every named property method setProperty(value) will be invoked.
This way is especially helpful if you need more than one bean based on one implementation.
For example, if we define one more bean in xml:
<bean id="Bean2" class="org.some.beans.MyBean">
<property name="id" value="2"/>
<property name="name" value="EnotherBean"/>
</bean>
Then code like this:
MyBean b1 = appContext.getBean("Bean1");
System.out.println("Bean id = " + b1.getId() + " name = " + b1.getName());
MyBean b2 = appContext.getBean("Bean2");
System.out.println("Bean id = " + b2.getId() + " name = " + b2.getName());
Will print
Bean id = 1 name = MyBean
Bean id = 2 name = AnotherBean
So, in your case it should look like this:
#Repository("personDao")
public class PersonDaoImpl extends AbstractDaoImpl implements PersonDao {
Long maxResults;
public void setMaxResults(Long maxResults) {
this.maxResults = maxResults;
}
// Now use maxResults value in your code, it will be injected on Bean creation
public void someMethod(Long results) {
if (results < maxResults) {
...
}
}
}
If you need more Flexibility for the configurations, try the Settings4jPlaceholderConfigurer:
http://settings4j.sourceforge.net/currentrelease/configSpringPlaceholder.html
In our application we use:
Preferences to configure the PreProd- and Prod-System
Preferences and JNDI Environment variables (JNDI overwrites the preferences) for "mvn jetty:run"
System Properties for UnitTests (#BeforeClass annotation)
The default order which key-value-Source is checked first, is described in:
http://settings4j.sourceforge.net/currentrelease/configDefault.html
It can be customized with a settings4j.xml (accurate to log4j.xml) in your classpath.
Let me know your opinion: settings4j-user#lists.sourceforge.net
with friendly regards,
Harald
Easiest way in Spring 5 is to use #ConfigurationProperties here is example
https://mkyong.com/spring-boot/spring-boot-configurationproperties-example/
Use Spring's "PropertyPlaceholderConfigurer" class
A simple example showing property file read dynamically as bean's property
<bean id="placeholderConfig"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/WEB-INF/classes/config_properties/dev/database.properties</value>
</list>
</property>
</bean>
<bean id="devDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${dev.app.jdbc.driver}"/>
<property name="jdbcUrl" value="${dev.app.jdbc.url}"/>
<property name="user" value="${dev.app.jdbc.username}"/>
<property name="password" value="${dev.app.jdbc.password}"/>
<property name="acquireIncrement" value="3"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="10"/>
<property name="maxStatementsPerConnection" value="11000"/>
<property name="numHelperThreads" value="8"/>
<property name="idleConnectionTestPeriod" value="300"/>
<property name="preferredTestQuery" value="SELECT 0"/>
</bean>
Property File
dev.app.jdbc.driver=com.mysql.jdbc.Driver
dev.app.jdbc.url=jdbc:mysql://localhost:3306/addvertisement
dev.app.jdbc.username=root
dev.app.jdbc.password=root