I have some JDO objects that I want to spring to configure with info from a property file.
But since spring isn't used to create (i.e these objects are not listed as beans in the xml. Should they, how would it look?) these objects how can I get it to configure those objects?
Only solution I can come up with is to have the property file info configured into the dao and then have the dao insert that data into the object before it returns it. Or I guess I can do some AOP magic, but that seems heavy handed and I don't think it will work in Google App Engine where this service will be deployed.
Any other advice.
You can put any bean in applicationContext.xml, and configure all of its properties there.
The properties file can be loaded via:
<context:property-placeholder location="classpath:application.properties" />
and then, on your bean definition:
<property name="propertyName" value="${valueFromPropertiesFile}" />
Then, in order to have the properly configured bean, you will have to inject it - either in the applicationContext.xml, or via #Resource / #Autowired
But if you can't let spring create, and configure your beans, then simply populate them with your properties manually - load a properties file with java.util.Properties, and fill the data needed.
I have some JDO objects that I want to spring to configure with info from a property file.
I don't get the whole idea. Are these objects persistent or not? If they are, just load them from the datastore. If not, they aren't really JDO objects as pointed out in comments. And in that case, I don't understand the point of the DAO and of the property file. Why don't you just declare them as Spring beans?
Related
I am trying to figure out how can I dynamically update/reload externalized configuration in a Spring Boot application without restarting the whole application.
Most of the advice involves reloading ApplicationContext after changing the externalized configuration, but that is equivalent to restarting the entire application, so this is not really all that useful.
Reading through SpringBoot reference documentation, I found a chapter 23.7 Typesafe Configuration Properties.
If I understand it correctly, this allows to define simple POJO classes that will hold your application (externalized) configuration values as attributes.
In theory at least, this scheme could be used to bind beans only once to the required configuration POJO and upon configuration change just update the values in the POJO. Components could easily pick up the changes next time they access getters on the POJO...
However, I have yet not managed to figure out how to enable this type of behavior. Is there some glaringly obvious way to dynamically update components annotated with #ConfigurationProperties when relevant configuration has changed?
It sounds like you're looking for #RefreshScope which is provided by Spring Cloud. From the Spring Cloud documentation:
A Spring #Bean that is marked as #RefreshScope will get special treatment when there is a configuration change. This addresses the problem of stateful beans that only get their configuration injected when they are initialized. For instance if a DataSource has open connections when the database URL is changed via the Environment, we probably want the holders of those connections to be able to complete what they are doing. Then the next time someone borrows a connection from the pool he gets one with the new URL.
I wonder if there is a way to extract properties from Spring Environment (e.g. obtained from ApplicationContext) in the form of Properties instance? Or, at least, is there a way to enumerate the properties in Spring Environment, or get them all as a map, or any other way I can turn a [initially unknown] set of properties into a Properties object?
I need this in order to create a jclouds Context by calling org.jclouds.ContextBuilder.newBuilder() and .overrides(Properties). The idea is to configure the actual cloud provider solely by means of .properties file, and I don't want to couple application logic with provider-specific properties.
[UPDATE]
The .properties files to be used are configured using <context:property-placeholder>, and it actually specifies a list of paths, like this:
< context:property-placeholder location=
"classpath:/jdbc.properties,
file:${jboss.server.config.dir}/jdbc.properties,
file:${catalina.home}/conf/jdbc.properties"
ignore-resource-not-found="true"/>
which suggests that the .properties file is searched in the mentioned list of locations in order. I would like to achieve the following:
keep the list of .properties files and their possible locations in this XML definition file only;
allow to place jclouds related properties in any of the .properties files mentioned in the XML;
access the properties, resolved and loaded by Spring, in the form of Properties object so I am able to feed that to jclouds ContextBuilder.
Please let me know if all of this is feasible. Thank you in advance!
-Vlad
If you wan't to use properties in your Spring configuration then you can simply use:
<context:property-placeholder location="classpath:foo.properties" />
To get the properties in your code later you can simply read this file from the classpath into a Properties object:
props.load(MyClass.class.getClassLoader().getResourceAsStream("foo.properties"));
Alternatively you can have a look at PropertyPlaceholderConfigurer.
UPDATE
Updated after Deinum's remark but only if you are getting the properties from a Spring managed bean:
<util:properties id="myProps"
location="classpath:foo.properties"/>
<context:property-placeholder properties-ref="myProps" />
Now you can inject myProps into Spring managed beans (no need to load them again from the classpath).
You could use PropertiesFactoryBean and do something like this:
<bean id="jcloudsProps"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location">
<value>your/props/file.properties</value>
</property>
</bean>
You can then use jcloudsProps as you would any other Spring bean.
I am programming service for getting data from database and providing them via REST service. It uses spring mvc. My database connection cofiguration is in property file from where it is loaded by spring as a data source bean during context initialization.
Now my problem is - I want to change configuration in properties file (for example change database info) but I can't afford to restart the application server so the new configuration does not load.
How can I re-initialize spring context or some particular beans so the newly defined properties are used?
If you want multiple data source in spring and need to deciding appropriate data source dynamically at runtime you can do this with AbstractRoutingDataSource provided with spring. You have to implement your lookup key logic for determining data-source in method determineCurrentLookupKey(). With this you can map different beans to different data-sources at runtime. following are few questions relating to this context.
How to programatically change databases in Spring with one DataSource?
Also
dynamically change Spring data source
Is there a way to update a Spring bean dynamically if the spring beans configuration changes?
E.g. assume that I have a spring bean with boolean property x and the spring beans has the value true when the application starts.
So spring creates the bean with the property x set to true.
Is there a way so that if I changes the property to x (while the application is running) that the property will be updated e.g. to false?
Calling the setter for x setX() method will do that.
But it should not be a prototype bean.
it is possible with the jrebel-spring integration. it monitors your configuration and TRIES to re-wire your beans at runtime.
Though i would not use it in production...only for playing around, testing etc
Spring reads configuration files at startup. If you really need to update configs while application running, you should manually implement all the chain: detecting config changes, validating config, detecting changed beans, updating beans in context.
Spring beans can be initialized using applicationContext.xml or even programatically. In your case; you will need to remove configurations from xml and add into java program. You can get some idea from How to programmatically create bean definition with injected properties? . Other good links were also available on google.
I am new to Spring and the bean concept, so sorry if asking the obviously.
I have set up a Java project and used the Hibernate framework to make my connections to the DB (using hibernate tool on eclipse, really recommended btw).
My basic setup was as follows:
some hibernate pojos (generated by Hibernate tools),
hibernate mapping files (hbm.xml files).
The configuration was set in hibernate.cfg.xml file placed at my root of the packages.
I initially setup a HibernateUtils class that gets a session from my sessionFactory.
some classes that act as Dao - creates the queries using the pojos and the hibernateUtils to get the session.
This was working fine with hibernate's powerful framework. Then I migrated to project to Spring MVC. From the various tutorials I read I understood that some changes need to be done in order to make things play nicely again. The main change is that the Spring FW now loads the beans by itself, therefore the following:
the pojos did not change, nor did the hbm.xml files
The configuration is no longer set at hibernate.cfg.xml - the Spring MVC FW loads it's own LocalSessionFactoryBean once I declared it in the XML files (Spring search for xmls as part of the initialization process). So I created a separate xml file called spring-hibernate.xml, that has the DB definition, the session factory bean and a hibernate template. To complete it, the xml file also declare the location of the Dao and the hbm files.
with hibernate template configured in the xml, there is a bean injection, therefore I changed the Dao files to add getter/setter to a hibernate template property. Then using this - the Dao class may create the db query.
All of this configuration works fine and I can get the Spring FW initialize the Dao classes (I put a sysout just to confirm that the Dao classes are injected with the hibernate template during MVC startup). Now my problem is - how to get access to the Dao bean instance created?
In my logic part, I get a hold of the bean as follows:
ClassPathXmlApplicationContext appContex = new ClassPathXmlApplicationContext(new String[] {"spring-hibernate.xml"});
UserUIDDao userUIDDao= (UserUIDDao)appContext.getBean("UserUIDDao");
Problem is - this is a NEW reference to a newly created bean and not the same one created during the spring MVC startup.
So my questions are: how to get a hold of the original bean created by the Spring init process? and - is my setup correct?
the pojos did not change, nor did the hbm.xml files
That's correct.
The configuration is no longer set at hibernate.cfg.xml - the Spring MVC FW loads it's own LocalSessionFactoryBean once I declared it in the XML files (Spring search for xmls as part of the initialization process).
You can choose to use Spring to configure Hibernate (but you could keep your hibernate.cfg.xml).
So I created a separate xml file called spring-hibernate.xml, that has the DB definition, the session factory bean and a hibernate template. To complete it, the xml file also declare the location of the Dao and the hbm files. with hibernate template configured in the xml, there is a bean injection, therefore I changed the Dao files to add getter/setter to a hibernate template property. Then using this - the Dao class may create the db query.
Using Spring's HibernateTemplate is one option, but you could also go template-less and just inject Hibernate's SessionFactory and use sessionFactory.getCurrentSession().
This is actually the officially recommended approach for new projects, check out So should you still use Spring's HibernateTemplate and/or JpaTemplate?? and the javadoc of HibernateTemplate.
Now my problem is - how to get access to the Dao bean instance created?
You inject it where needed (typically, in your services).
In my logic part, I get a hold of the bean as follows (...)
No, don't do this. This "service locator approach" actually defeats the point of a DI container like Spring. Configure Spring to inject your DAOs where needed.