web-dev-qa-db-fra.com

ResourceBundle introuvable pour MessageSource lorsqu'il est placé dans un dossier

J'essaie d'utiliser des ensembles de ressources avec Message Source de Spring. Voici comment je le fais:

@Component
public class MessageResolver implements MessageSourceAware {

    @Autowired
    private MessageSource messageSource;

    public void setMessageSource(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    public String getMessage(){
        return messageSource.getMessage("user.welcome", new Object[]{"Rama"} , Locale.US);
    }

}

Et voici la structure de mon dossier:

enter image description here

messages_en_US.properties contient une seule ligne:

user.welcome=Welcome {0}

Voici la configuration XML utilisée:

<bean name="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename">
        <value>resourcebundles/messages</value>
    </property>
</bean>

Voici l'erreur que je reçois:

WARNING: ResourceBundle [resourcebundles/messages] not found for MessageSource: Can't find bundle for base name resourcebundles/messages, locale en_US
Exception in thread "main" org.springframework.context.NoSuchMessageException: No message found under code 'user.welcome' for locale 'en_US'.

Mais si je déplace mon regroupement de ressources directement sous le dossier des ressources, cela fonctionne correctement. Dans ce cas, voici la configuration XML que j'utilise:

<bean name="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename">
    <value>messages</value>
</property>

Est-ce que si je dois utiliser ResourceBundleMessageSource, je devrais placer mes ensembles de ressources directement sous les ressources? Si je dois le conserver uniquement dans le dossier spécifié, existe-t-il un autre moyen d'obtenir ce travail?

Merci!

10
Prasanth

Modifiez votre configuration comme suit pour le bean messageSource dans votre fichier xml.

<bean name="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> 
    <property name="basename"> 
        <value>classpath*:resourcebundles/messages</value> 
    </property> 
</bean>

Puisque tous vos fichiers de propriétés sont dans le classpath de Java, vous devez définir le chemin avec le préfixe classpath*:, sinon le répertoire Web de votre application sera examiné.

J'espère que cela vous aide. À votre santé.

11
Japan Trivedi

garçon, peut-être que vous pouvez changer la configuration XML comme suit:

utilisation 

org.springframework.context.support.ReloadableResourceBundleMessageSource

au lieu de

org.springframework.context.support.ResourceBundleMessageSource

toutes les configurations comme ceci:

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:resourcebundles/messages" />
    <property name="useCodeAsDefaultMessage" value="true" />
</bean>
17
jis117

Nous sommes presque en 2015 et j'utilise Spring 4.1.2.RELEASE. Il existe certainement un problème de configuration du bean messageSource afin qu'il récupère le groupe de ressources cible. 

1) Si le bean messageSource est de type ReloadableResourceBundleMessageSource cela ne fonctionnera pas:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;

@Configuration
@ComponentScan(basePackages = { "com.intertech.service" })
//@ImportResource({"classpath:spring/applicationContext-i18n.xml"})
public class AppConfig {

  @Bean(name = "messageSource")
  public ReloadableResourceBundleMessageSource getMessageSource() {
      ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
      messageSource.setBasename("config/messages");
      messageSource.setDefaultEncoding("UTF-8");
      messageSource.setUseCodeAsDefaultMessage(true);
      return messageSource;
  }

//  @Bean(name = "messageSource")
//  public ResourceBundleMessageSource getMessageSource() {
//      ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
//      messageSource.setBasename("config/messages");
//      messageSource.setDefaultEncoding("UTF-8");
//      messageSource.setUseCodeAsDefaultMessage(true);
//      return messageSource;
//  }
}

2) Si le bean messageSource est de type ResourceBundleMessageSource cela fonctionnera:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;

@Configuration
@ComponentScan(basePackages = { "com.intertech.service" })
//@ImportResource({"classpath:spring/applicationContext-i18n.xml"})
public class AppConfig {

//  @Bean(name = "messageSource")
//  public ReloadableResourceBundleMessageSource getMessageSource() {
//      ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
//      messageSource.setBasename("config/messages");
//      messageSource.setDefaultEncoding("UTF-8");
//      messageSource.setUseCodeAsDefaultMessage(true);
//      return messageSource;
//  }

  @Bean(name = "messageSource")
  public ResourceBundleMessageSource getMessageSource() {
      ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
      messageSource.setBasename("config/messages");
      messageSource.setDefaultEncoding("UTF-8");
      messageSource.setUseCodeAsDefaultMessage(true);
      return messageSource;
  }
}

3) Si vous utilisez un fichier de configuration XML associé à une classe de configuration, cela fonctionnera (notez comment le bundle de base est configuré dans une classe telle que la méthode de qualification, par exemple 'config.messages' et non 'config/messages'): -i18n.xml)

<?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:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource"
        p:basename="config.messages"
        p:useCodeAsDefaultMessage="true"/>

    <!-- This will not work -->
    <!--
    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
        p:basename="config/messages"
        p:useCodeAsDefaultMessage="true"/>
     -->
</beans>

et:

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;

@Configuration
@ComponentScan(basePackages = { "com.intertech.service" })
@ImportResource({"classpath:spring/applicationContext-i18n.xml"})
public class AppConfig {

//  @Bean(name = "messageSource")
//  public ReloadableResourceBundleMessageSource getMessageSource() {
//      ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
//      messageSource.setBasename("config/messages");
//      messageSource.setDefaultEncoding("UTF-8");
//      messageSource.setUseCodeAsDefaultMessage(true);
//      return messageSource;
//  }

//  @Bean(name = "messageSource")
//  public ResourceBundleMessageSource getMessageSource() {
//      ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
//      messageSource.setBasename("config/messages");
//      messageSource.setDefaultEncoding("UTF-8");
//      messageSource.setUseCodeAsDefaultMessage(true);
//      return messageSource;
//  }
}

4) Plus important encore ... si vous utilisez un WebApplicationInitializer (no web.xml), vous devez enregistrer la classe de configuration qui définit le bean 'messageSource' dans le contexte racine, pas dans le répartiteur. le contexte de servlet:

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class WebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) throws ServletException {
    // Create the 'root' Spring application context
    AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
    rootContext.register(AppConfig.class);
    // Manage the lifecycle of the root application context
    container.addListener(new ContextLoaderListener(rootContext));
    // Create the dispatcher servlet's Spring application context
    AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
    dispatcherServlet.register(MvcConfig.class);
    // Register and map the dispatcher servlet
    ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(
            dispatcherServlet));
    dispatcher.setLoadOnStartup(1);
    dispatcher.addMapping("*.htm");
    }
}
6
Tom Silverman

Dans mon cas, en utilisant Spring 4.3.2.RELEASE et config Java et un ReloadableResourceBundleMessageSource , je devais définir mon moteur de modèle comme un bean, sinon mes messages ne seraient pas résolus.

Voici un exemple de configuration opérationnelle.

AppConfig.Java

import Java.util.concurrent.TimeUnit;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;

@Configuration
@EnableWebMvc
@ComponentScan("myapp")
public class AppConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware {

private ApplicationContext applicationContext;

private static final boolean CACHE_THYMELEAF_TEMPLATES = false;
private final String UTF8_ENCODING = "UTF-8";

@Override
public void setApplicationContext(ApplicationContext applicationContext) {
    this.applicationContext = applicationContext;
}

@Bean
public ViewResolver viewResolver() {
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setTemplateEngine(templateEngine());
    resolver.setCharacterEncoding(UTF8_ENCODING);
    resolver.setCache(CACHE_THYMELEAF_TEMPLATES);
    return resolver;
}

@Bean
public TemplateEngine templateEngine() {
    //this method must be defined as a bean otherwise i18n messages are not found
    //if method defined as private TemplateEngine templateEngine() messages are not found
    SpringTemplateEngine engine = new SpringTemplateEngine();
    engine.setEnableSpringELCompiler(true);
    engine.addTemplateResolver(templateResolver());
    return engine;
}

private ITemplateResolver templateResolver() {
    SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setApplicationContext(applicationContext);
    resolver.setPrefix("/WEB-INF/thymeleaf/");
    resolver.setTemplateMode(TemplateMode.HTML);
    resolver.setSuffix(".html");
    resolver.setCacheable(CACHE_THYMELEAF_TEMPLATES);
    resolver.setCharacterEncoding(UTF8_ENCODING);
    return resolver;
}   

@Bean
public MessageSource messageSource() {
    ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
    messageSource.setBasenames("WEB-INF/i18n/messages");
    messageSource.setUseCodeAsDefaultMessage(true);
    messageSource.setDefaultEncoding(UTF8_ENCODING);
    messageSource.setFallbackToSystemLocale(false);
    messageSource.setCacheSeconds((int)TimeUnit.HOURS.toSeconds(1));
    return messageSource;
}

}
2
Timothy Anyona

Version YAML pour cette

  spring:
     messages:
       basename: i18n/validation, i18n/message # for multiple properties just use comma separated values
       encoding: UTF-8

Vous pouvez vous référer à documentation pour une description complète.

De plus, je devrais mentionner que le bean MessageSource par défaut est un ResourceBundleMessageSource qui lit déjà un chemin de classe, il n'est donc pas nécessaire d'utiliser une nonation comme classpath:i18n/validation.

Structure du répertoire

 enter image description here

0
Edgar Asatryan
 <!-- Application Message Bundle -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="resourcebundles/messages" />
</bean>

Vous devez configurer le chemin de vos messages comme indiqué ci-dessus . Vérifiez également le nom de la classe.

0
Sachin J

Ce qui a fonctionné pour moi était quelque chose de très simple.

C'était 

<property name="basename">
            <value>locale\messages</value>
        </property>

Je l'ai changé pour

<property name="basename">
            <value>locale/messages</value>
        </property>

Juste un\to/change corrigé pour moi. J'utilise un MAC.

Je n'ai pas essayé *classpath, cela n'a peut-être pas fonctionné pour moi.

0
Siddharth

J'ai utilisé la configuration suivante et cela fonctionne bien dans mon projet . Mes messages.properties se trouvent dans le chemin ci-dessous: ..\WebContent\WEB-INF\resources

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:WEB-INF/resources/messages" />
    <property name="useCodeAsDefaultMessage" value="true" />
</bean>
0
Ganesh Teltia

J'ai utilisé la configuration suivante et cela fonctionne bien

<beans:bean id="messageSource class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <beans:property name="basename" value="classpath:resourcebundles/ScreenLabelResources" />
    </beans:bean>
0
Sanchi Girotra