Skip to main content

Use Spring profiles and yaml configuration without Spring Boot

That's a refinement you can do to updgrade legacy applications. Using yaml config files combines with Spring profiles is a great way to configure your apps. Let's see how to do that.

Firstly, let's consider that we weill inject something in a java class depending on the runtime  environment.

@Service
public class MyService {

@Value("${service.url}")
private String URL;

}

application.yaml should be like this :

service:
   url: http://alexdp.free.fr/violetumleditor

---
spring:
  profiles: production

service:
   url: http://violet.sourceforge.net


Thus, if I lauch my applicatin without JVM Spring profile params, URL will be http://alexdp.free.fr/violetumleditor. If I launch it with -Dspring.profiles.active=production, URL will be http://violet.sourceforge.net. Great! But this feature is natively supported only for Spring Boot based applications. So, let's active this on legacy apps with this XML spring config file fragment :

<bean id="yamlProperties"
class="org.springframework.beans.factory.config.YamlPropertiesFactoryBean">
<property name="resources">
<list>
<value>classpath:application.yml</value>
</list>
</property>
<property name="documentMatchers">
<bean
class="mypackage.SpringProfileDocumentMatcher" />
</property>
</bean>
<context:property-placeholder properties-ref="yamlProperties" />

Of course, you saw that we wrote our custom SpringProfileDocumentMatcher.

import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Properties;
import java.util.Set;

import org.springframework.beans.factory.config.YamlProcessor.DocumentMatcher;
import org.springframework.beans.factory.config.YamlProcessor.MatchStatus;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;


/**
 * Allows to use Spring profiles without Spring Boot for legacy Spring based apps
 * 
 * @author Alexandre de Pellegrin
 *
 */
public class SpringProfileDocumentMatcher implements DocumentMatcher, EnvironmentAware {

private static final String[] DEFAULT_PROFILES = new String[] { "default" };

private String[] activeProfiles = new String[0];

public SpringProfileDocumentMatcher() {
}

public SpringProfileDocumentMatcher(String... profiles) {
addActiveProfiles(profiles);
}

public void addActiveProfiles(String... profiles) {
LinkedHashSet set = new LinkedHashSet(
Arrays.asList(this.activeProfiles));
Collections.addAll(set, profiles);
this.activeProfiles = set.toArray(new String[set.size()]);
}

@Override
public MatchStatus matches(Properties properties) {
String[] profiles = this.activeProfiles;
if (profiles.length == 0) {
profiles = DEFAULT_PROFILES;
}
return new ArrayDocumentMatcher("spring.profiles", profiles).matches(properties);
}

@Override
public void setEnvironment(Environment environment) {
if (environment != null) {
       addActiveProfiles(environment.getActiveProfiles());
   }
}


private class ArrayDocumentMatcher implements DocumentMatcher {

private final String key;

private final String[] patterns;

public ArrayDocumentMatcher(final String key, final String... patterns) {
this.key = key;
this.patterns = patterns;

}

@Override
public MatchStatus matches(Properties properties) {
if (!properties.containsKey(this.key)) {
return MatchStatus.ABSTAIN;
}
Set values = StringUtils.commaDelimitedListToSet(properties
.getProperty(this.key));
for (String pattern : this.patterns) {
for (String value : values) {
if (value.matches(pattern)) {
return MatchStatus.FOUND;
}
}
}
return MatchStatus.NOT_FOUND;
}
}
}


That's it!

Comments

SATHYA TECH said…
Thank you for sharing such a nice and interesting blog with us.very unique and recommanded I would like to suggest your blog in my student circle

java training in hyderabad
java training institute in hyderabad
java training in ameerpet

Popular posts from this blog

DCcduino usb drivers (CH340 / CH341 chipset)

I've just received my first arduino platform. It's a DCcduino board (a clone of Arduino Uno). As I had some difficulties to have it recognised by my MacBook, I decided to share its drivers. This card has a CH340 USB-to-serial chip. You can find drivers for this chip on the web site of the chinese manufacturer, here :

http://www.wch.cn/downloads.php?name=pro&proid=5

Or download it directly from my Google Drive. The archive contains drivers for Mac, Linux and Windows platforms.

https://drive.google.com/file/d/0B5okZr5AW4gaX2pZaWt6dVNaSFU/edit?usp=sharing

I hope this will help somebody.

UPDATE for Mac users with Yosemite :

Please, follow this extra instructions :
Install the CH340 driverRun the command in Terminal: sudo nvram boot-args="kext-dev-mode=1"Reboot

The great alternative to JRebel

I'm an old user and addict of JRebel. I started to use it on open source projects and in professional contexts. From the beginning, I've been convinced that the licensing mode was wrong because of its lifetime. Asking for license renewal each year is boring. So, I decided to look for FREE alternative solutions and finally I recently found one.

This solution is efficient for maven projects developed with Eclipse. It is base on :

Hotswap Agent project : http://hotswapagent.org/Dynamic Source Lookup plugin for Eclipse : https://github.com/ifedorenko/com.ifedorenko.m2e.sourcelookup
I tested it with Java 7 & Java 8. I work on web applications that run on Tomcat. I developed wih Spring (IoC), sometimes Hibernate and Vaadin



Hotswap Agent installation consists on the deployment of a patch for your JVM. You just have to download the corresponding patch here : https://github.com/dcevm/dcevm/releases Then, download the hotswap-agent.jar from here : https://github.com/HotswapProjects…

How to secure REST services exposed with Jersey (JAX-RS) using Spring Security

This is the challenge I had to perform. I have to open services to business partners and I want to secure them. I use a Java based application with Jersey API (JAX-RS).

The first thing to consider is : what kind of solution offers the best compromise between security and the effort I'll have to provide to maintain this solution?
After some discussions with developers and experts, the conclusion is : expose your services over https and use Basic authentication (Digest authentication and certificate based authentication are too complex for partners)

So, how to implement that? I delegate "https" to my Apache http servers. But I still need to handle authentication (and authorization of course). After long hours on Google, I understood that it is possible to manage security with Jersey by many many ways. Here is a short list :

Delegate simple authentication and authorization to your container (Tomcat) or to your frontend (Apache)Delegate authentication to your container or fro…