Java, Spring setting up themes confusing and not working - java

spring-servlet.xml setting up theme beans:
<bean id="themeSource"
class="org.springframework.ui.context.support.ResourceBundleThemeSource">
<property name="basenamePrefix" value="theme-" /> // also tried WEB-INF.resources.theme- and WEB-INF/resources/theme- here, same problem
</bean>
<bean id="themeChangeInterceptor"
class="org.springframework.web.servlet.theme.ThemeChangeInterceptor">
<property name="paramName" value="theme" />
</bean>
<bean id="themeResolver"
class="org.springframework.web.servlet.theme.CookieThemeResolver">
<property name="defaultThemeName" value="default" />
</bean>
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor" />
<ref bean="themeChangeInterceptor" />
</list>
</property>
</bean>
under WEB-INF/resources, where are 3 theme files:
theme-black.properties
theme-blue.properties
theme-default.properties
each file contain this accordingly:
css=themes/black.css
css=themes/blue.css
css=themes/default.css
i have folder WEB-INF/themes , which contains 3 of these css files, i think the content of css isn't important here.
now error i run into is :
javax.servlet.ServletException: javax.servlet.jsp.JspTagException: Theme 'default': No message found under code 'css' for locale 'en'.
so basically it just can't find the css value for themes, which means it can't find the properties file...
what I am doing wrong? feel free to ask questions

You should try to put theme properties into classpath (as is written in docs). Classpath is not /WEB-INF folder. See this question for clarity.
By default the delegate will be a
org.springframework.ui.context.support.ResourceBundleThemeSource that
loads properties files from the root of the classpath.

If you do don't want to put the theme.properties file under "classes" folder, you can put it under "META-INF" folder. If you use maven to create and manage the project, the "META-INF" folder is also unser the class path.
For example, if you put the themes under "META-INF/theme", you can do the following stuff to make it works.
<!-- resolves localized <theme_name>.properties files in the classpath to allow for theme support -->
<bean class="org.springframework.ui.context.support.ResourceBundleThemeSource" id="themeSource">
<property name="basenamePrefix" value="META-INF.theme."/>
</bean>

here the problem is not with css file actually ResourcebundleThemeSource trying to find theme-default.properties file in rot of classpath .ie. under the src folder. so put your all properties file under thier, and i am sure your problem will resolve.

Are you trying to use the i18N features in your application , regarding the localization if yes, then you need to add the below code
<"bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/messages" />
<property name="cacheSeconds" value="3000" />
</bean>
Otherwise remove your code <ref bean="localeChangeInterceptor" /> from the below code
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor" />
<ref bean="themeChangeInterceptor" />
</list>
</property>
</bean>
I hope this code will work properly.....

Related

Externalise properties working but not overriding existing default value in internal properties

I have a multi module maven project, each module is a jar with its own context file and a set of default properties bundled inside the JAR.
Basically in a core module I have this :
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:core.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
Now i have another module that build the application by loading all relevant XML and adding its own configuration file
<import resource="classpath*:core-context.xml" />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
<value>#{systemEnvironment['foo_bar']}</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
What happen is that all my configurations files are working fine except the one that has default value. I can't override them in application.properties or in the file pointed by the system variable.
I tryed to force the configuration file using the spring.config.location. I do see in the tomcat the message saying that I have the configuration -Dspring.config.file=file:///... (windows path). But spring is totally ignoring it (no message in the logs from Spring).
I tried to switch to PropertySources class without more success.
I'd very like to not have to remove all default properties and put everything in an external file, because lot of parameters are internal to the application and don't have any value for a client.
So what I am missing here ?
Well I finnaly found after many hours so something very ... easy.
Here is the trick : Declare the property placeholder before the import.
When you declare files in a property placeholder, it's the last that win, it seems here it's the exact opposite : the first place holder win.
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
<value>#{systemEnvironment['foo_bar']}</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
<import resource="classpath*:core-context.xml" />

Can't load multiple property files in spring's application context

I have three property files placed in a resource folder in classpath. The problem i am facing is while i am able to load invidual files separately i am unable to load them when they are declared together.
Please see the XML below:
<bean name="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames" value="resources\label"/>
</bean>
This is working but the XML given below isn't:
<bean name="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames" value="resources\label,resources\button,resources\messages"/>
<property name="cacheSeconds" value="1"/>
</bean>
I wish to declared them together as I wish to use a single bean to access all three files. Help required!
Found the answer . It should be like this `
<property name="basenames">
<list>
<value>classpath:resources\label</value>
<value>classpath:resources\button</value>
<value>classpath:resources\messages</value>
</list>
</property>
</bean>
Do it like this
<property name="basenames">
<list>
<value>resources\label</value>
<value>resources\button</value>
<value>resources\messages</value>
</list>
</property>

Using Spring Integration SpEl inside value tag

I am trying to set the properties file inside a class that extends the PropertyPlaceholderConfigurer based upon the environment (local, dev, ref, qa, prod)
My folder structure looks like the following.
properties
environment.properties
server-local.properties
server-ref.properties
server-prod.properties
email-local.properties
email-ref.properties
email-prod.properties
cache-local.properties
cache-ref.properties
cache-prod.properties
The environment.properties has a property
environment.stage=local (or whatever env this is)
My Spring Integration context statements look something like this:
<context:property-placeholder location="classpath:properties/*.properties" />
<bean id="propertyPlaceholder" class="com.turner.bvi.BviPropertiesUtil">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="locations">
<list>
<value>classpath:properties/environment.properties</value>
<value>classpath:properties/*-${environment.stage}.properties</value>
</list>
</property>
</bean>
What I want to do is have only the properties file from the particular environment stage load (be it local, ref, prod .... etc.). How do I get just this second set of properties files to load based upon environment.stage?
Thanks for the help in advance.
You can use Spring profiles for this, it would be something like this:
<context:property-placeholder location="classpath:properties/*.properties" />
<beans profile="local">
<bean id="propertyPlaceholder" class="com.turner.bvi.BviPropertiesUtil">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="locations">
<list>
<value>classpath:properties/environment.properties</value>
<value>classpath:properties/*-local.properties</value>
</list>
</property>
</bean>
</beans>
<beans profile="dev">
<bean id="propertyPlaceholder" class="com.turner.bvi.BviPropertiesUtil">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="locations">
<list>
<value>classpath:properties/environment.properties</value>
<value>classpath:properties/*-local.properties</value>
</list>
</property>
</bean>
</beans>
...
Setting an environment variable can be done using spring_profiles_active (or spring_profiles_default). In Unix try exporting SPRING_PROFILES_DEFAULT=local
You can alternativerly use the JVM parameters like -Dspring.profiles.active=local
In case you need to maintain the environment variables as they are, you can implement a custom ActiveProfilesResolver as described in here: Spring Profiles: Simple example of ActiveProfilesResolver?
Thank you all for your help. I was able to take snippets of all your suggestions and come up with a solution using "environmentProperties" in the Spring context.
The problem with trying to use a in the context was that it had not been set at the time MY class was trying to resolve the ${environment.stage}... Or at least that is what I gathered from searching other posts.
If my properties file structure looks like this:
properties
environment.properties
server-local.properties
server-ref.properties
server-prod.properties
email-local.properties
email-ref.properties
email-prod.properties
cache-local.properties
cache-ref.properties
cache-prod.properties
I was able to set the Environment property 'env' to the correct value through Chef or through a Docker container and use the following code.
<!-- Register the properties file location -->
<context:property-placeholder location="classpath:properties/*.properties" />
<bean id="propertyPlaceholder" class="com.turner.bvi.BviPropertiesUtil">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="locations">
<list>
<value>classpath:properties/environment.properties</value>
<value>classpath:properties/*-#{systemEnvironment['env']}.properties</value>
</list>
</property>
</bean>
I could have put each of the property sets under its own directory and had
<value>classpath:properties/#{systemEnvironment['env']}/*.properties</value>
Again, thank you all for your help.

Spring UTF-8 message resource from external jar issue

I have a problem with UTF-8 message sources in Spring MVC application. I've tried two implementations of AbstractMessageSource: ResourceBundleMessageSource and ReloadableResourceBundleMessageSource. I have an external jar with i18n messages contained in com.mypackage.i18n package
The configuration for ResourceBundleMessageSource:
<bean id="propertiesMessageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="com.mypackage.i18n.messages" />
<property name="useCodeAsDefaultMessage" value="true" />
</bean>
This configuration loads finds and loads properties, but fails with UTF-8, because this implementation just doesn't support UTF-8.
The configuration for ReloadableResourceBundleMessageSource:
<bean id="propertiesMessageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="com.mypackage.i18n.messages" />
<property name="useCodeAsDefaultMessage" value="true" />
<property name="fileEncodings" value="UTF-8" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
This configuration doesn't find properties. I know that this implementation to have reloadable resources needs properties to be located somewhere in WEB-INF directory and it doesn't restrict resources to be located somewhere else if you don't need reloading of resources.
According to the class java:
Note that the base names set as "basenames" property are treated in a slightly different fashion than the "basenames" property of ResourceBundleMessageSource. It follows the basic ResourceBundle rule of not specifying file extension or language codes, but can refer to any Spring resource location (instead of being restricted to classpath resources). With a "classpath:" prefix, resources can still be loaded from the classpath, but "cacheSeconds" values other than "-1" (caching forever) will not work in this case.
Can someone advice me how to solve the problem: I need to use another approach or somehow modify config of ReloadableResourceBundleMessageSource to find resources from jar?
I've found a solution. Proper ReloadableResourceBundleMessageSource configuration looks like this:
<bean id="propertiesMessageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:com/mypackage/i18n/messages" />
<property name="useCodeAsDefaultMessage" value="false" />
<property name="fileEncodings" value="UTF-8" />
<property name="defaultEncoding" value="UTF-8" />
<property name="cacheSeconds" value="-1"/>
</bean>

How to read jBoss configuration files in Spring?

I want to have a project independent configuration file that I can access from different projects. What I'm currently trying (and does not give me good results at all):
<bean id="wroProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="${JBOSS_HOME}/standalone/configuration/wro.properties" />
</bean>
I use Spring 3 and JBoss 7.1. My configuration files are under jboss/standalone/configuration/....properties. Besides that I want to read message files from that same directory with:
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames" value="messages,local" />
<property name="useCodeAsDefaultMessage" value="true" />
</bean>
Currently it looks for messages.properties and local.properties in src folder?
This is the solution I ended up using, which is platform independent and portable:
<bean id="wroProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="file:#{systemProperties['jboss.home.dir']}/standalone/configuration/wro.properties" />
</bean>
The configuration of the message source is identical.
A ResourceBundleMessageSource uses the basenames provided to (and the locale) to build a resource name (ex. message.properties) which is eventually (in the call stack) used by java.util.ResourceBundle.Control#newBundle(...). This resource name is then looked for on the classpath starting at its root (ex. /message.properties).
If you're on an IDE like Eclipse, your classpath very likely starts at src.
If jboss/standalone/configuration/... is on your classpath as well and the properties file are in there, you can change the basenames to
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames" value="jboss/standalone/configuration/messages,jboss/standalone/configuration/local" />
<property name="useCodeAsDefaultMessage" value="true" />
</bean>

Categories