I'm running tests using spring (SpringJUnit4ClassRunner and #ContextConfiguration). The tests are run in parallel.
Some of my beans are singleton, and I would like to change them to be in scope "thread" of the tests. I want each test to have its own instance of the bean.
I've managed to it by having an applicationContext.xml file and a applicationTestContext.xml file which is used for tests.
In the applicationTestContext.xml I define those beans with scope "thread".
The problem with this is that everytime we add a new bean of that type, we'll have to add it to both applicationContext.xml and applicationTestContext.xml which is pretty annoying.
Is there a way to do it with less boilerplate?
Gather up all the beans whose scope you want to customize and put them in a separate bean config file, included from both applicationContext and applicationTestContext, e.g.
<import resource="customScopedBeans.xml"/>
Then use a placeholder for the scope
<bean class="com.Foo" scope="${threadOrSingleton}" />
and declare the property differently in the parent config file.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties">
<value>threadOrSingleton=thread</value>
</property>
</bean>
Related
I have two beans in my application context and a property ${applicationType}
BeanTypeA
<bean id="beanTypeA" class="com.ext.library.A">
<constructor-arg><value>boot</value></constructor-arg>
</bean>
BeanTypeB
<bean id="beanTypeB" class="com.ext.library.B">
<constructor-arg><value>boot</value></constructor-arg>
</bean>
How do I control which beans to be created based on the SPEL in xml configurations using the property ${applicationType}
I am already using spring profiles for a different purpose in the application. So in this case, I won't be able to overload multiple spring profiles. Trying to achieve the conditional creation of bean using SPEL.
Thanks for the inputs.
I have a Spring-Boot application that just have a simple rest controller. On this controller, I added the jmx annotations #ManagedResource and #ManagedOperation and it is working fine. It is correctly exposed in Jmx.
This application depends on a "global-commons" library to share many basic functionality to all of our modules.
But if I add the same annotations to a class in this library, it is ignored!
And before you ask, yes the library is imported with the latest change.
There is no error or warning message in the logs.
I am configuring all my beans using an xml file. Both classes are beans defined in the same file.
One is a #RestController. The other one is a simple utility class.
Any idea?
Make sure the classes from the global-commons library as managed by Spring. As long as none of the classes in the library are managed by Spring, the annotions don't have any effect.
I found the problems:
The bean that was not working was defined as an "inner" bean:
<bean id="imMetrics" class="com.imetrik.global.common.metrics.ImGlobalMetrics" init-method="init">
...
<property name="reporterList">
<util:list>
<bean id="jmxReporter" class="com.imetrik.global.common.metrics.reporters.ImJmxReporter">
<property name="registryId" value="metricRegistry1"/>
<property name="durationUnit" value="SECONDS"/>
<property name="rateUnit" value="SECONDS"/>
<property name="domain" value="com.imetrik.global.metric"/>
</bean>
</util:list>
</property>
</bean>
The annotated beans is "jmxReporter".
But if I put it outside as a normal "first level" bean and use a reference instead, it is working.
But it is annoying! Is there a way to make it work even as a inner beans?
I've got a Spring bean:
<bean id="sharedBean" class="com.bean.SharedBean">
<constructor-arg name="app-name" value="#{ config['app.name'] }"/>
</bean>
This bean is defined in a jar and used in two apps that both get deployed to the same tomcat server. I've only got one properties file the apps share and I'd like to keep it that way if possible. You might see the problem - I need two values for app.name (one for each web app).
I need to set the app.name independently in each app. I don't mind hard coding the value in the Java (but don't think I can inject the value in that direction). I know I can introduce another properties file at a different path and override but I'm hoping there is a better way I can accomplish this through Spring that will allow me to maintain only one shared properties file.
Possible solutions, in recommended order:
1 - is there a reason why the shared bean is declared in a separate jar file? Certainly, the bean class can be located there, but why not declare the actual bean inside the individual web apps where it's being used?
2 - if you absolutely need to keep the bean definition in the shared jar you can use bean inheritance; (a) change your bean class to use a property rather than a constructor arg:
<bean id="sharedBean" class="com.bean.SharedBean">
<property name="app-name" value="default"/>
</bean>
(b) in your web app context file:
<bean id="instanceBean" parent="sharedBean">
<property name="app-name" value="app1"/>
</bean>
3 - use a Spring profile; in your shared jar context.xml:
<beans profile="app1">
<bean id="sharedBean" class="com.bean.SharedBean">
<constructor-arg name="app-name" value="app1"/>
</bean>
</beans>
<beans profile="app2">
<bean id="sharedBean" class="com.bean.SharedBean">
<constructor-arg name="app-name" value="app2"/>
</bean>
</beans>
note: <beans profile=... MUST be the last entries in your context file.
Add a context param to each web.xml (changing value as appropriate):
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>app1</param-value>
</context-param>
I have a set of unit tests. Some will use dataSource, others will want to use hsqlbDataSource. This datasource is not a wired bean into my unit tests/code, but is transitively used via templates and transaction managers. Therefore I intend to use bean defs like this:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/myDataSource"
cache="true" resource-ref="true" lookup-on-startup="false"
proxy-interface="javax.sql.DataSource" />
<jee:jndi-lookup id="hsqlbDataSource" jndi-name="jdbc/myDataSource"
cache="true" resource-ref="true" lookup-on-startup="false"
proxy-interface="javax.sql.DataSource" />
<bean id="qmat-das-jdbcTemplate"
class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"
c:dataSource-ref="${test.datasource:dataSource}" />
<bean id="transactionManager"
class="org.springframework.transaction.jta.WebSphereUowTransactionManager">
<property name="dataSource" ref="${test.datasource:dataSource}"/>
</bean>
I want for my unit tests (there are many of them, of course) to pick and choose which datasource to use. Ideally what makes sense to me is for each unit test to have an annotation which sets the system property to override the default datasouce with its own. Is there an elegant way to achieve that without property files, but just set the java property via an annotation?
With an annotation it's not possible with out-of-the-box functionality, but have a look at Spring 3 profiles as it allows to activate/deactivate groups of beans.
The beans can be activated with system properties or via code. This code could be put in a test superclass to activate the test-only beans:
springContext.getEnvironment().setActiveProfiles("test")
I am using spring 3.1 with spring profiles to load the beans. In my app context file, I load the properties like :
<context:property-placeholder order="1" location="classpath*:META-INF/spring/*_${spring.profiles.active}.properties" ignore-unresolvable="true"/>
And then I use the property value to load the data source bean like
<property name="driverClassName" value="${database.driverClassName}"/>
It works fine.
The problem starts when I add a couple of more property placeholders so that properties from some database tables can be loaded.
This uses a properties reference loaded by
<bean id="configFactoryBean"
class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
<constructor-arg ref="globalSystemConfiguration"/>
</bean>
To add to the details, this configFactoryBean uses the datasource to load the properties from the database.
When I do this, I have the following exception:
java.lang.ClassNotFoundException: ${database.driverClassName}
My analysis is that its trying to load the datasource before resolving the property from the first context property placeholder. I may be wrong. Or maybe spring profile variable is not resolved properly.
Can anyone please help me to fix this.
Thanks
Akki
This bug about multiple property placeholders might relate to your problem: https://jira.spring.io/browse/SPR-9989
When using multiple PropertyPlaceholderConfigurer in conjunction with
#Value annotation and default value for placeholders syntax (ie
${key:defaultValue}), only the first PropertyPlaceholderConfigurer is
used. If this configurer does not contain the desired value, it falls
back to #Value default even if the second
PropertyPlaceholderConfigurer contains the value.
Affects Version/s: 3.1.3
Each <context:property-placeholder> creates a new instance of PropertyPlaceholderConfigurer - it gets messy easily. You should have one such thing per application and on application level, not on libraries' one - that makes maintenance much easier.
For more details and a suggestion how to cope with it look here:
http://rostislav-matl.blogspot.cz/2013/06/resolving-properties-with-spring.html
In my application I am using property-placeholder configurer in following way and it works very well. You can try that.
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:META-INF/spring/*_${spring.profiles.active}.properties</value>
</list>
</property>
</bean>
I think this should resolve your problem. :)
Since you have suggested hardcoding the path to the configuration file works, try using the profiles attribute on the tag to selectively include the configuration.
<beans profile="profileName">
<context:property-placeholder order="1" location="classpath*:META-INF/spring/hardcoded.properties" ignore-unresolvable="true"/>
</beans>
<beans profile="profileName2">
<context:property-placeholder order="1" location="classpath*:META-INF/spring/hardcoded.properties" ignore-unresolvable="true"/>
</beans>
See this article explaining profiles: http://java.dzone.com/articles/using-spring-profiles-xml