I have used #Activeprofiles along with importing the spring profile containing .xml to context configuration but it does not seem to load the profile to the respective Junit class. below is the snippet of what I have done. The assert compare value is not been changed as per the profile that is set. Any tips to improve on to get the spring profile activated.
TEST CLASS.
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles("unittest-hsql")
#ContextConfiguration(locations = {
"classpath:spring/Services.xml"
"classpath:spring/profiles/dev.xml"
})
public class TestSpringProfile
{
#Test
public void testGetCronExpression()
{
String expression = EventLimitation.getExpression();
assertThat(expression, is("20"));
}
}
Try to specify in the beans tag of your profile-specific configuration, the profile attribute:
<!--language:xml-->
<?xml version="1.0" encoding="UTF-8"?>
<beans profile="dev">
...
</beans>
That should work as long as you have in the file spring/profiles/dev.xml something like the below where you specify a profile named "unittest-hsql":
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<beans profile="unittest-hsql">
<bean id="applicationPropertiesPlaceholder"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:profiles/hsqldb.profile.properties</value>
</list>
</property>
</bean>
</beans>
</beans>
Related
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="com.wqh">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/>
</context:component-scan>
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:custom.properties</value>
</list>
</property>
</bean>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean class="com.wqh.demo.TestBean" name="${custom.beanName}" />
</beans>
When I use configuration like this, Spring will create BeanDefinition with beanName ${custom.beanName}, and will not resolve the placeholder inside it.
But I want to use the beanName which declared in custom.properties file, is there any way to achieve this requirement?
The following configuration would result in NoSuchBeanDefinitionException when attempting to get the bean from context.
<bean class="com.wqh.demo.TestBean" name="${custom.beanName}" />
However , the XML Template Proposals for attribute name shows the following
Attribute : name Can be used to create one or more aliases illegal in
an (XML) id. Multiple aliases can be separated by any number of
spaces, commas, or semi-colons (or indeed any mixture of the three).
Data Type : string
Based on this , the following work around is possible
Considering the properties file entry is :
custom.beanName=propBeanName
Provide the bean configuration with multiple alias names as follows
<bean class="com.wqh.demo.TestBean" name="testBeanName ${custom.beanName}" />
Now when you getBean() based on the name from the application context , it would retrieve the bean successfully
Sample code
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("app-context.xml");
System.out.println(Arrays.asList(ctx.getAliases("testBeanName")));
TestBean bean = (TestBean)ctx.getBean("propBeanName");
System.out.println(bean);
}
would display the following in the console
[propBeanName]
com.wqh.demo.TestBean#4c60d6e9
I'm trying to find a way to only create a bean if the value of another bean/property is true, using Spring 3.2 and XML configurations.
<bean id="isEnabled" class="java.lang.Boolean">
<bean factory-bean="configurationService" factory-method="getBooleanValue">
<constructor-arg index="0">
<util:constant static-field="org.code.ConfigurationKeys.ENABLED"/>
</constructor-arg>
</bean>
</bean>
<if isEnabled=true>
..... create some beans
</if>
I've seen some slightly similar examples using Spring EL but nothing that does this exactly...
You can use profiles.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd" >
<!-- here goes common beans -->
<beans profile="Prof_1">
<import resource="./first-config.xml" />
</beans>
<beans profile="Prof_2">
<import resource="./second-config.xml" />
</beans>
</beans>
One can activate multiple profile at same time or choose not to activate any. To activate there are multiple ways but to programtaically do this we need to add a initializer in web.xml
<context-param>
<param-name>contextInitializerClasses</param-name>
<param-value>com.test.MyCustomInitializer</param-value>
</context-param>
MyCustomInitializer looks like following
public class MyCustomInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext applicationContext) {
try {
String activeProf;
// some logic to either read file/env variable/setting to determine which profile to activate
applicationContext.getEnvironment().setActiveProfiles( activeProf );
} catch (IOException e) {
e.printStackTrace();
}
}
}
Why you don't use the factory to create the objects when are required and make them lazy.
<bean id="second "class="xxx.xxx.Class" lazy-init="true" scope="prototype"/>
There is no way to introduce if statement within the spring configuration, profiles could work but at more related to environment not a programmatic configuration.
I am creating sample spring program to understand, local attribute of ref tag.
I have created two bean files
first one [applicationcontext.xml]
<bean class="org.vik.spring.SequenceGenerator" name="sequenceProperty_Other">
<property name="prefix">
<ref local="prefixGeneratorOther" />
</property>
<property name="suffix" value="23"></property>
</bean>
Second xml file [prefix_context.xml]
<bean class="org.vik.spring.DatePrefixGenerator" id="prefixGeneratorOther" p:prefix="other"/>
I have created app context like below
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("applicationcontext.xml" ,"prefix_context.xml");
When I request for bean "sequenceProperty_Other", spring successfully returns it
SequenceGenerator sequenceConstrutornerator = applicationContext.getBean( "sequenceProperty_Other",SequenceGenerator.class);
What I could understand from this, is that as "prefixGeneratorOther" bean in not in same xml file (applicationcontext.xml) and I am using local attribute to refer it, Spring should through exception. But in my case its working. Am I missing some thing.
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- <bean class="org.vik.spring.SequenceGenerator" name="sequence"> </bean> -->
<bean class="org.vik.spring.DatePrefixGenerator" id="prefixGenerator"
p:prefix="122333">
</bean>
<bean class="org.vik.spring.SequenceGenerator" name="sequenceProperty_Locale">
<property name="prefix">
<ref local="prefixGenerator" />
</property>
<property name="suffix" value="23"></property>
</bean>
<bean class="org.vik.spring.SequenceGenerator" name="sequenceProperty_Other">
<property name="prefix">
<ref local="prefixGeneratorOther" />
</property>
<property name="suffix" value="23"></property>
</bean>
prefix_context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="org.vik.spring.DatePrefixGenerator" id="prefixGeneratorOther" p:prefix="other"/>
</beans>
Java class
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("applicationcontext.xml",
"prefix_context.xml");
System.out.println(applicationContext.getBean("prefixGenerator", PrefixGenerator.class).getPrefix());
SequenceGenerator sequenceProperty = applicationContext.getBean("sequenceProperty_Locale",
SequenceGenerator.class);
System.out.println(sequenceProperty);
SequenceGenerator sequenceConstrutornerator = applicationContext.getBean("sequenceProperty_Other",
SequenceGenerator.class);
System.out.println(sequenceConstrutornerator);
This particular behavior works with any version after Spring 3.1.0 (included) in the 3.x branch. If you test this with the latest 3.0.x (which is 3.0.7) you'll get an exception. If you test with Spring 4, you'll get an exception, but a different one.
If you take a look carefully at the exception in Spring 3.0.7, this refers to XML parsing:
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:347)
at org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument(DefaultDocumentLoader.java:75)
which means the restriction is at xml schema level (and I believe it's at Java code level, as well).
This behavior has changed in Spring 3.1.0 (and after) because of this JIRA issue. From all those JIRA issue it is linked to, this one seems to explain what happened: the restriction has been eliminated from 3.1 schema and the ref local entered in a kind of "deprecated" state (because in 3.1.x and 3.2.x one can use it) and in Spring 4 ref local has been entirely eliminated. In Spring 4 the documentation says ref local is not supported anymore and, also, the xsd schema has been updated (in the sense that ref doesn't accept local anymore).
I have an XML file that contains the configration of a Spring project and I want to dynamically add a new bean. I have to modify the initial xML file and add my new bean definition:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="config"
class="myclass">
<property name="configXml">
<value>config.xml</value>
</property>
</bean>
<-- here a want to add a new bean definition <bean>....</bean> -->
</beans>
Has anyone got an idea?
I'm still not 100% what you mean, but here's two cases to try.
If you want to specify properties of a bean based on some derived value you can use the Spring Expression Language
http://static.springsource.org/spring/docs/3.0.x/reference/expressions.html
<bean id="someBean" class="example.SomeBean">
<property name="foo" value="#{config.whatever}"/>
</bean>
If you want to something more complex you can construct a bean programatically using a factory bean
<bean id="someBean" class="example.SomeBeanFactory">
<property name="config" ref="config"/>
</bean>
with something like
class SomeBeanFactory implements FactoryBean<SomeBean> {
public void setConfig(MyClass config) { ... }
public SomeBean getObject() {
...
}
}
I'm using Spring's #Configuration, and I noticed that a #Bean does not get registered using JMX.
The bean is wired as
#Bean
protected CountingHttpInterceptor countingHttpInterceptor() {
return new CountingHttpInterceptor();
}
and the class definition is
#ManagedResource
public class CountingHttpInterceptor implements HttpRequestInterceptor, HttpResponseInterceptor { /* code here*/ }
This #Configuration file is processed after the main , XML-based, application context is built, and does not have the chance to take part in the discovery process which is activated using XML bean definitions ( org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource and frieds ).
How can I JMX-enable the beans from the #Configuration file?
Update: the xml configuration
<bean id="jmxExporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="assembler" ref="assembler"/>
<property name="namingStrategy" ref="namingStrategy"/>
<property name="autodetect" value="true"/>
</bean>
<bean id="jmxAttributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
<bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
<bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
Despite the temptations of the #Configuration- based approach, some things remain better done with XML config. In particular, the namespace-based config such as <context:mbean-export>. These essentially represent "macros" consisting of complex arrangements of interacting objects.
Now, you could replicate this logic in your #Configuration class, but it's really more trouble than it's worth. Instead, I suggest putting such system-level stuff into XML, and importing it from your #Configuration class:
#ImportResource("/path/to/beans.xml")
public class MyConfig {
#Bean
protected CountingHttpInterceptor countingHttpInterceptor() {
return new CountingHttpInterceptor();
}
}
and then in /path/to/beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
<context:mbean-export/>
</beans>
Everything you have is correct. In your #Configuration class you need to add one more annotation to export your MBeans, #EnableMBeanExport.
Your configuration class would look something like this...
#Configuration
#EnableMBeanExport
public class SpringConfiguration {
#Bean
protected CountingHttpInterceptor countingHttpInterceptor() {
return new CountingHttpInterceptor();
}
}