Dealing with two different values of a property (cloud and default) in cloudfoundry and the #Value annotation - spring

I am in reference to Spring's #Value annotation as documented here: #Value and Spring profiles.
I need to be able to have different values for a given property such as:
websiteContext=http://localhost:8080/kadjoukor
...according to whether the app is running locally or on the cloud. I am not sure how to achieve that with the #Value("${websiteContext}") annotation...
What is the best practice for dealing with such an issue?

If you are using Spring 3.1 or later, you can take advantage of bean profiles and the CloudFoundry "cloud" profile to load a different properties file depending on the environment. That might look something like this in a Spring XML configuration file:
<beans profile="default">
<context:property-placeholder location="default.properties"/>
</beans>
<beans profile="cloud">
<context:property-placeholder location="cloud.properties"/>
</beans>
Here are a few good blog posts that explain how this works in more detail:
SPRING 3.1 M1: UNIFIED PROPERTY MANAGEMENT
USING CLOUD FOUNDRY SERVICES WITH SPRING: PART 4 – SPRING PROFILES

Related

Is it possible to use Spring boot with web.xml and annotation based configurataion

I want to use Spring Boot with web.xml and servlet 3.1 configuration.Is there any example?
I want to define my context(Dispatcher servlet/SpringBootServletInitializer) in Web.xml mean time define all other configuration using annotation based.Ex want to load application.properties/yml values using pojos.
Need this type of configuration to deploy the app in Liberty profile as Liberty expecting application context in web.xml when using liberety global sharelib.

Creating Spring Service that reads a file and serve queries based on its data

In a Java Web Project with Spring and JSF, I want do this: I want to have a service that in the first run of the app, reads a file and puts its data to a variable. then other classes can read that variable.
In fact I want that file reads one time and after that I just query the data, even web pages changed via links and navigation system.
Is there a Spring annotation to turn class to a service like this? Should I have some XML config files to specify a class as a service? I don't know what I have to do. What I know is that it can be done via Spring and I can get its data from JSF components, but how?
I have to do this based on MVC.
You can have it lazy-loaded on first call of the service. Or you can add a ContextListener to initialize the service on startup of the web context, assuming you are deploying to a J2EE container. Or you can make that service a spring bean with an init-method that initializes the data. Or any one of a hundred different ways. You'll need to determine what works best for your application.
Here's a spring example:
<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-2.5.xsd">
<bean id="myService"
class="org.your.Service"
init-method="initializeData"></bean>
</beans>
How you get hold of that service is up to you. You can either have the data stored statically on the class, or you can use the spring context to retrieve this single instance of the spring bean.
Spring documentation for lifecycle methods: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-lifecycle

Alternative to spring profiles

Using spring 3 I can determine which bean to use at runtime. But using Spring 2.5 what is the alternative?
Here is the config within my context file :
<jee:jndi-lookup id="myDataSource" jndi-name="jdbc/mydb"
resource-ref="true" expected-type="javax.sql.DataSource" />
I can use a profile to determine whether or not to use this datasource, what is the alternative when using an earlier version of spring (earlier than Spring 3)
Update :
"myDataSource" will be injected when I run my app locally, on a prod environment the "jndi" lookup, will be used. To inject "myDataSource" using Spring 3 I can use "profiles" but what alternative can I use if not using Spring 3 ?
You could define all your environment depend beans into several files, such as :
beans-dev.xml
beans-prod.xml
Your XML config would be :
<beans>
<import resource="beans-${myapp.env}.xml"/>
<bean id="bean1" class="..."/>
<bean id="bean2" class="..."/>
</beans>
In this case, myapp.env property is a JVM system property, i.e. configured with -Dmyapp.env=dev or -Dmyapp.env=prod. myapp.env cannot be setted from a property placeholder since Spring <import> are resolved before property placeholders.
You need to build out this kind of thing yourself. Typically by maintaining a number of different files for each profile that get composed together and a convention for picking the correct file at runtime. A -D System Property can help you pick which one. For example, we could have applicationContext-dev.xml and applicationContext-prod.xml, our applicationContext.xml would import applicationContext-${activeProfile}.xml, and you can set and load -DactiveProfile=dev; you can infer some of the other conventions like a context-param in the web.xml, etc. from how Spring3 profiles are designed.

Spring approach for changing configuration source by environment

I'm new to Spring and trying to figure out the best way to handle the following scenario:
We have an application where for local development and testing, all configuration values are pulled from a Properties file. When the app is deployed on to the App Server (Websphere in this case), instead of properties file we use JNDI resource properties.
Is there an accepted way of handling this in Spring? For a non-Spring application I probably would have done something like this using a good ol' factory pattern to decide the config source. For Spring, I've seen examples that use different context XML files per environment (sounds messy), or make use of Spring "Profiles".
Is there a generally accepted practice for this scenario?
Spring profiles are rather new and they were added precisely to address your problems. Moreover they should deprecate all other workarounds like different context XML files you mention.
For the sake of completeness here is an example:
<beans profile="test">
<context:property-placeholder location="/foo/bar/buzz.properties" />
</beans>
<beans profile="prd">
<jee:jndi-lookup id="properties" jndi-name="foo/bar/name"/>
</beans>
Depending on which profile you choose during deployment/startup, only one of the beans above will be instantiated.
Another approach I've never tried but seems to fit your case is default-value attribute in jee namespace:
<jee:jndi-lookup id="properties" jndi-name="foo/bar/name" resource-ref="true"
default-value="classpath:foo.properties"/>
Not sure if this will help you though.
Assuming Spring 3.1, try using profiles like Tomasz suggested, but instead of setting individual JNDI values for production, use
<beans profile="prd">
<context:property-placeholder/>
</beans>
In Spring 3.1, ContextLoaderListener apparently pulls in JNDI props as a PropertySource by default, so with property-placeholder, when you need to access a value you can just use ${some/jndi/name} in applicationContext.xml or a #Value annotation.
To make sure the webapp gets the values from JNDI, add
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>prd</param-value>
</context-param>
to web.xml.
In your tests, set the system property 'spring.profiles.active' to 'test', and you'll get the values from the props file.
one way to go is you use jndi also for local dev and testing. You could define the same jndi name. I don't know what's your testing server, in practice we use jetty, and maven-jetty plugin to test. It is lightweight and can run from your ide.
another way is like what you said in your question. Making use of Spring profile. Then you could declare different transactionManager beans with same id/name. of course they should be in different profiles. At runtime you could decide which profile should be activated, that is, which bean should be used.

Spring framework default-lazy-init all beans

Is there a spring property to lazy-init all beans that spring framework loads ?
I know about these properties
- lazy-init="true"
- default-lazy-init="true"
however there are multiple spring config xml files and some are packaged within jar so dont have liberty to change neither <bean> nor <beans> tag.
Any other way to tackle this via configuration ? or programatically ?
Short of extending the Spring bean loader, none that I know of.
You caN also use #Lazy annotation, but it is the same as you mentioned above.
According to java doc this should work ( though it looks not nice)
if (context.getBeanFactory() instanceof DefaultListableBeanFactory)
{
((DefaultListableBeanFactory) context.getBeanFactory()).setAllowEagerClassLoading(false);
}
I've implemented this on my company, had to extend some classes of spring tough. It wasn't easy, but we gained about 20s on every tomcat startup. Unfortunately, for privacy clauses, I can't show the code, but take a look at ClassPathBeanDefinitionScanner,DefaultBeanDefinitionDocumentReader,ContextNamespaceHandler and ComponentScanBeanDefinitionParser classes.
Starting with Spring Boot 2 you can use the spring.main.lazy-initialization property to configure lazy initialization across the whole application.
Setting the property value to true means that all the beans in the application will use lazy initialization.
in application.yaml
spring:
main:
lazy-initialization: true
or in application.properties
spring.main.lazy-initialization=true

Resources