Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Populating a spring bean using a constructor-arg field

Tags:

How can i inject a properties file containing a Map to be used as additional constructor arg using the field.

With a Map being loaded from a properties file

the bean is currently setup using:

<bean id="graphDbService" class="org.neo4j.kernel.EmbeddedGraphDatabase"
     init-method="enableRemoteShell" destroy-method="shutdown">

     <constructor-arg index="0" value= "data/neo4j-db"/>
         <constructor-arg index="1" value=?  />
</bean>

Java Equivalent:

Map<String,String> configuration =  EmbeddedGraphDatabase.loadConfigurations( "neo4j_config.props" );
GraphDatabaseService graphDb = new EmbeddedGraphDatabase( "data/neo4j-db", configuration );

Thanks

like image 461
patrick-fitzgerald Avatar asked Aug 12 '10 09:08

patrick-fitzgerald


People also ask

What is constructor-ARG in Spring?

The constructor-arg element within the bean element is used to set the property value thru constructor injection. Since there is only one constructor in the User bean class, this code will work fine. When there is more than one constructor with the same number of arguments, then the following ambiguities will occur.

Can Spring bean have constructor?

No, you are not required to use default (no arg) constructors. If you want to reference another bean in your application context, you can do it using the ref attribute of the constructor-arg element rather than the val attribute.

How do you Autowire a constructor in Spring?

Spring container looks at the beans on which autowire attribute is set constructor in the XML configuration file. It then tries to match and wire its constructor's argument with exactly one of the beans name in the configuration file. If matches are found, it will inject those beans.


2 Answers

Something like this:

<bean id="configuration" class="org.neo4j.kernel.EmbeddedGraphDatabase" 
      factory-method="loadConfigurations">
   <constructor-arg value="neo4j_config.props"/>
</bean>

<bean id="graphDbService" class="org.neo4j.kernel.EmbeddedGraphDatabase"
     init-method="enableRemoteShell" destroy-method="shutdown">

     <constructor-arg index="0" value="data/neo4j-db"/>
     <constructor-arg index="1" ref="configuration"  />
</bean>

This takes advantage of the ability to create beans using arbitrary static factory methods, in this case using loadConfigurations() as a factory method to create the configuration bean, which is then injected into the proper constructor of EmbeddedGraphDatabase.

like image 123
skaffman Avatar answered Oct 07 '22 18:10

skaffman


Create a bean that loads the properties (and takes the file name as an argument) and inject that instead.

EDIT When using annotations, things like constructor injection become more simple:

@Bean
public Map<String,String> configuration() {
    return EmbeddedGraphDatabase.loadConfigurations( "neo4j_config.props" );
}

@Bean
public GraphDatabaseService graphDb() {
    return new EmbeddedGraphDatabase( "data/neo4j-db", configuration() );
}

Note that the second bean definition method "simply" calls the first. When this code is executed, Spring will do some magic so you can still override the bean elsewhere (i.e. beans still overwrite each other) and it will make sure that the method body will be executed only once (no matter how often and from where it was called).

If the config is in a different @Configuration class, then you can @Autowired it:

@Autowired
private Map<String,String> configuration;

@Bean
public GraphDatabaseService graphDb() {
    return new EmbeddedGraphDatabase( "data/neo4j-db", configuration );
}
like image 45
Aaron Digulla Avatar answered Oct 07 '22 18:10

Aaron Digulla