how can I configure RedisHttpSessionConfigure to fallback if redis is not online - spring

I'm using spring-session + redis as documented here:
http://docs.spring.io/spring-session/docs/current/reference/html5/guides/httpsession-xml.html
How can I configure RedisHttpSessionConfigure such that for local development, redis is not needed and the application will simply default to the container session handling?

Generally this isn't recommended because you are differing your development environment from your production environment. It should be quite trivial to point your dev machine to a Redis instance.
If you need to support it, you can use Spring profiles. For example, with XML you can use something like:
<beans profile="dev">
<bean id="springSessionRepositoryFilter" class="org.springframework.web.filter.CharacterEncodingFilter"/>
</beans>
<beans profile="production">
<context:annotation-config/>
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
<bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"/>
</beans>
The key is to ensure that your dev environment also has a Bean that implements Filter named springSessionRepositoryFilter. In this example, I used CharacterEncodingFilter which should do nothing since the encoding property is not set but feel free to replace with whatever you like.
The next thing you will need to do is activate your environments. For example, you can use
-Dspring.profiles.active="production"

Related

Spring application should start even database is not available at startup

I have an old spring application which uses jee:jndi-lookup for datasource. This application running on Tomcat 8.
<jee:jndi-lookup id="datasource" jndi-name="java:/comp/env/jdbc/Tomcat8Database" destroy-method="close" expected-type="javax.sql.DataSource" lookup-on-startup="false"/>
The database may be sometime down at startup of the application, but as I also tried to lazy-init spring beans it did not helped as what it seems like that JNDI lookup in spring happened on Startup always or its not in spring controls as Server provide Pooling over connections.
Any idea or code example will be helpful.
According to spring javadoc, For a lazy lookup, a proxy interface needs to be specified.
Proxy interface specify the proxy interface to use for the JNDI object.
Typically used in conjunction with "lookupOnStartup"=false and/or "cache"=false. Needs to be specified because the actual JNDI object type is not known in advance in case of a lazy lookup.
Try:
<jee:jndi-lookup id="datasource" jndi-name="java:/comp/env/jdbc/Tomcat8Database" destroy-method="close" expected-type="javax.sql.DataSource" lookup-on-startup="false" proxy-interface="javax.sql.DataSource"/>

Load different properties for development and deployment

I have a very common use case -- connect to different databases when my program is in development mode, in test mode, or in deployment mode.
The way I am doing it now, is I configure a data source, and pass it ${...} properties via bean:property tag.
However to get the ${...}, i am doing
<context:property-placeholder properties-ref="myProperties" />
and in the bottom of the xml config, I have
<beans profile=test>
<util:properties id=myProperties>
</util>
</beans>
<beans profile=dev,default>
<util:properties id=myProperties>
</beans>
<beans profile=prod>
<util:properties id="myProperties>
</beans>
This seems inefficient, overly verbose, and prone to error. All spring properties tutorials tell me that context:property-placeholder is Environment aware, and Environment is responsible for profiles so how do I simplify this? It is intuitive to me that there is a simpler way, I just can't figure it out.
Really, what I am looking for is to specify profile on context:properties-placeholder, or something like that.
I solved that problem once (a long time before Spring supports profiles): spring property substitution for test and production
nowadays a would still use property files but, but I would select them by profiles. There are a lot of ways to do this:
The simplest one is:
<context:property-placeholder
location="classpath*:META-INF/spring/config-${spring.profiles.active}.properties" />
an other is:
<beans profile="normal">
<context:property-placeholder
location="classpath*:META-INF/spring/config-normal.properties"/>
</beans>
<beans profile="test">
<context:property-placeholder
location="classpath*:META-INF/spring/config-test.properties"/>
</beans>
The first approach has the drawback, that when more than one profile is activated then only the properties for the first profile gets loaded. I am not sure what will happen with the second approach when having more than one profiles.
For the first approach I found this solution, but I have not tested it:
<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>
While profiles are certainly a solution to that problem I think that this approach opens another big door to issues that you discover only on the target platform.
In my projects I have always externalized the properties and turned as many properties as possible into runtime parameters.
Just imagine having to bundle Jenkins/Sonar/etc again as your platform will not be part of a profile with properties residing in the classpath. I don't think that then these would be successful projects ;)
As for spring you can use the 'file://' protocol in a propertyconfigurer allowing to superseed a "dedault" property coming from the classpath. So you have two configurer tags with an order parameter and other properties. Here's an example:
<jee:jndi-lookup id="configDirectory" jndi-name="configDirectory"
resource-ref="true" default-value="." />
<jee:jndi-lookup id="datasource" jndi-name="jdbc/datasource"
expected-type="javax.sql.DataSource" default-ref="localDatasource" />
<!-- Allows fetching properties from multiple locations: -->
<!-- external definition -> file://${configDirectory}/root-context.properties
-> declared in context.xml -->
<!-- standard web application bundle -> /WEB-INF/spring/root-context.properties -->
<!-- testing -> classpath:root-context.properties -->
<context:property-placeholder location="${configDirectory:.}/context.properties"
order="9" ignore-resource-not-found="true" ignore-unresolvable="true" />
<context:property-placeholder
location="/WEB-INF/spring/context.properties,
classpath:context.properties"
order="10" ignore-resource-not-found="true" ignore-unresolvable="true" />
<context:property-placeholder location="classpath:spring/default.properties"
order="100" />
Like this we are able to build it locally, run our unit and integration tests during maven build, run the build on UAT and if all that is ok copy the build from UAT to PROD without having to modify the war file.
In the properties we define all the parametersthat cannot be changed at runtime, which is essentially the Hibernate parameters plus some others.
All the rest is stored in the database as simple system parameters (key-value pairs). There are a lot of properties that do not need to be fixed. This includes: LDAP, MailSender, folder definitons like tempdir and others.
As the datasource is one of the very first beans to be initiated this works pretty nice in the projects I am running currently, and we are still discovering more properties to be pushed into the database.
Please read:
https://examples.javacodegeeks.com/enterprise-java/spring/load-environment-configurations-and-properties-with-spring-example/
<context:property-placeholder location="
classpath:application.properties,
classpath:application${spring.profiles.active}.properties"
ignore-unresolvable="true"/>
mvn clean install -Dspring.profiles.active="profile_name".

Configure singleton CacheManager for multiple web applications with Spring Caching

I have multiple web applications deployed in Tomcat and service jar shared in TOMCAT_HOME/lib/ext. All of the application are using Spring, and in the service jar I have beans, annotated with Spring 3.1 Caching annotations . I am using Ehcache provider. And I want to have one single CacheManager used by all the web applications. If I define spring cache configurations at web application level, caching works, but separate cacheManager is created for every app/context. 'Shared' Cache Manager is causing problems, because if one the those applications gets undeployed, this shared cacheManager is shut down. So I want a single CacheManager , configured in my service jar, and used for all the calls to methods made from beans from the web apps. My current try is to define following confuguration in service.jar's applicationContext.xml:
<context:annotation-config/>
<context:component-scan base-package="com.mycompany.app" />
<context:component-scan base-package="com.mycompany.portal.service" />
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cacheManager-ref="ehCacheManager"/>
<bean id="ehCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:configLocation="ehcache.xml" ></bean>
<cache:annotation-driven cache-manager="cacheManager"/>
I have defined parent application context via beanRefContext.xml:
<bean id="service.parent.context" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<list>
<value>applicationContext.xml</value>
</list>
</constructor-arg>
</bean>
And I am using this context as a parent context for all of my web apps with following contextParam in web app's web.xml:
<context-param>
<param-name>parentContextKey</param-name>
<param-value>service.parent.context</param-value>
</context-param>
The result is that this parentContext is loaded, but caching doesn't work at all
How can I solve this? Am I on the right way with the defining of the parentContext in the service.jar?
I don't think so. It looks like you are trying to have a single cache for multiple applications by "hacking" the root classloader.
If you need to share your cache across several applications, use a cache manager that supports that use case (i.e. that provides you a service you can reach from each application).

Switching between jms providers

I would like to do a SPRING (3.2.1) setup where I can switch the underlying JMS provider depending on the environment you are in e.g. dev, test, prod. I am no expert but have come across #Profile annotation of Spring. I don't really know how to use it. So what I need to do is in DEV environment I want to use ActiveMQ and in PRODUCTION I want to use IBM MQ. Is this possible? If so, would appreciate it if you could provide some config or code to do this. Thanks in advance.
http://static.springsource.org/spring-framework/docs/3.2.1.RELEASE/spring-framework-reference/html/new-in-3.1.html#new-in-3.1-bean-definition-profiles
For XML config, see this blog... http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/
See this blog about #Profile: http://blog.springsource.com/2011/02/14/spring-3-1-m1-introducing-profile/ for using profiles with #Configuration.
It boils down to this...
When using XML configuration, simply add <beans/> elements at the end of your spring config files...
<beans ...>
<bean... />
<beans profile="DEV">
<bean ... // my ActiveMQ config .../>
</beans?
<beans profile="default">
<bean ... // my IBM (or JNDI) config .../>
<beans/>
</beans>
Then run in dev with -Dspring-profiles-active=DEV.
Similarly #Profile can be added to #Configuration classes to limit their use to particular active profiles.

Good example of Spring Configuration using java.util.prefs or Commons Configuration

One application I'm working on has several URLs and other information that is instance specific. The first pass uses a typical Spring PropertyPlaceholderConfigurer with a properties file:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:application.properties"/>
</bean>
The main issue with this is of course the property file is an artifact that must be checked in, and for starting a new instance would require updating that artifact. For a streamline deployment, I would like to have the ApplicationContext bootstrap itself based on database table(s). I have seen solutions like this forum post, does anyone here know of better tools or is this defacto approach to this problem? I would also like to be able to update/reload the settings at runtime using JMX or other facilities, but having to restart the app after changes to the database would still be a better solution to the current one.
The way we did it was to put some configuration information in the environment and then pull the relevant info from there.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="searchSystemEnvironment" value="true" />
</bean>
If configuration changes then the app will need to be restarted. Can also put all the different configurations into the environment and nest the variables like the following:
<bean id="db" class="org.DataSource"
p:databaseServer="${${MODE}_DBSERVER}"
p:databaseName="${${MODE}_DBNAME}" />
where $MODE = dev, qa, etc.

Resources