3

Hi I got a simple application and I try to write some integration tests. So I am using springboot in my JUnit Tests and I need slightly different configurations for test-development and production so I work with profiles. My problem now is that the profiles are working perfectly if I deploy my application to a standalone tomcat server. But when starting a JUnit test with springboot the application tries to load ALL profile configurations which results in conflicts

"No qualifying bean of type 'org.springframework.context.MessageSource' available: expected single matching bean but found 2"

As I already said this works on standalone tomcat.

here is a snippet of my code:

this is my testclass

@ActiveProfiles(ProfileConstants.TEST)
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment =     SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {SpringBootInitializer.class})
public class MyTest

then the SpringBootInitializer

@Configuration
@EnableAutoConfiguration
@Import(WebAppConfig.class)
public class SpringBootInitializer extends SpringBootServletInitializer implements ServletContextAware
{

  /**
   * this method will force the embedded tomcat to load the jsf-configuration
   * 
   * @param servletContext the servletcontext of embedded tomcat
   */
  @Override
  public void setServletContext(ServletContext servletContext)
  {
    // sets the spring default initialization profile to test
    servletContext.setInitParameter("spring.profiles.active", ProfileConstants.TEST);
    // will ensure, that the context-initialization is executed. If not set to true the jsf-config will not be
    // loaded
    servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", "true");
    // will initialize jsf-context
    servletContext.addListener(com.sun.faces.config.ConfigureListener.class);
  }

  /**
   * registration of the {@link FacesServlet} with url mappings to .xhtml, .jsf and .faces
   * 
   * @return the ServletRegistrationBean with registered {@link FacesServlet}
   */
  @Bean
  public ServletRegistrationBean facesServletRegistration()
  {
    ServletRegistrationBean registration = new ServletRegistrationBean(new FacesServlet(), "*.xhtml", "*.jsf",
                                                                       "*.faces");
    registration.setLoadOnStartup(1);
    return registration;
  }
}

and at last my WebAppConfig.class

@Configuration
@ComponentScan({"my.component.package"})
@EnableWebMvc
public class WebAppConfig extends WebMvcConfigurerAdapter
{
    ...
    /**
     * spring locale. the resource-bundles will be set here . <br>
     * also the {@link MessageReaderHolder} will be initialized here that holds a static default implementation
     * to read the messages from the resource bundles.
     *
     * @return the resource bundles
     */
    @Profile({ ProfileConstants.PRODUCTION, ProfileConstants.TEST})
    @Bean(name = "messageSource")
    public MessageSource messageSourceProduction()
    {
      ReloadableResourceBundleMessageSource bundleMessageSource = new ReloadableResourceBundleMessageSource();
      bundleMessageSource.setBasenames("classpath:locale");
      MessageReaderHolder.initialize(bundleMessageSource);
      return bundleMessageSource;
    }

    /**
     * spring locale. the resource-bundles will be set here . <br>
     * also the {@link MessageReaderHolder} will be initialized here that holds a static default implementation
     * to read the messages from the resource bundles.
     *
     * @return the resource bundles
     */
    @Profile({ ProfileConstants.DEVELOPMENT})
    @Bean(name = "messageSource")
    public MessageSource messageSourceDevelopment()
    {
      ReloadableResourceBundleMessageSource bundleMessageSource = new ReloadableResourceBundleMessageSource();
      bundleMessageSource.setBasenames("classpath:locale");
      bundleMessageSource.setCacheSeconds(30); 
      MessageReaderHolder.initialize(bundleMessageSource);
      return bundleMessageSource;
    }
}

I would expect only one messageSource to be loaded into the configuration based on the profile I use. Since I am always using only 1 profile the application should not load duplicate beans, but it does.

Why does this happen? I cannot find any clues on this problem...

Goldfish
  • 614
  • 1
  • 7
  • 19
  • Your `WebAppConfig` is component scanning a package. Could the other message source be coming from an un-profile-annotated component/configuration? – nicholas.hauschild May 19 '17 at 15:24
  • Post your startup log - it should show you what messageSource beans have been created. Turn on logging for org.springframework if necessary. By the way, I'd configure my production message source with a profile of just "!" + ProfileConstants.DEVELOPMENT – PaulNUK May 19 '17 at 15:31
  • I already ensured that the duplicate bean is really the one from another profile. This can be perfectly traced with the debugger. So there is no mistaken on this. – Goldfish May 19 '17 at 15:43

0 Answers0