Spring per-environment configuration where PropertyPlaceholder is not enough - java

I am configuring my spring application per-environemnt and I came to following problem:
As long as the environment changes just bean constructor/properties values I am fine with using PropertyPlaceholderConfigurer.
Now I am facing the fact that the bean structure itself change in different environemnts. E.g. in test environemnt I define single bean where in production environment I define another bean of same interface which requires property of type List set - in another words different structure where PropertyPlaceholderConfigurer can't really help.
I went with defining per-environment spring xml configuration importing it via <import resource="myDefinition-${Environment}.xml />. This is also fine until I want have it optional. The resource I am defining there is #Autowired(required = false) to another bean.
Since <import ... /> doesn't allow optional attribute (as can be seen here: https://jira.springsource.org/browse/SPR-1624) I ended up having empty .xml configuration files for environemnts where I don't require having that bean. This is somewhat inconvenient.
Could anyone advice on best practice in such scenario?
Thanks.

Bean definition profiles, introduced in Spring 3.1 are designed to solve just this kind of problem. See http://static.springsource.org/spring/docs/3.1.0.RC2/spring-framework-reference/html/new-in-3.1.html

Related

How to dynamically add externally defined beans definitions to Spring context?

I have a requirement where Spring bean definitions need to be loaded dynamically from an "external" source. This external source could be some type of file, database, or web service.
I've read up on BeanFactoryPostProcessor and BeanDefinitionRegistryPostProcessor classes that can do this type of thing, but I'm running into one big challenge:
The object that retrieves the bean definiton info from the external source is configured as a bean itself (e.g. DatabaseBeanDefinitionProvider) so it would need to be configured with all dependencies (e.g. DataSource) and available from the context to fetch the data.
I'm not sure where/when in the Spring application context lifecycle to do this: essentially use "existing beans to add new beans" to the context.
Any ideas experts?
The possibility to use a database table for loading persisted bean definitions is already implemented in Spring with the JdbcBeanDefinitionReader. I mentioned this just to be sure you do not reinvent the wheel ;). You can also use the PropertiesBeanDefinitionReader if you want to rely just on a bunch of properties from a plain file.
Both classes have the BeanDefinitionRegistry as dependency, the bucket, where all bean definitions will be collected during the bean definition load phase. Implementing the BeanDefinitionRegistryPostProcessor (BDRPP) interface provides this in a very convenient way.
Now, how to get it running:
Basically, if you stick to the DataSource-bound way, I would recommend to setup those dependencies by hand, means instantiating the BDRPP and dependencies in an own ApplicationContextInitializer implementation. In there you can then call applicationContext.addBeanFactoryPostProcessor(yourBdrpp) and load whatever properties you need for the DataSource under the JdbcBeanDefinitionReader.
XML will also work fine if all your dependencies are independent of any autowiring or properties replacement. You need to define them explicitly, e.g.
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
<bean class="net.bensteinert.MyBeanDefinitionRegistryPostProcessor">
<constructor-arg ref="jdbcTemplate"/>
</bean>
Only problem is, that your dataSource will have no access to any property placeholder infrastructure, That is the reason why I would tend to the programmatic solution.
Means in general, no worries about using beans for creating beans. They just need to be independent. By the way, the powerful Java Config bootstrapping is also a BeanDefinitionRegistryPostProcessor.
More details on dynamic bean definition can also be found here: How to create dynamic bean definitions in Spring
A very good introduction into the Spring Bean Lifecycle can be found here: SpringONE 2013 Presentation by Mark Secrist
Hope that helps,
so long.

Analysing spring bean definitions

Our application exports its configuration as several sets of Spring beans.
I have no control over how it does this.
I want to write something that documents the dependencies between the configuration items defined in these beans. Note: these are dependencies at the application level, nothing to so with Spring dependencies (so we might have configuration items of type Actresses who have a dependency on certain items from the type Bishops, but - at the Spring bean level - this is merely that the value of a property in the Actress matches the value of a different property of the Bishop).
So I'd like to use some library or toolset that lets me load up a set of bean definition XML, iterate over them and the content of each, extract property values and so on.
From some googling, I can find ways of extending the parsing Spring does itself, but I don't want that - I want something I can run offline outside of the Spring-using app itself.
Can someone point me at some resources for doing this?
The closest thing I've heard of to this is Spring BeanDocs:
http://spring-beandoc.sourceforge.net/

Spring Tool Suite - Search for bean declaration by id OR alias

I'm using Spring Tool Suite (STS) to manage a large Java Spring project. Is there a function in STS that allows one to find the declaration of a particular bean by its alias?
For example, if I have the following property in a Java class:
#Resource
private WidgetService widgetService;
I know that this property will be auto-wired from a Spring bean with the name "widgetService". The bean injected will be an instance of a class that implements the interface WidgetService. The implementation(s) may not be located in the same package as the interface. I need a way to quickly determine from that property declaration which implementation will be injected.
I tried searching for widgetService using the Spring Beans Search, but it came up empty. It came up empty because the bean is defined as follows:
<alias alias="widgetService" name="defaultWidgetService" />
<bean id="defaultWidgetService" class="namespace.DefaultWidgetService"/>
There's the answer to my search (DefaultWidgetService), but it's inside a bean named "defaultWidgetService". Since the bean that is used to autowire the #Resource is aliased, the Spring Beans Search doesn't work, as it only has options to search by name, class, etc, but not by alias.
I know I can just use a File Search and search for alias="widgetService" but because of the size of the project searching by text is quite slow. I could also examine the property at debug time and get the class of the injected bean, but that is also cumbersome. Java Search is quick because it is indexed, and Spring Beans Search is quick for the same reason. But I wonder: why I am using STS (which adds extra time to my builds so STS can index the Spring beans) if it won't help me with finding aliased beans?

CDI : #alternative vs #Qualifiers

being new to CDI, i want to know the practical difference between an alternative and a
Qualifier.
in Weld reference, it's stated that:
4.3. Qualifier annotations
If we have more than one bean that implements a particular bean type,
the injection point can specify exactly which bean should be injected
using a qualifier annotation.
but while explaining the Alternatives, it is said:
4.7. Alternatives
Alternatives are beans whose implementation is specific to a
particular client module or deployment scenario.
If I understood right, #Qualifier defines which implementations of the target bean get injected to the Injection Points.
on the other hand #Alternative describes a wish during deployment dependending on the client about whether or not an Alternatice to the standard (the "#default" I mean ) bean get Injected to the injection's point.
It is right ?
Yes, that's right. You can imagine qualifiers as the basic weaving that you setup at development time, using annotations in your source code.
Alternatives allow you to overwrite this at execution time using the beans.xml file - a simple deployment artifact.
A typical scenario would be to use different beans.xml for different environments and thereby enable mock-alternatives for components that you don't want to execute on your local / integration environments.

Does having many unused beans in a Spring Bean Context waste significant resources?

My model layer is being used by a handful of different projects and I'd like to use a single XML Spring Configuration file for the model regardless of which project is using it.
My question is: Since not all beans are used in all projects am I wasting resources to any significant amount if there not being instantiated? I'm not too sure how lazy Spring is about loading them since it's never been an issue until now.
Any ideas?
Taken from the Spring Reference Manual:
The default behavior for ApplicationContext implementations is to eagerly pre-instantiate all singleton beans at startup. Pre-instantiation means that an ApplicationContext will eagerly create and configure all of its singleton beans as part of its initialization process. Generally this is a good thing, because it means that any errors in the configuration or in the surrounding environment will be discovered immediately (as opposed to possibly hours or even days down the line).
However, there are times when this behavior is not what is wanted. If you do not want a singleton bean to be pre-instantiated when using an ApplicationContext, you can selectively control this by marking a bean definition as lazy-initialized. A lazily-initialized bean indicates to the IoC container whether or not a bean instance should be created at startup or when it is first requested.
When configuring beans via XML, this lazy loading is controlled by the 'lazy-init' attribute on the [bean element] ; for example:
<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/>
But, unless your beans are using up resources like file locks or database connections, I wouldn't worry too much about simple memory overhead if it is easier for you to have this one configuration for multiple (but different) profiles.
In addition to the other comments: it's also possible to specify a whole configuration file to be lazily initialized, by using the 'default-lazy-init' attribute on the <beans/> element; for example:
<beans default-lazy-init="true">
<!-- no beans will be pre-instantiated... -->
</beans>
This is much easier than adding the lazy-init attribute to every bean, if you have a lot of them.
By default Spring beans are singletons and are instantiated when the application context is created (at startup). So assuming you haven't overridden the default behaviour, then a single instance of every bean will be created.
Depends upon the objects.
But, unused code is 'cruft' and will increase the cost of maintenance.
Better to delete the refs and classes. You can always restore from version control if they are needed later.

Categories

Resources