Spring: force reload of a bean - java

I've been struggling with this for a while and it's driving me crazy.
Basically I've a bean defined as follows:
<bean id="tipoUfficioGiudiziarioListImpl" singleton="false"
class="java.util.ArrayList" >
</bean>
and it's basically a collectio of all the entries in a table. now the problem is that this bean is loaded when at server start up (or at first use if I set lazy-init="true") but if I add an entry on the db (both via the application itself or sql) the bean does not reload and I don't see the new entries when the collection is used.
is there any way to force this to reload or invalidate it so it'll be loaded at the next first use?
I'm using Spring 1.2

Maybe, you want to instantiate a new bean instance every time you use it, you can do this using prototype scope? <bean id = tipoUfficioGiudiziarioListImpl" class="java.util.ArrayList" scope = "prototype">?

you can do like this:
#Aspect
#Component
public class DaoAspect {
#Autowired
TipoUfficioGiudiziarioListImpl impl;
//your dao path,intercept your dao operation.
#Before("execution(* com.test.dao..*.*(..))")
public void doBeforeInServiceLayer(JoinPoint joinPoint) {
/*
TODO some condition
*/
impl.loaddata();
}
}

Related

Spring Reload Property - Bean not updated

I have a webservice that fetches property from application.properties file located in server like query[testSql] through spring
public class RuntimeEnvironmentPropertiesConfigurerextends PropertyPlaceholderConfigurer
implements InitializingBean, RuntimeEnvironmentInterface
Now that query is injected in my Spring bean dao.
<bean id="dao" name="dao" class="com.dao.DaoImpl">
<property name="ackJdbcTemplate" ref="ackJdbcTemplate" />
<property name="testSql" value="${dao.query.tSql}" />
</bean>
With help from How can I reload properties file in Spring 4 using annotations? link I am able to reload the property at run time.
verified by
#Autowired
public RuntimeEnvironmentInterface propertyLoader;
....
Set s=propertyLoader.getProperties();
Iterator itr=s.iterator();
while(itr.hasNext()){
String tempKey=String.valueOf(itr.next());
logger.info(tempKey +"==="+propertyLoader.getProperty(tempKey));
but problem is my dao bean does not take updated testSql query.It runs on old one untill I restart the application.
I found a way like in separate url mapping i wrote a method which does below job:
Dao.setTestSql(propertyLoader.getProperty("com.dao.query.tSql"));
and the person who is updating she have to hit the url after updating the property.
But this I have to do for all the bean and and injected property.That is pretty hectic job.I miss one property and I am doomed.
Is there any other way to automatically update the injected bean?I need that my updated properties are reflected without restart .
I tried to understand wuenschenswert code given but was unable to.
<property name="testSql" value="${dao.query.tSql}" />
This means that on bean initialization Spring computes the property value using a property called dao.query.tSql. So setTestSql() method will be called when the context is initialized, and that's all. When your properties are reloaded, property loader will not push new property value into your bean.
But, as Alexey suggests, you can pull the property value from your propertyLoader every time you execute that sql query like this:
final String actualQuery = propertyLoader.getProperty("com.dao.query.tSql");
executeQuery(actualQuery);
There is a problem: this may start look ugly when the number of properties grows. But this can be alleviated, if you create some class encapsulating these accesses; that class will provide properties via its methods. Example:
public class DynamicProperties {
private final RuntimeEnvironmentInterface propertyLoader;
public DynamicProperties(RuntimeEnvironmentInterface propertyLoader) {
this.propertyLoader = propertyLoader;
}
public String tSql() {
return propertyLoader.getProperty("dao.query.tSql");
}
... other methods for other properties
}
Then create an instance of this class in your Dao:
private DynamicProperties dynamicProperties = new DynamicProperties(propertyLoader);
And then
executeQuery(dynamicProperties.tSql());
A little bonus: you can make type conversions in that same DynamicProperties class (for example, when your property is int and not String).

Spring not injecting bean if it is instantiated on definition

I have a session scoped bean defined like so:
<!-- this is where the serviceImpl bean is defined -->
<import resource="classpath:META-INF/*-core-context.xml"/>
<bean id="myBean" class="com.company.Bean">
<property name="service" ref="serviceImpl"/>
</bean>
Now inside the bean I have defined a default value for the injected service like so:
public class Bean {
private Service service = new NullService();
public void setService(Service service) {
this.service = service;
}
}
What I want to do is to provide the ability to optionally inject the service and if you choose not to the Bean will use the NullService implementation which simply does nothing, not affecting the bean logic in any way.
The problem is that for some reason the serviceImpl is never injected and I always end up with the NullService implementation.
So is there some spring setting or feature which prevents it from injecting it ? Or do you have any other ideas on why this might happen ?
More info
This is the setter that spring uses to inject the service:
public void setPermissionsService(PermissionService permissionsService) {
this.permissionsService = permissionsService;
System.out.println("setting permissions service to: " + permissionsService.getClass().getName());
if (this.permissionsService instanceof NoopPermissionsServiceImpl) {
System.out.println("NULL IMPLEMENTATION");
}
else if (this.permissionsService instanceof PermissionServiceImpl) {
System.out.println("CORRECT IMPLEMENTATION");
}
else {
System.out.println("WHAT ?!?!");
}
}
It prints "WHAT ?!?!".
So it turns out spring sets it to a dynamic proxy $Proxy859. Is there a way to see the class the proxy is proxying ?
You seem to be lacking a definition for your serviceImpl bean in your configuration. Something like
<bean id="serviceImpl" class="com.company.ServiceImpl" />
The only solution I see to your problem is to reverse-engineer this a bit. Do something like that in the same spring.xml:
<bean id="myBean" class="com.company.Bean">
<property name="service" ref="testServiceImpl"/>
</bean>
<bean id="testServiceImpl" class="com.company.TestServiceImpl" />
Then implement the TestServiceImpl with simple debug messages indicating that construction and your service call is actually working. This has to work. If it does you have a problem with your original service definition. If not you have a problem in your Bean.
Try to narrow the problem to a simpler. And then work into the simpler problem.
Good luck!
Instead of using instanceof use Class.isAssignableFrom(Class)

injecting mock beans into spring context for testing

I know similar questions have been asked, e.g. here, but having done a search, I've come upon a solution I'm much happier with here
My only problem however, is that I'm not sure how to implement this solution.
What I want to be able to do is via the HotswappableTargetSource override the bean definitions of select beans in my application context with my test versions and then run the test.
Then for each test case I'd like to specify which beans I want to be hot swappable and then each test must be able to create its own mock versions and swap those in, and be able to swap back again.
I am able to get the Application Context the test is running with but what I don't know is how to configure a bean to be hot swappable. I know how to do it when configuring beans with xml but I don't want to go back to using xml to configure beans.
UPDATE: There's a library that does it!
https://bitbucket.org/kubek2k/springockito/wiki/springockito-annotations
The solution is as follows:
You will need to change the spring context of your application to proxy the bean you want to swap:
<bean id="beanSwappable" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource" ref="beanSwap" />
</bean>
<bean id="beanSwap" class="org.springframework.aop.target.HotSwappableTargetSource">
<constructor-arg ref="beanToSwap" />
</bean>
beanSwap is the proxy onto this beanSwap.
beanSwappable is the bean which you reference when you want to swap the bean
beanToSwap is the default implementation of the bean
Thus a change to the system under test is necessary.
And in your test the code will look like:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "test.xml", "spring.xml" })
public class Test {
#Resource(name="beanSwappable")
Bean b;
#Resource(name = "beanSwap")
HotSwappableTargetSource beanSwap;
public void swap() {
Bean b = << create mock version >>
beanSwap.swap(b);
// run test code which
}
}

Can I replace a Spring bean definition at runtime?

Consider the following scenario. I have a Spring application context with a bean whose properties should be configurable, think DataSource or MailSender. The mutable application configuration is managed by a separate bean, let's call it configuration.
An administrator can now change the configuration values, like email address or database URL, and I would like to re-initialize the configured bean at runtime.
Assume that I can't just simply modify the property of the configurable bean above (e.g. created by FactoryBean or constructor injection) but have to recreate the bean itself.
Any thoughts on how to achieve this? I'd be glad to receive advice on how to organize the whole configuration thing as well. Nothing is fixed. :-)
EDIT
To clarify things a bit: I am not asking how to update the configuration or how to inject static configuration values. I'll try an example:
<beans>
<util:map id="configuration">
<!-- initial configuration -->
</util:map>
<bean id="constructorInjectedBean" class="Foo">
<constructor-arg value="#{configuration['foobar']}" />
</bean>
<bean id="configurationService" class="ConfigurationService">
<property name="configuration" ref="configuration" />
</bean>
</beans>
So there's a bean constructorInjectedBean that uses constructor injection. Imagine the construction of the bean is very expensive so using a prototype scope or a factory proxy is not an option, think DataSource.
What I want to do is that every time the configuration is being updated (via configurationService the bean constructorInjectedBean is being recreated and re-injected into the application context and dependent beans.
We can safely assume that constructorInjectedBean is using an interface so proxy magic is indeed an option.
I hope to have made the question a little bit clearer.
Here is how I have done it in the past: running services which depend on configuration which can be changed on the fly implement a lifecycle interface: IRefreshable:
public interface IRefreshable {
// Refresh the service having it apply its new values.
public void refresh(String filter);
// The service must decide if it wants a cache refresh based on the refresh message filter.
public boolean requiresRefresh(String filter);
}
Controllers (or services) which can modify a piece of configuration broadcast to a JMS topic that the configuration has changed (supplying the name of the configuration object). A message driven bean then invokes the IRefreshable interface contract on all beans which implement IRefreshable.
The nice thing with spring is that you can automatically detect any service in your application context that needs to be refreshed, removing the need to explicitly configure them:
public class MyCacheSynchService implements InitializingBean, ApplicationContextAware {
public void afterPropertiesSet() throws Exception {
Map<String, ?> refreshableServices = m_appCtx.getBeansOfType(IRefreshable.class);
for (Map.Entry<String, ?> entry : refreshableServices.entrySet() ) {
Object beanRef = entry.getValue();
if (beanRef instanceof IRefreshable) {
m_refreshableServices.add((IRefreshable)beanRef);
}
}
}
}
This approach works particularly well in a clustered application where one of many app servers might change the configuration, which all then need to be aware of. If you want to use JMX as the mechanism for triggering the changes, your JMX bean can then broadcast to the JMS topic when any of its attributes are changed.
I can think of a 'holder bean' approach (essentially a decorator), where the holder bean delegates to holdee, and it's the holder bean which is injected as a dependency into other beans. Nobody else has a reference to holdee but the holder. Now, when the holder bean's config is changed, it recreates the holdee with this new config and starts delegating to it.
You should have a look at JMX. Spring also provides support for this.
Spring 2.0.x
Spring 2.5.x
Spring 3.0.x
Further updated answer to cover scripted bean
Another approach supported by spring 2.5.x+ is that of the scripted bean. You can use a variety of languages for your script - BeanShell is probably the most intuitive given that it has the same syntax as Java, but it does require some external dependencies. However, the examples are in Groovy.
Section 24.3.1.2 of the Spring Documentation covers how to configure this, but here are some salient excerpts illustrating the approach which I've edited to make them more applicable to your situation:
<beans>
<!-- This bean is now 'refreshable' due to the presence of the 'refresh-check-delay' attribute -->
<lang:groovy id="messenger"
refresh-check-delay="5000" <!-- switches refreshing on with 5 seconds between checks -->
script-source="classpath:Messenger.groovy">
<lang:property name="message" value="defaultMessage" />
</lang:groovy>
<bean id="service" class="org.example.DefaultService">
<property name="messenger" ref="messenger" />
</bean>
</beans>
With the Groovy script looking like this:
package org.example
class GroovyMessenger implements Messenger {
private String message = "anotherProperty";
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message
}
}
As the system administrator wants to make changes then they (or you) can edit the contents of the script appropriately. The script is not part of the deployed application and can reference a known file location (or one that is configured through a standard PropertyPlaceholderConfigurer during startup).
Although the example uses a Groovy class, you could have the class execute code that reads a simple properties file. In that manner, you never edit the script directly, just touch it to change the timestamp. That action then triggers the reload, which in turn triggers the refresh of properties from the (updated) properties file, which finally updates the values within the Spring context and off you go.
The documentation does point out that this technique doesn't work for constructor-injection, but maybe you can work around that.
Updated answer to cover dynamic property changes
Quoting from this article, which provides full source code, one approach is:
* a factory bean that detects file system changes
* an observer pattern for Properties, so that file system changes can be propagated
* a property placeholder configurer that remembers where which placeholders were used, and updates singleton beans’ properties
* a timer that triggers the regular check for changed files
The observer pattern is implemented by
the interfaces and classes
ReloadableProperties,
ReloadablePropertiesListener,
PropertiesReloadedEvent, and
ReloadablePropertiesBase. None of them
are especially exciting, just normal
listener handling. The class
DelegatingProperties serves to
transparently exchange the current
properties when properties are
updated. We only update the whole
property map at once, so that the
application can avoid inconsistent
intermediate states (more on this
later).
Now the
ReloadablePropertiesFactoryBean can be
written to create a
ReloadableProperties instance (instead
of a Properties instance, as the
PropertiesFactoryBean does). When
prompted to do so, the RPFB checks
file modification times, and if
necessary, updates its
ReloadableProperties. This triggers
the observer pattern machinery.
In our case, the only listener is the
ReloadingPropertyPlaceholderConfigurer.
It behaves just like a standard spring
PropertyPlaceholderConfigurer, except
that it tracks all usages of
placeholders. Now when properties are
reloaded, all usages of each modified
property are found, and the properties
of those singleton beans are assigned
again.
Original answer below covering static property changes:
Sounds like you just want to inject external properties into your Spring context. The PropertyPlaceholderConfigurer is designed for this purpose:
<!-- Property configuration (if required) -->
<bean id="serverProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- Identical properties in later files overwrite earlier ones in this list -->
<value>file:/some/admin/location/application.properties</value>
</list>
</property>
</bean>
you then reference the external properties with Ant syntax placeholders (that can be nested if you want from Spring 2.5.5 onwards)
<bean id="example" class="org.example.DataSource">
<property name="password" value="${password}"/>
</bean>
You then ensure that the application.properties file is only accessible to the admin user and the user running the application.
Example application.properties:
password=Aardvark
Or you could use the approach from this similar question and hence also my solution:
The approach is to have beans that are configured via property files and the solution is to either
refresh the entire applicationContext (automatically using a scheduled task or manually using JMX) when properties have changed or
use a dedicated property provider object to access all properties. This property provider will keep checking the properties files for modification. For beans where prototype-based property lookup is impossible, register a custom event that your property provider will fire when it finds an updated property file. Your beans with complicated lifecycles will need to listen for that event and refresh themselves.
You can create a custom scope called "reconfigurable" into the ApplicationContext. It creates and caches instances of all beans in this scope. On a configuration change it clears the cache and re-creates the beans on first access with the new configuration. For this to work you need to wrap all instances of reconfigurable beans into an AOP scoped proxy, and access the configuration values with Spring-EL: put a map called config into the ApplicationContext and access the configuration like #{ config['key'] }.
This is not something I tried, I am trying to provide pointers.
Assuming your application context is a subclass of AbstractRefreshableApplicationContext(example XmlWebApplicationContext, ClassPathXmlApplicationContext). AbstractRefreshableApplicationContext.getBeanFactory() will give you instance of ConfigurableListableBeanFactory. Check if it is instance of BeanDefinitionRegistry. If so you can call 'registerBeanDefinition' method. This approach will be tightly coupled with Spring implementation,
Check the code of AbstractRefreshableApplicationContext and DefaultListableBeanFactory(this is the implementation you get when you call 'AbstractRefreshableApplicationContext getBeanFactory()')
Option 1 :
Inject the configurable bean into the DataSource or MailSender. Always get the configurable values from the configuration bean from within these beans.
Inside the configurable bean run a thread to read the externally configurable properties (file etc..) periodically. This way the configurable bean will refresh itself after the admin had changed the properties and so the DataSource will get the updated values automatically.
You need not actually implement the "thread" - read : http://commons.apache.org/configuration/userguide/howto_filebased.html#Automatic_Reloading
Option 2 (bad, i think, but maybe not - depends on use case) :
Always create new beans for beans of type DataSource / MailSender - using prototype scope. In the init of the bean, read the properties afresh.
Option 3 :
I think, #mR_fr0g suggestion on using JMX might not be a bad idea. What you could do is :
expose your configuration bean as a MBean (read http://static.springsource.org/spring/docs/2.5.x/reference/jmx.html)
Ask your admin to change the configuration properties on the MBean (or provide an interface in the bean to trigger property updates from their source)
This MBean (a new piece of java code that you will need to write), MUST keep references of Beans (the ones that you want to change / inject the changed properties into). This should be simple (via setter injection or runtime fetch of bean names / classes)
When the property on the MBean is changed (or triggered), it must call the appropriate setters on the respective beans. That way, your legacy code does not change, you can still manage runtime property changes.
HTH!
You may want to have a look at the Spring Inspector a plug-gable component that provides programmatic access to any Spring based application at run-time. You can use Javascript to change configurations or manage the application behaviour at run-time.
Here is the nice idea of writing your own PlaceholderConfigurer that tracks the usage of properties and changes them whenever a configuration change occurs. This has two disadvantages, though:
It does not work with constructor injection of property values.
You can get race conditions if the reconfigured bean receives a
changed configuration while it is processing some stuff.
My solution was to copy the original object. Fist i created an interface
/**
* Allows updating data to some object.
* Its an alternative to {#link Cloneable} when you cannot
* replace the original pointer. Ex.: Beans
* #param <T> Type of Object
*/
public interface Updateable<T>
{
/**
* Import data from another object
* #param originalObject Object with the original data
*/
public void copyObject(T originalObject);
}
For easing the implementation of the function fist create a constructor with all fields, so the IDE could help me a bit. Then you can make a copy constructor that uses the same function Updateable#copyObject(T originalObject). You can also profit of the code of the constructor created by the IDE to create the function to implement:
public class SettingsDTO implements Cloneable, Updateable<SettingsDTO>
{
private static final Logger LOG = LoggerFactory.getLogger(SettingsDTO.class);
#Size(min = 3, max = 30)
private String id;
#Size(min = 3, max = 30)
#NotNull
private String name;
#Size(min = 3, max = 100)
#NotNull
private String description;
#Max(100)
#Min(5)
#NotNull
private Integer pageSize;
#NotNull
private String dateFormat;
public SettingsDTO()
{
}
public SettingsDTO(String id, String name, String description, Integer pageSize, String dateFormat)
{
this.id = id;
this.name = name;
this.description = description;
this.pageSize = pageSize;
this.dateFormat = dateFormat;
}
public SettingsDTO(SettingsDTO original)
{
copyObject(original);
}
#Override
public void copyObject(SettingsDTO originalObject)
{
this.id = originalObject.id;
this.name = originalObject.name;
this.description = originalObject.description;
this.pageSize = originalObject.pageSize;
this.dateFormat = originalObject.dateFormat;
}
}
I used it in a Controller for updating the current settings for the app:
if (bindingResult.hasErrors())
{
model.addAttribute("settingsData", newSettingsData);
model.addAttribute(Templates.MSG_ERROR, "The entered data has errors");
}
else
{
synchronized (settingsData)
{
currentSettingData.copyObject(newSettingsData);
redirectAttributes.addFlashAttribute(Templates.MSG_SUCCESS, "The system configuration has been updated successfully");
return String.format("redirect:/%s", getDao().getPath());
}
}
So the currentSettingsData which has the configuration of the application gonna have the updated values, located in newSettingsData. These method allows updating any bean without high complexity.

Short way of making many beans depend-on one bean

When using database migrations, I obviously want none of the DAOs to be usable before the migrations are run.
At the moment I'm declaring a lot of DAOs, all having a depends-on=databaseMigrator property. I find this troubling, especially since it's error prone.
Is there a more compact way of doing this?
Notes:
the depends-on attribute is not 'inherited' from parent beans;
I am not using Hibernate or JPA so I can't make the sessionFactory bean depend-on the migrator.
You could try writing a class that implements the BeanFactoryPostProcessor interface to automatically register the dependencies for you:
Warning: This class has not been compiled.
public class DatabaseMigratorDependencyResolver implements BeanFactoryPostProcessor {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
// Your job is here:
// Feel free to make use of the methods available from the BeanDefinition class (http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/beans/factory/config/BeanDefinition.html)
boolean isDependentOnDatabaseMigrator = ...;
if (isDependentOnDatabaseMigrator) {
beanFactory.registerDependentBean("databaseMigrator", beanName);
}
}
}
}
You could then include a bean of this class alongside all your other beans.
<bean class="DatabaseMigratorDependencyResolver"/>
Spring will automatically run it before it starts initiating the rest of the beans.
I do this on application start-up. The schema version that the application requires is compiled into the application as part of the build process. It is also stored in the database and updated by the database migration scripts.
On application start-up, the app checks that the schema version in the database is what it expects and if not, aborts immediately with a clear error message.
In a normal Java program, this happens right at the start of the main method.
In a webapp, it's performed by the app's ServletContextListener and is the first thing it does when the servlet context is created.
That's saved my (apps') bacon several times.
I ended up creating a simple ForwardingDataSource class which appears in the context files as:
<bean id="dataSource" class="xxx.ForwardingDataSource" depends-on="databaseMigrator">
<property name="delegate">
<!-- real data source here -->
</property>
</bean>
If find it less elegant than Adam Paynter's solution, but clearer.

Categories

Resources