[BLOSSOM-144] Spring Profiles not supported Created: 10/Oct/13  Updated: 12/Nov/13  Resolved: 12/Nov/13

Status: Closed
Project: Blossom
Component/s: None
Affects Version/s: 3.0
Fix Version/s: None

Type: Bug Priority: Neutral
Reporter: Sigurd Rolfes Assignee: Tobias Mattsson
Resolution: Not an issue Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows 7 professional
Tomcat 7.0.32/JBoss eap 6.1
Spring MVC 3.2.3


Attachments: Zip Archive itr-blossom-test.zip    
Template:
Acceptance criteria:
Empty
Task DoD:
[ ]* Doc/release notes changes? Comment present?
[ ]* Downstream builds green?
[ ]* Solution information and context easily available?
[ ]* Tests
[ ]* FixVersion filled and not yet released
[ ]  Architecture Decision Record (ADR)
Bug DoR:
[ ]* Steps to reproduce, expected, and actual results filled
[ ]* Affected version filled
Date of First Response:

 Description   

When using profiles in Spring the active profile settings seem to get loss in application context initialization.

Application/Servlet context gets initialized in the BlossomModuleSupport class which will be extended by the Mgnl module class.

Usually there are a few ways to set the active profile in Spring (spring.profiles.active):

1. via <context-param> in the web.xml
2. via system property -Dspring.profiles.active=development
3. setting the attribute profiles in the <bean> tag of the context definition
4. by code calling setActiveProfile("development") of Springs ConfigurableEnvironment class

The latter should automatically be called when providing the profile name via system property (VM arg).

We tried system property, context-param and bean xml definition, no success.

If the profile definition is missing several beans are just ignored during instantiation process.

We use xml profile and annotation based profiles, this makes no difference.



 Comments   
Comment by Tobias Mattsson [ 10/Oct/13 ]

I can't reproduce your problem.

I'm using a test bean which looks like this:

public class ProfileTestBean {

    @PostConstruct
    public void init() {
        System.out.println("");
        System.out.println("");
        System.out.println("");
        System.out.println("              YES I AM STARTED");
        System.out.println("");
        System.out.println("");
        System.out.println("");
    }
}

And I add it to the applicationContext.xml like this:

  <context:annotation-config />

  <beans profile="development">

    <bean class="info.magnolia.blossom.sample.module.ProfileTestBean"/>

  </beans>

I get the output when I add this to the web.xml

  <context-param>
    <param-name>spring.profiles.active</param-name>
    <param-value>development</param-value>
  </context-param>

I get the output when starting with -Dspring.profiles.active=development.

And when setting it manually like this:

    public void start(ModuleLifecycleContext moduleLifecycleContext) {
        if (moduleLifecycleContext.getPhase() == ModuleLifecycleContext.PHASE_SYSTEM_STARTUP) {
//            super.initRootWebApplicationContext("classpath:/applicationContext.xml");

            initRootWebApplicationContext(new ContextLoader() {

                @Override
                protected void customizeContext(ServletContext servletContext, ConfigurableWebApplicationContext applicationContext) {

                    applicationContext.getEnvironment().setActiveProfiles("development");
                    applicationContext.setConfigLocations(StringUtils.tokenizeToStringArray("classpath:/applicationContext.xml", ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS));
                }
            });

            // this servlet will pick up the active environments from the parent
            super.initBlossomDispatcherServlet("blossom", "classpath:/blossom-servlet.xml");
        }
    }

I'm not aware of a way to specify the active profile within the beans xml file. As far as I know the profile you specify there is the condition, the profiles for which the beans are active. Could you show me an example?

Spring reads the properties using the PropertySources configured, by default in a web application these include system properties and context init parameters, if you have modified these then maybe that's what's causing the problem.

Comment by Sigurd Rolfes [ 10/Oct/13 ]

Hi Tobias,

your code example is close to what I'm currently trying. I extended the BlossomModuleSupport and try tried to set the profile via ConfigurableEnvironment.

Well, I need it in the servlet context and also tried this:

CustomServletConfig servletConfig = new CustomServletConfig(servletName, getServletContext());
servletConfig.addInitParameter("contextConfigLocation", configLocation);
servletConfig.addInitParameter("spring.profiles.active", "development");

I think I have to reduce complexity and try a simple profile.

Just setting -Dspring.profiles.active=development should already do the job without any further changes?

Spring should automatically recognize and call setActiveProfile() in the context initialisation process.

Sigurd

Comment by Sigurd Rolfes [ 10/Oct/13 ]

and I'll have a look at the PropertySources first.

Comment by Tobias Mattsson [ 10/Oct/13 ]

Yes, this all takes place in org.springframework.core.env.AbstractEnvironment#doGetActiveProfiles. It will first look for it in ServletConfig, then ServletContext, then system properties and finally in system environment variables.

Could you show me the bean definition xml file? Maybe that's where the problem is.

Comment by Sigurd Rolfes [ 10/Oct/13 ]

Tobias,

did you test profiles with the BlossomDispatcherServlet and corresponding component-scan for Blossom?

<context:annotation-config/>
<context:component-scan base-package="de.mypackage" use-default-filters="true">
<context:include-filter type="annotation" expression="info.magnolia.module.blossom.annotation.Template"/>
<context:include-filter type="annotation" expression="info.magnolia.module.blossom.annotation.Area"/>
<context:include-filter type="annotation" expression="info.magnolia.module.blossom.annotation.DialogFactory"/>
<context:include-filter type="annotation" expression="info.magnolia.module.blossom.annotation.VirtualURIMapper"/>
<context:include-filter type="assignable" expression="info.magnolia.cms.beans.config.VirtualURIMapping"/>
</context:component-scan>

Sigurd

Comment by Sigurd Rolfes [ 10/Oct/13 ]

Example for defining the active profile in the bean tag:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:blossom="http://www.magnolia-cms.com/schema/blossom"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.magnolia-cms.com/schema/blossom http://www.magnolia-cms.com/schema/blossom.xsd" profile="development">

Comment by Tobias Mattsson [ 10/Oct/13 ]

Right, so that whole file will only be parsed if the "development" profile is active.

Tried it now with the blossom servlet, works as expected, even tried with the component scan within a <beans profile="development"> and i could switch it on and off using -Dspring.profiles.active=development

Comment by Sigurd Rolfes [ 10/Oct/13 ]

We've got hundreds of classes and most profile settings annotation driven.

I'll reduce complexity and make a simple test.

Comment by Sigurd Rolfes [ 10/Oct/13 ]

ok, I've made a test in a simple mgnl module with annotated classes and beans in the servlet context xml.

Works fine with just specifying -Dspring.profiles.active=development.

I will have a look at the property hint.

Comment by Sigurd Rolfes [ 11/Oct/13 ]

Hi Tobias,

I've got it working now and found very strange behaviour that is related to Spring, I guess. Let me explain.

We've got lots of classes and all annotation driven.

Regarding the problem it's basically this:

public interface MyTestComponent () {}

@Component("testComponent")
@Profile("development")
public class TestA implements MyTestComponent {}

@Component("testComponent")
@Profile("production")
public class TestB implements MyTestComponent {}

@Component("useTestComponent")
public class Test {

@Autowired
public Test(MyTestComponent myTestComponent) {}

}

Application context is empty, servlet context has some classes (webflow configuration etc.), but nothing related to the problem.

When starting up I got an exception "no default constructor found for class Test". For whatever reason Spring tries to use a default constructor, which of course is not there.

Although I would expect an exception like "no bean of type testComponent found" my conclusion was either:

1. component-scan does not work
2. profile does not work

Even a @DependsOn("testComponent") did not work on class Test.

Now the strange thing:

Defining the beans in the servlet context xml works fine:

<bean class="de.itr.Test" id="useTestComponent" >
<constructor-arg ref="myTestComponent" />
</bean>

<beans profile="development">
<bean class="de.itr.TestA" id="myTestComponent" />
</beans>
<beans profile="production">
<bean class="de.itr.TestB" id="myTestComponent" />
</beans>

I already mentioned in an other bug we've got a web application we're trying to integrate via Blossom and standalone this application works fine.

Well, I already noticed that there is some different behaviour when using either Tomcat or JBoss.

My conclusion for now is that there must be a difference between the XMLProcessor and the AnnotationProcessor.
May be the interface, but Spring should be smart enough to recognize myTestComponent should be instantiated first, when coming to the autowired constructor arg.

Just to let you know: when deleting your includes for the Blossom annotations in the component scan: everything still works fine.

Well, I'm sorry to bother you with my problems.

Sigurd

Comment by Tobias Mattsson [ 11/Oct/13 ]

Interesting, could I see the full stack trace for the "no default constructor found for class Test" problem.

Is the test bed you're using something you could share with me?

Comment by Sigurd Rolfes [ 11/Oct/13 ]

find attached my simple test case. Currently I've got the WEB-INF stuff in the webapp module. The other files in a separate module.

I hope I didn't miss anything.

Comment by Sigurd Rolfes [ 11/Oct/13 ]

Tobias,

for the log output: can I send you a private message, it's customer code...

Sigurd

Comment by Sigurd Rolfes [ 11/Oct/13 ]

mmh, I've overseen something. The problematic class is implementing FactoryBean<JavaMailSender> and JavaMailSender is used in the constructor of a service class.

Have to investigate some more details...

Comment by Tobias Mattsson [ 12/Nov/13 ]

Did you find the cause of this problem?

Comment by Sigurd Rolfes [ 12/Nov/13 ]

no, I just moved the problematic classes to xml file. Now it works.

You may close this as profiles work.

Generated at Sun Feb 11 23:30:34 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.