Blogs

SpringSource Blog

Spring Framework 3.1 M1 released

Chris Beams

The first milestone release of Spring 3.1 has just been published [1], and this article kicks off a series of posts where I and other team members will walk through each of the major features. Even in the first milestone there's already a lot to talk about!

  • Bean definition profiles
  • Unified property management through Spring's new Environment abstraction
  • Enhancements to Java-based configuration with @Feature methods
  • Expanded MVC namespace support and a Java-based configuration equivalent
  • Streaming support and new interception model for the RestTemplate API
  • Comprehensive caching support
  • New c: XML namespace for concise configuration of constructor injection


Today I'll be covering the first item — a new feature we call bean definition profiles. One of our most frequent requests has been to provide a mechanism in the core container that allows for registration of different beans in different environments. The word "environment" can mean different things to different users, but a typical scenario might be registering monitoring infrastructure only when deploying an application into a performance environment, or registering customized implementations of beans for customer A vs. customer B deployments. Perhaps one of the most common cases would be working against a standalone datasource in development vs looking up that same datasource from JNDI when in QA or production. Bean definition profiles represent a general-purpose way to satisfy use cases of this kind, and we'll explore the latter use case in the examples below.

Get hands-on with a sample

I've developed a small sample to accompany this post, and you might like to take a moment now to check it out (if not, don't worry; you don't need the code to read along below). Just follow the instructions on the README at https://github.com/cbeams/spring-3.1-profiles-xml. If you're not familiar with Git, the README has instructions for SVN access, too.

Understanding the application

First let's take a look at a JUnit test case that demonstrates how transferring money between two accounts should work in our banking application:

src/test/com/bank/config/xml/IntegrationTests.java

public class IntegrationTests {
	@Test
	public void transferTenDollars() throws InsufficientFundsException {

		ApplicationContext ctx = // instantiate the spring container

		TransferService transferService = ctx.getBean(TransferService.class);
		AccountRepository accountRepository = ctx.getBean(AccountRepository.class);

		assertThat(accountRepository.findById("A123").getBalance(), equalTo(100.00));
		assertThat(accountRepository.findById("C456").getBalance(), equalTo(0.00));

		transferService.transfer(10.00, "A123", "C456");

		assertThat(accountRepository.findById("A123").getBalance(), equalTo(90.00));
		assertThat(accountRepository.findById("C456").getBalance(), equalTo(10.00));
	}
}

We'll get to the details of creating the Spring container in a moment, but first notice that our goal is simple — transfer $10.00 from account "A123" to account "C456". The unit test simply asserts the initial balances in the two accounts, performs the transfer, then asserts that the final balances reflect the change.

A typical XML configuration

The bean definition profiles feature is supported equally well in Spring XML as it is when using Spring @Configuration classes to configure the container, but in today's post we'll cover the XML approach as that's what most users are familiar with.

Forgetting about bean definition profiles for a moment, to configure this application in Spring XML one would traditionally do something like the snippet below. Let's assume we're early in the development process and that working against a standalone datasource is preferred. We'll use HSQLDB for convenience, but you may of course imagine the datasource of your choosing being configured.

src/main/com/bank/config/xml/transfer-service-config.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xsi:schemaLocation="...">

	<bean id="transferService" class="com.bank.service.internal.DefaultTransferService">
		<constructor-arg ref="accountRepository"/>
		<constructor-arg ref="feePolicy"/>
	</bean>

	<bean id="accountRepository" class="com.bank.repository.internal.JdbcAccountRepository">
		<constructor-arg ref="dataSource"/>
	</bean>

	<bean id="feePolicy" class="com.bank.service.internal.ZeroFeePolicy"/>

	<jdbc:embedded-database id="dataSource">
		<jdbc:script location="classpath:com/bank/config/sql/schema.sql"/>
		<jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/>
	</jdbc:embedded-database>
</beans>

The only potentially unfamiliar item above might be the use of Spring's jdbc: namespace. Introduced in Spring 3.0, the elements within allow for easy configuration of commonly used embedded database types. It's used here just as a convenience.

With this configuration in mind, we can now finish writing the unit test we started above.

src/test/com/bank/config/xml/IntegrationTests.java

public class IntegrationTests {
	@Test
	public void transferTenDollars() throws InsufficientFundsException {

		GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
		ctx.load("classpath:/com/bank/config/xml/transfer-service-config.xml");
		ctx.refresh();

		TransferService transferService = ctx.getBean(TransferService.class);
		AccountRepository accountRepository = ctx.getBean(AccountRepository.class);

		// perform transfer and issue assertions as above ...
	}
}

Side note: We're using Spring's GenericXmlApplicationContext application context in order to load the XML configuration. Many Spring users will be more familiar with ClassPathXmlApplicationContext, which would work equally as well. As a general rule, however, GenericXmlApplicationContext is a more flexible alternative that should be generally preferred.

When running this test, the bar will be green. Our simple application is wired up by the container and we retrieve some of the beans and excercise them — nothing special to see here, folks. It gets interesting when we consider how this application will be deployed into a QA or production environment. For example, it is a common scenario for enterprises using Spring to develop web applications against Tomcat for ease-of-use reasons, but then deploy those applications into WebSphere in production. Chances are very good that the datasource for the application will be registered with the production application server's JNDI directory. This means that in order to get hold of the datasource, we must perform a JNDI lookup. Of course Spring provides great support for doing so, and one popular way is through Spring's <jee:jndi-lookup/> element. The production version of the configuration file above might end up looking something like the following:

src/main/com/bank/config/xml/transfer-service-config.xml

<beans ...>
	<bean id="transferService" ... />

	<bean id="accountRepository" class="com.bank.repository.internal.JdbcAccountRepository">
		<constructor-arg ref="dataSource"/>
	</bean>

	<bean id="feePolicy" ... />

	<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
</beans>

Of course this configuration works perfectly well. The problem is how to switch between using these two variations based on the current environment. Over time, Spring users have devised a number of ways to get this done, usually relying on a combination of system environment variables and XML <import/> statements containing ${placeholder} tokens that resolve to the correct configuration file path depending on the value of an environment variable. While these and other solutions can be made to work, they're hardly what we would call "first-class" solutions provided by the container.

Enter bean definition profiles

If we generalize the example use case above of enviroment-specific bean definitions, we end up with the need to register certain bean definitions in certain contexts, while not in others. You could say that you want to register a certain profile of bean definitions in situation A, and a different profile in situation B.

In Spring 3.1, <beans/> XML documents now incorporate this new concept. We can break our configuration down into the following three files. Notice the profile="..." attribute on the *-datasource.xml files:

src/main/com/bank/config/xml/transfer-service-config.xml

<beans ...>
	<bean id="transferService" ... />

	<bean id="accountRepository" class="com.bank.repository.internal.JdbcAccountRepository">
		<constructor-arg ref="dataSource"/>
	</bean>

	<bean id="feePolicy" ... />
</beans>

src/main/com/bank/config/xml/standalone-datasource-config.xml

<beans profile="dev">
	<jdbc:embedded-database id="dataSource">
		<jdbc:script location="classpath:com/bank/config/sql/schema.sql"/>
		<jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/>
	</jdbc:embedded-database>
</beans>

src/main/com/bank/config/xml/jndi-datasource-config.xml

<beans profile="production">
	<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
</beans>

We can then update the test case to load all three files:

	GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
	ctx.load("classpath:/com/bank/config/xml/*-config.xml");
	ctx.refresh();

But this is not quite enough. When running the unit test after these changes, we would see a NoSuchBeanDefinitionException thrown, because the container could not find the Spring bean named "dataSource". The reason why is that while we have clearly defined two bean definition profiles — "dev" and "production", we have not yet activated either of them.

Enter the Environment

New in 3.1 is Spring's notion of an Environment. This abstraction has been integrated throughout the container, and we'll see it several times over the blog posts in the coming days. For our purposes here, it's important to understand that the Environment contains information about which profiles (if any) are currently active. When the Spring ApplicationContext above is loading our three bean definition files, it pays close attention to the <beans profile="..."> attribute in each of them. If it is present and set to the name of a profile that is not currently active, the entire file is skipped — no bean definitions are parsed or registered.

Activating a profile can be done in several ways, but the most straightforward is to do it programmatically against the ApplicationContext API:

	GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
	ctx.getEnvironment().setActiveProfiles("dev");
	ctx.load("classpath:/com/bank/config/xml/*-config.xml");
	ctx.refresh();

At this point, running our unit test will result in the green bar. Let's break down how the container thinks about things when loading the three files that match *-config.xml:

  • transfer-service-config.xml does not specify a profile attribute at all, so it is always parsed
  • standalone-datasource-config.xml specifies profile="dev" and the "dev" profile is currently active, so it is parsed
  • jndi-datasource-config.xml specifies profile="production" but the "production" profile is not currently active, so it is skipped.

The result is exactly one registered bean named "dataSource", which satisfies the dependency injection needs of the "accountRepository" bean. Everything works once again.

How then does one switch to the JNDI lookup when actually in production? Of course it's necessary to activate the "production" profile. It's fine to do this programmatically for the purpose of a unit test as above, but this approach won't be practical once the WAR file has been created and the application is ready for deployment. For this reason, profiles may also be activated declaratively through the spring.profiles.active property which may be specified through system environment variables, JVM system properties, servlet context parameters in web.xml or even as an entry in JNDI [2]. For example, you might configure web.xml as follows:

  <servlet>
      <servlet-name>dispatcher</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
          <param-name>spring.profiles.active</param-name>
          <param-value>production</param-value>
      </init-param>
  </servlet>

Note that profiles are not an "either-or" proposition; it is possible to activate multiple profiles at once. Programmatically, simply provide multiple profile names to the setActiveProfiles() method, which accepts String... varargs:

	ctx.getEnvironment().setActiveProfiles("profile1", "profile2");

Declaratively, spring.profiles.active may accept a comma-separated list of profile names:

	-Dspring.profiles.active="profile1,profile2"

Bean definition files may be marked as candidates for more than one profile in a similar fashion:

	<beans profile="profile1,profile2">
		...
	</beans>

This allows for a flexible approach to decomposing your application, slicing and dicing which beans are registered under which circumstances.

Making it even simpler: introducing nested <beans/> elements

So far, bean definition profiles have provided us with a convenient mechanism for determining which beans get registered based on the deployment context of the application, but it came with one downside: Where above we had a single Spring XML configuration file, we now have three. This split was necessary in order to distinguish profile="dev" vs. profile="production" beans, because the profile attribute is specified at the <beans> element level.

With Spring 3.1, it is now possible to nest <beans/> elements within the same file. This means that we can, if desired, return to a single configuration file:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xsi:schemaLocation="...">

	<bean id="transferService" class="com.bank.service.internal.DefaultTransferService">
		<constructor-arg ref="accountRepository"/>
		<constructor-arg ref="feePolicy"/>
	</bean>

	<bean id="accountRepository" class="com.bank.repository.internal.JdbcAccountRepository">
		<constructor-arg ref="dataSource"/>
	</bean>

	<bean id="feePolicy" class="com.bank.service.internal.ZeroFeePolicy"/>

	<beans profile="dev">
		<jdbc:embedded-database id="dataSource">
			<jdbc:script location="classpath:com/bank/config/sql/schema.sql"/>
			<jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/>
		</jdbc:embedded-database>
	</beans>

	<beans profile="production">
		<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
	</beans>
</beans>

spring-beans-3.1.xsd has been updated to allow this nesting, but constrained to allow such elements only as the last ones in the file. This should help provide flexibility without incurring clutter in the XML files. While this enhancement was developed in service of bean definition profiles, nested <beans/> elements are useful in general. Imagine you have a subset of beans in a given file that should be marked lazy-init="true". Rather than marking each bean, you could instead declare a nested <beans default-lazy-init="true"/> element, and all beans within will inherit that default. Beans defined elsewhere in the file will maintain the normal default of lazy-init="false". This applies for all the default-* attributes of the <beans/> element, such as default-lazy-init, default-init-method, default-destroy-method, and so on.

Caveats

There are a few things to watch out for when considering the use of bean definition profiles.

Do not use profiles if a simpler approach can get the job done. If the only thing changing between profiles is the value of properties, Spring's existing PropertyPlaceholderConfigurer / <context:property-placeholder/> may be all you need.

The set of beans registered between two profiles should probably be more similar than different. For example, if you have a radically different set of beans in dev and QA than you do in production, the question becomes: are you testing everything you should be?. As a rule of thumb, beans shouldn't differ much beyond the dev/QA split. An exception might be conditionally introducing monitoring aspects in a performance environment.

Be careful not to ship "too much" into production. If you have certain beans and class libraries present during development but that are unnecessary or unwanted in production, you run the risk of packaging all of that up and deploying it live. This is wasteful (why drag everything into the WAR if it's not needed), but also potentially insecure. Remember that the way profiles are activated is through properties. For example, if your totally insecure 'no-op password encryptor' bean definition and class are both present in the production environment, and all it takes to turn this on is the acccidental activation of the 'dev' profile, the danger is clear. A couple options for mitigating this risk might be customizing your build system to exclude unnecessary or unwanted classes from the production deployment archives, or working with the native Java SecurityManager API to disallow access to the spring.profiles.active system environment variable and/or JVM system property. Doing so will mean that even though Spring may try to read these values, it won't be able to and will move on as if they'd never been set.

Summary

That's it for now; I encourage you to take a look at the sample application and play around. For example, try running the unit tests as-is, then try setting the spring.profiles.active system property to "production" and see what happens.

In the next post in this series, we'll take a look at how bean definition profiles can be used when configuring the container with @Configuration classes instead of XML; the new @Profile annotation will help us out there.

Footnotes

[1] Milestone builds are published to http://maven.springframework.org/milestone. See the pom.xml and build.gradle files in the sample for details on how to pull from this repository.

[2] technically spring.profiles.active may be specified in any PropertySource object registered with the ApplicationContext's Environment. We'll cover the concept of property sources in a subsequent blog post.

Similar Posts

Share this Post
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • LinkedIn
  • Slashdot
  • Technorati
  • Twitter
 

46 responses


  1. Great feature.

    I'm looking forward for the other features to be blogged next :)


  2. One of the cool features of the "c" namespace is the ability to name argument parameters. <bean class=“…” c:age=“35” c:amount=“50000”/>

    Regards,
    Gordon Dickens

    Instructor / Mentor
    Chariot Solutions
    chariotsolutions.com/education
    technophile.gordondickens.com
    twitter.com/gdickens


  3. Could be one of the best features. One question left to me. web.xml is shipped within our application. How to detect the active profile for Prod/Q/Dev?


  4. I would change comma-separated list of profile names to space-separated list, like more usual way for example in html


  5. Excellent article, Chris! It's great to see Spring Framework 3.1.0.M1 here today!

    We have been using bean profiles to much success in the Greenhouse reference application. In Greenhouse, we have two modes of operation: "embedded" and "standard". The "embedded" mode allows the app to run for demonstration and developer-testing purposes without any external setup required (it is also the default mode). The "standard" mode is what we run our production instance in, which connects to an external database and file store (and is activated by passing '-Dspring.profiles.active=standard' to our production server). The beans that differ between the modes include the dataSource and pictureStorage, along with the passwordEncoder and stringEncryptor. We also use PropertyPlaceholderConfigurer in conjunction with the Maven Properties plugin to vary bean property values across these environments.

    Keep up the great work!

    Keith


  6. It would be really nice if the "What's New in Spring x.x"-section in the reference documentation was updated for milestones too. Maybe only with links to start with….


  7. Congratulations to the team for the fantastic work. Is servlet 3.0 available in this release?


  8. Chris,

    Thanks for an excellent review on Spring's new 'profile' feature.

    A question about using profiles in test environment:
    Will test environment have an in-code mechanism (such as extending @ContextConfiguration annotation or adding new behavior to SpringJUnit4ClassRunner) to support such selection ?

    Guy.


  9. Hi Guy,

    We've already had some discussions about how to enable profile selection within tests, and I've just created a JIRA issue here to capture our thoughts:

    https://jira.springsource.org/browse/SPR-7960

    Regards,

    Sam


  10. It is nice to finally see explicit support for environment-aware Spring configuration. For those of you that are not in a position to upgrade but would still like to use a similar mechanism I can recommend the following approach:

    1) launch your VM with a system property, e.g. -Dmy.env=prod
    2) Use the property in an import tag i.e.

    We've been using this since 2.0.x and it works like a charm :)

    Happy coding,
    Jorg Heymans


  11. @Chris.

    Great to see things being made explicit and consistent. Property-placeholder suffers when aggregating components with spring contexts, so I hope that during the 3.1 milestone stages, we really get some production use of this to find the corner cases.

    Reading your example, I can see a few areas I'd like to be explicit:
    1) Being able to define valid profile combinations. In your example, you can specify "production,dev", which is clearly not what is intended, and all too easy to do.

    This could be achieved by allowing profiles combinations to be specified.

    2) Going with the above, it may be wise to be able to configure specific bean definition override behaviour (i.e. 'final' bean defs). ** This would have saved a LOT of time on the project I've recently been working on, mainly due to the number of components developed by different teams with varying levels of Spring experience **

    Either of the above would prevent the 'prod,dev' profile from being bootstrapped:

    1)

    2)

    .. jndi datasource bean defs

    .. dev datasource defs


  12. Darn XML examples in comments don't work, so:

    1)
    [config]
    [profileOptions exclusive="production,dev,uat"/]
    [profileOptions exclusive="perf,trace"/]
    [/config]

    2]
    [beans profile="production" final="true"]
    … jndi datasource bean defs
    [/beans]
    [beans profile="dev" final="true"]
    … dev datasources
    [/beans]


  13. Awesome post… very helpfull


  14. I trust that the extensible XML bean configuration authoring support has a nice way to create a bean definition with a given profile? I have a lot of custom XML processing code that I'd love to rework to take advantage of profiles…


  15. Great to see this support. We have 6 env, dev, qa, staging1, 2, pre-production, and production in my company. I will definitely give this a try soon.


  16. Great news.

    I have been wanting this kind of functionality for a couple of years now. So much infact that I created a small framework for this called Constretto back in 2008. It have since been used in several norwegian systems, and I have grown addicted to it :)
    Now I hope I can deprecate the assembly capabilites of it, and focus on the core abstractions of configuration.

    One experience I had was that my users soon stopped using the feature of choosing beans by environment, but more and more used targeted configuration. This can indicate that we need that functionality more.

    btw, do not look for much documentation in the constretto pages, but the testcases in the source code shows lots of different usecases


  17. Thanks for these articles on Spring 3.1 – very good. Do you have an estimate on when the 3.1 final release will be out?


  18. The final release is scheduled for the June 2011 timeframe.


  19. Thanks, @Neale. Would you mind adding an issue for both these requests?


  20. Good point, @jjjjj. I've relaxed the restrictions on the delimiter to allow for comma, space or semicolon to be used. This is consistent with other similar elements/attributes like 'alias'. See https://jira.springsource.org/browse/SPR-8033.


  21. @Paul, are you referring to tooling support in STS? If so, it will follow, but is not there yet. If you're referring to authoring custom BeanDefinitionParsers, then the idea is that you would declare your custom namespace elements within the bounds of a element. There is no explicit support in the BeanDefinition model for setting the profile(s) for individual beans.


  22. @Chris: https://jira.springsource.org/browse/SPR-7982


  23. Chris, as always excellent writing. Thanks

    I like that we are taking the approach that Grails has been using, where we can create multiple of the same beans within the same configuration file.

    Speaking of grails, I wonder if we could in the future use json for our configuration files instead of xml? Sorry I digress.

    Mark


  24. Chris – Bean profiles will be useful, but I think your example of using them to configure a bean for test and the same bean for production in one Spring configuration file is not a good use case. Mixing test and production settings is not a standard practice and should be avoided.

    Spring provides excellent support for working with JUnit (see RunWith and ContextConfiguration annotations). So a developer can easily specify a Spring configuration that will just be loaded for running tests and not become part of the production build–especially if the developer follows Maven's conventions of placing test configurations in src/test/resources.


  25. Not too long ago, I blogged about JUnit & Spring:

    JUnit & Spring: What You Don't Know.
    http://gordondickens.com/wordpress/2011/01/07/junit-spring-what-you-dont-know-about/


  26. So this is just what I need.

    We have to mock out and external service and in integration testing use the mocked out version of the external service. This would really simplify that problem.


  27. Would like to see the ability to have a "default" profile that is used if none is specified. This would make it easier for production.


  28. Hi Adrian,

    Have a look at http://jira.springframework.org/browse/SPR-8203 and watch / vote for it if you like. This notion of a reserved default profile name has been requested a number of times now, and it's likely we'll put it (back) in for 3.1 M2.


  29. Chris & Spring committers,

    Isn't it about time the Mn releases (of Spring Framework and Spring Data) got published to Maven Central?

    It's quite clear that they are single releases not snapshots, so why not make early adoption and feedback that bit easier.


  30. By Mn, I mean Milestone releases (dunno why I didn't just type that the first time)


  31. Hi Neale,

    We (SPR, at least) will very likely begin publishing our milestones and RCs to Maven Central starting with 3.2 M1.


  32. Sounds good. Although I don't see any reason not to do so for 3.1.0.M2 either.

    When 3.0 was coming into final milestone and RCs, I used that in projects knowing it would be final before the project hit UAT. In our more agile world, it's not inconceivable to base iterations on consuming milestone releases, with 3.1 M1 being a great example, bringing code saving features that everyone wants to use yesterday ;)


  33. @Neale, you might want to put a watch on http://jira.springframework.org/browse/SPR-8424, which I just created.


  34. greatgreatgreat


  35. Do you have a facebook fan page? I looked for one on twitter but could

    not discover one, I would really like to become a fan!

    http://investorhomesolutions.com/


  36. It would be nice to be able to specify what happens when a profile is not defined "!production". It would allow easier definition when there are more than 2 mutually exclusive profiles (e.g., production, dev, test) and will allow creating default cases when a profile is not defined (the use of setDefaultProfiles means i have to code these in code and doesn't work well if there are several sets of profiles)


  37. @Ittay – please comment/watch/vote on https://jira.springsource.org/browse/SPR-8728


  38. We've been using Maven's support for profiles to do a similar job. We create profile specific resource directories, e.g. dev-resources, prod-resources containing app contexts for data sources etc. then activate them with "mvn -Pdev" for example.
    I'm not sure the profile support in Spring 3.1 is sufficient to tempt us away from this.


  39. @Chris,

    the more I look at the application sample (https://github.com/cbeams/spring-3.1-profiles-xml), the more I think it's great to be able to manage deployment profile within Spring.
    It really simplifies the deployment process to be able to produce a single WAR/JAR and then trigger the profile needed from an environment variable.

    That being said, to be able to fully cover the configuration needs with Spring and get rid of any other system, I would count 3 parts that need to be covered:

    - bean definition profile and bean properties placeholder (covered obviously)
    - legacy application properties placeholder (all the properties used internally by the application and that changes between environment)
    - 3rd parties system configuration properties (e.g. log4j.properties)

    Your application sample doesn't have any internal properties, but it does have a typical log4j.properties for instance.
    You definitely want a different log4j config in dev and in production.

    If these needs aren't covered by Spring, another system is still needed to cover application configuration at deployment. You would end up with a mix of 2 systems, which is pretty bad as it makes the whole configuration more complex. (e.g. typically, a Maven profile filtering with a spring.profiles.active variable)

    It'd be great to be able to cover everything with Spring, and just deploy a unique WAR/JAR, and that's it.

    That's what I started to implement internally based on Spring's PropertiesLoaderSupport and PropertySourcesPlaceholderConfigurer. I'm now able to cover the 2 first items in the above list. It's pretty simple and can replace Maven profile filters.

    I have started to implement an ad-hoc solution for 3rd parties like log4j, and well, I realize that Spring can't go what I consider half way on this one.

    I just notice @Richard comment, and that just support my point: as it is now, it can't really lure people away from other configuration systems.
    And if not, using bean profile definition means another layer of configuration, which even if very convenient, just adds another layer of complexity instead of simplifying the whole thing.

    I guess it's outside of the initial scope but it could become part of a second iteration. What do you think?


  40. @Jean,

    With regard to log4j, have you considered simply programmatically configuring log4j within one of your @Configuration classes?

    This would be reasonable to do within a @PostConstruct method, for example. You could consider using Spring's own Log4jConfigurer support here. Point to one log4j config file for profile A, another for profile B.

    I'm not sure I follow regarding 'legacy application properties placeholder'. Could you give an example here to clarify?

    Thanks,

    - Chris


  41. @Chris,

    I'm using Spring's Log4jConfigurer to manage log4j config. I was about to extend/tweak Log4jWebConfigurer to be able to redirect it to the right configuration according to the profile.
    I'm not sure I understand how you would use @PostContruct, since Log4jConfigurer is configured in the web.xml. Good if you have the time to develop a little bit on this part.

    As for what I called the "legacy application properties placeholder", I mean all the property files that are used directly by the application (without going through Spring) and that contains placeholders that are filtered at runtime somehow.

    A 'classic' placeholder filter system being Maven resource filter.
    It's extremely efficient but it needs to use a Maven profile, which is 'external' to the application. So at deployment time, you need to specify for which profile you want to deploy. This leads to having to one artifact per maven profile.
    And this is extremely counter productive, making the deployment a very tedious and delicate process.

    Being able to deploy only one artifact for all platform is a very very compelling option! And with Spring profile support it's become something much more accessible.
    But since Spring profile doesn't encompass what I call '3rd parties component configuration' and 'legacy properties placeholder', it can only cover half of what's needed to switch from one system to the other (fronm'one artifact per profile' to 'one artifact containing all the profile').


  42. @Jean,

    Feel free to propose any of the above as Improvements via JIRA. It'll be interesting to see what you've done with Log4jWebConfigurer. As regards "legacy application properties", I'm not sure whether there's anything to be done here. I would assume that any such usage would involve hard-coded paths to properties files, and there is little that Spring can do to help here, other than allowing the user to query the Environment object and load different properties files conditionally based on which profiles are active.

    In any case, let's continue such discussions via individual JIRA issues. Thanks.


  43. In Spring 3.1.0.RELEASE – The ability to add profile configuration does NOT work with the DispatcherServlet. It does, however, work for the ContextLoaderListener. See https://jira.springsource.org/browse/SPR-9035

    I also recently posted a blog about Profiles here http://blog.chariotsolutions.com/2012/01/spring-31-cool-new-features.html

    Regards,
    Gordon Dickens

    twitter.com/gdickens
    linkedin.com/in/gordondickens
    Blog: technophile.gordondickens.com


  44. I find myself wanting a this or that profile setup.

    e.g.


    Default profiles don't quite let me do this, as they can't cater for




    I'm wanting this as my users are wanting to be able to choose between very different data sources for a variety of services at start time.

    Is there anything existing that will fill this requirement?

    Cheers,
    Peter


  45. My xml examples got wiped out. Here they are again.

    <beans profile="someProfile">…</beans>
    <beans profile="!someProfile">…</beans>

    and

    <beans profile="someProfile">…</beans>
    <beans profile="!someProfile">…</beans>
    <beans profile="someOtherProfile">…</beans>
    <beans profile="!someOtherProfile">…</beans>


  46. @Peter – please comment/watch/vote on https://jira.springsource.org/browse/SPR-8728

6 trackbacks

Leave a Reply