I have the following beans in my contexs:
<!-- Context 1 -->
<beans profile="ldap">
<bean id="activeDirectoryAuthProvider" class="com.production.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="${ldap.login.provider.domain}"/>
<constructor-arg value="${ldap.login.provider.url}" />
<property name="useAuthenticationRequestCredentials" value="true" />
<property name="convertSubErrorCodesToExceptions" value="true" />
</bean>
</beans>
<!-- Context 2 -->
<bean id="activeDirectoryAuthProvider" class="com.test.TestActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="${ldap.login.provider.domain}"/>
<constructor-arg value="${ldap.login.provider.url}" />
<property name="useAuthenticationRequestCredentials" value="true" />
<property name="convertSubErrorCodesToExceptions" value="true" />
</bean>
My goal is to use the first bean only for production version another one for test purposes.
Namely when I start test based on production context I expect that production bean would be replaced by test bean with needed configuration.
But unfortunately when I tried to create two beans with same name only production bean is created and another one is ignored. Another thing that I noticed that when I tried to change test bean name to: activeDirectoryAuthProvider1 then both beans are successfully created. Can anyone explain why it happen and suggest possible solution how it can be bypassed?
You need to use different contexts for development and production. In each context you define only the relevant bean (i.e. only 1 bean with a certain name). If you use maven you can put the test/development context under src/test/resources and the production context under src/main/resources
If you do not use maven there are other approaches. You can find an example here: http://mrhaki.blogspot.it/2009/02/use-spring-configurator-to-support.html
Take a look at Spring Profiles you can have one for test and one for prod.
<beans profile="test">
<!-- Context 1 -->
<bean id="activeDirectoryAuthProvider" class="com.production.ActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="${ldap.login.provider.domain}"/>
<constructor-arg value="${ldap.login.provider.url}" />
<property name="useAuthenticationRequestCredentials" value="true" />
<property name="convertSubErrorCodesToExceptions" value="true" />
</bean>
</beans>
<beans profile="prod">
<!-- Context 2 -->
<bean id="activeDirectoryAuthProvider" class="com.test.TestActiveDirectoryLdapAuthenticationProvider">
<constructor-arg value="${ldap.login.provider.domain}"/>
<constructor-arg value="${ldap.login.provider.url}" />
<property name="useAuthenticationRequestCredentials" value="true" />
<property name="convertSubErrorCodesToExceptions" value="true" />
</bean>
</beans>
You can set the active profile in a various ways. Check the docs.
Related
I asked a similar question, but based on the responses, I did a bad job describing what I am after. I have a spring 4 webapp that loads properties from a properties file. We consume those properties both via the "${proper.name"} expressions in spring, as well as by injecting a properties object into some of our classes.
We want to move most of the properties to a database table and make them reloadable. However, a few need to stay in local properties, potentially overriding the database setting. These should also be loaded dynamically after the app is running.
I know that once a particular bean is injected, it won't get reloaded, that doesn't concern me, it's up to that module to handle that. But I am having trouble getting the behavior I want. In particular, I have implemented an AbstractConfiguration from apache commons configuration to get the dual source and overriding I am after. But while it works for injecting the properties object, expressions loaded with "${prop.name}" don't work at all.
How can I get them to work? Did I override the wrong thing? Is it just some config detail?
<bean id="sysProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="databaseConfigurator" />
<property name="targetMethod" value="getProperties"/>
</bean>
<bean id="databaseConfigurator" class="my.util.config.MyDatabaseConfigurator">
<property name="datasource" ref="dataSource" />
<property name="propertyFile" value="/WEB-INF/my.properties" />
<property name="applicationName" value="ThisApp" />
</bean>
<bean id="dbConfigFactory" class="org.apache.commons.configuration.ConfigurationConverter" factory-method="getProperties">
<constructor-arg ref="databaseConfigurator" />
</bean>
I haven't tested this, but I think it might work.
<bean id="sysProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="databaseConfigurator" />
<property name="targetMethod" value="getProperties"/>
</bean>
<bean id="databaseConfigurator" class="my.util.config.MyDatabaseConfigurator">
<property name="datasource" ref="dataSource" />
<property name="propertyFile" value="/WEB-INF/my.properties" />
<property name="applicationName" value="ThisApp" />
</bean>
<bean name="PropertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="CommonsConfigurationFactoryBean"/>
</bean>
<bean name="CommonsConfigurationFactoryBean" class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
<constructor-arg ref="databaseConfigurator"/>
</bean>
We are using Spring Cache Manager with spring-data-redis 1.5.2. These days we want to upgrade spring-data-redis to latest release i.e:1.6.2.RELEASE.
For some weird reason everything works good with 1.5.2 but when upgrading to 1.6.2 we get
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'cacheManager' defined in ServletContext
resource [/WEB-INF/spring-cache.xml]: Unsatisfied dependency
expressed through constructor argument with index 0 of type
[org.springframework.data.redis.core.RedisOperations]: Ambiguous
constructor argument types - did you specify the correct bean
references as constructor arguments?
This message seems like a mistake as redisTemplate is RedisTemplate which implements RedisOperations.
Any idea how to solve it?
P.S
note that when removing the cache configuration the 1.6.2 version seems to work good. So the issue is with the cache.
Configuration
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring-redis.xml
/WEB-INF/spring-cache.xml
</param-value>
</context-param>
spring-redis.xml
<context:annotation-config />
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration" />
<bean
class="org.springframework.security.web.session.HttpSessionEventPublisher" />
<!-- end of seesion managment configuration -->
<bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="${app.redis.port}" />
<property name="hostName" value="${app.redis.hostname}" />
<property name="password" value="${app.redis.password}" />
<property name="usePool" value="true" />
</bean>
<!-- for publishing string over redis channels -->
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="redisConnectionFactory" />
</bean>
<!-- for storing object into redis key,value -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="redisConnectionFactory" />
</bean>
spring-cache.xml
<!-- This file must load after spring-redis.xml -->
<cache:annotation-driven />
<!-- declare Redis Cache Manager -->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"
c:template-ref="redisTemplate" />
</beans>
It seems the reason for this bug is that RedisCacheManager has two constructors. Both of them has RedisOperations as parameter. Forsome reason Spring couldnot understand its related to the first constructor and not to the second one. a work around is mention constructor-arg index
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
<constructor-arg index="0" ref="redisTemplate"></constructor-arg>
</bean>
While upgrading from Spring Data Redis 1.5.2.RELEASE to 1.6.2.RELEASE, we need to use the below config for RedisCacheManager. Previous releases were using redis-template-ref instead of redis-operations-ref.
<beans:bean id='cacheManager'
class='org.springframework.data.redis.cache.RedisCacheManager'
c:redis-operations-ref='redisTemplate'>
</beans:bean>
This is an old question, but for those who reach this page.
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" factory-method="create" c:connection-factory-ref="jedisConnectionFactory" p:transaction-aware="true" />
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnectionFactory" />
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="${cache.redis.host}" p:port="${cache.redis.port}" p:use-pool="true">
<constructor-arg ref="jedisPoolConfig"></constructor-arg>
</bean>
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig" p:maxTotal="${cache.redis.pool.maxTotal}" p:maxIdle="${cache.redis.pool.maxIdle}" p:maxWaitMillis="${cache.redis.pool.maxWaitMillis}" p:testOnBorrow="true" />
I want to use simple-spring-memcached to cache data. so using this https://code.google.com/p/simple-spring-memcached/wiki/Getting_Started for my purpose.
i add in my dispatcher-servlet.xml
<aop:aspectj-autoproxy />
<import resource="simplesm-context.xml" />
<bean name="cacheManager" class="com.google.code.ssm.spring.SSMCacheManager">
<property name="caches">
<set>
<bean class="com.google.code.ssm.spring.SSMCache">
<constructor-arg name="cache" index="0" ref="defaultCache"/>
<!-- 5 minutes -->
<constructor-arg name="expiration" index="1" value="0"/>
<!-- #CacheEvict(..., "allEntries" = true) doesn't work -->
<constructor-arg name="allowClear" index="2" value="false"/>
</bean>
</set>
</property>
</bean>
<bean name="defaultCache" class="com.google.code.ssm.CacheFactory">
<property name="cacheName" value="defaultCache"/>
<property name="cacheClientFactory">
<bean name="cacheClientFactory" class="com.google.code.ssm.providers.xmemcached.MemcacheClientFactoryImpl"/>
</property>
<property name="addressProvider">
<bean class="com.google.code.ssm.config.DefaultAddressProvider">
<property name="address" value="127.0.0.1:11211"/>
</bean>
</property>
<property name="configuration">
<bean class="com.google.code.ssm.providers.CacheConfiguration">
<property name="consistentHashing" value="true"/>
</bean>
</property>
</bean>
i also add simple-spring-memcached-3.5.0.jar and spymemcache.jar,spymemcache-provider.jar to lib folder. but when i run my project occur this exception:
Cannot find class **[net.nelz.simplesm.config.MemcachedClientFactory]** for bean with name 'memcachedClientFactory' defined in ServletContext resource [/WEB-INF/simplesm-context.xml]; nested exception is java.lang.ClassNotFoundException: net.nelz.simplesm.config.MemcachedClientFactory
you must add lib for this class.
It seams that you have also an old version of Simple Spring Memcached on your classpath. The class net.nelz.simplesm.config.MemcachedClientFactory is no longer available in 3.x. Check your classpath and remove all Simple Spring Memcached artifacts older than 3.5.0.
I've got an app running on Tomcat 7, using Spring, Mybatis, and .. Mybatis-spring.
Here's the setup for the DB and transactions in servlet-context.xml:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyDS" />
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath*:maps/*.xml" />
<property name="transactionFactory">
<bean class="org.apache.ibatis.transaction.managed.ManagedTransactionFactory" />
</property>
</bean>
<mybatis:scan base-package="com.domain.dao.mappers" />
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
The error I'm getting when I run a method that uses the SqlSession is the following:
org.springframework.dao.TransientDataAccessResourceException: SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization
at org.mybatis.spring.SqlSessionUtils.getSqlSession(SqlSessionUtils.java:136)
What am I doing wrong?
My goal, really, is just to use transactions with this setup. I don't think I necessarilly need JTA. But if that's easy enough to setup on Tomcat, I'm willing to take a swing at it.
And I solved the problem myself. Really simple solution. In case anyone runs into the same issue, all I needed to do is remove the following from the sqlSessionFactory bean:
<property name="transactionFactory">
<bean class="org.apache.ibatis.transaction.managed.ManagedTransactionFactory" />
</property>
I must have somehow entered it thinking I needed it, but apparently it's only needed if you're not using CMT (Container Managed Transactions).
You can solve this by changing the transaction factory to
<property name="transactionFactory">
<bean class="org.mybatis.spring.transaction.SpringManagedTransactionFactory" />
</property>
I would like any requests that do not resolve to specific controller mappings to go to a view with a name derived from the request path.
Eg localhost/success should end up rendering a view located at /WEB-INF/view/freemarker/success.ftl. I gather from the Spring documentation that this behaviour should be enabled by default, by it doesn't appear to be working with my setup.
<mvc:annotation-driven />
<mvc:interceptors>
<!-- On pre-handle, resolve the device that originated the web request -->
<bean
class="org.springframework.mobile.device.DeviceResolverHandlerInterceptor" />
</mvc:interceptors>
<!-- Spring Mobile -->
<bean
class="org.springframework.mobile.device.view.LiteDeviceDelegatingViewResolver">
<constructor-arg>
<!-- Freemarker -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="false" />
<property name="prefix" value="" />
<property name="suffix" value=".ftl" />
</bean>
</constructor-arg>
<property name="mobilePrefix" value="mobile/" />
<property name="tabletPrefix" value="tablet/" />
</bean>
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/view/freemarker/" />
</bean>
Turns out there was no HandlerMapping implementation found for these requests, and so DispatcherServlet never called the DefaultRequestToViewNameTranslator.
Adding the following provided the appropriate HandlerMapping, and thus filled in the missing link. The only downside now is that it's throwing exceptions logging at SEVERE for any requests that can't be satisfied, as opposed to DispatcherServlet's more polite WARNING.
<mvc:view-controller path="/*" />