I'm trying to implement what Bryan Hansen taught in his spring mvc video serie for internationalization; I'm writing the same code as e does but mine does not work properly and I'm getting the following error message :
No message found under code 'student.name' for locale 'en_US'
my startup class is as follow :
public class Startup implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
//get the context :
WebApplicationContext context = this.getContext();
//creates a listener :
ContextLoaderListener listener = new ContextLoaderListener(context);
servletContext.addListener(listener);
//register as servlet :
ServletRegistration.Dynamic dispatcherServlet = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
dispatcherServlet.setLoadOnStartup(1);
dispatcherServlet.addMapping("/");
}
private WebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(WebConfig.class);
return context;
}
}
and my web config class is as follow :
#Configuration
#ComponentScan(basePackages = "ga.shahab.controllers")
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry resource) {
resource.addResourceHandler("/res/**").addResourceLocations("/resources/");
resource.addResourceHandler("/app/*.js").addResourceLocations("/resources/app/");
}
// START : Internationalization I18n
#Bean
public MessageSource MessageSource() {
// ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Bean
public LocaleResolver localResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.ENGLISH);
return localeResolver;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor changeInterceptor = new LocaleChangeInterceptor();
changeInterceptor.setParamName("language");
registry.addInterceptor(changeInterceptor);
}
// END : Internationalization I18n
#Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/Views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
I'm using spring messages like this :
<spring:message code="student.name"></spring:message>
and the structure of my project is as follow :
1.src/main/java
2.src/main/resources
my internationalization files are in the second folder( resources )
and finally my messages file includes just one line of code :
student.name=Name
but my project does not work for internationalization.
what's wrong with my sample ?!
Related
I'm trying to pass some information from a browser to my server and end up having '????' symbols. I thoroughly searched for this problem on the Internet and StackOverFlow but in the end nothing helped me. My assumption is Thymeleaf/Spring continues to use ISO_8859_1 charset instead of UTF-8.
DispatcherServlet(CharacterEncodingFilter):
public class DispatcherServlet extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
public void onStartup(ServletContext aServletContext) throws ServletException {
super.onStartup(aServletContext);
registerCharacterEncodingFilter(aServletContext);
registerHiddenFieldFilter(aServletContext);
}
private void registerHiddenFieldFilter(ServletContext aContext) {
aContext.addFilter("hiddenHttpMethodFilter",
new HiddenHttpMethodFilter()).addMappingForUrlPatterns(null, true, "/*");
}
private void registerCharacterEncodingFilter(ServletContext aContext) {
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST,
DispatcherType.FORWARD);
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
FilterRegistration.Dynamic characterEncoding = aContext.addFilter("characterEncoding",
characterEncodingFilter);
characterEncoding.addMappingForUrlPatterns(dispatcherTypes, true, "/*");
}
}
My Configuration:
public class ApplicationConfiguration implements WebMvcConfigurer {
private final ApplicationContext applicationContext;
private final Environment environment;
#Autowired
public ApplicationConfiguration(ApplicationContext applicationContext,
Environment environment) {
this.applicationContext = applicationContext;
this.environment = environment;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry resourceHandlerRegistry) {
resourceHandlerRegistry.addResourceHandler("/resources/**").
addResourceLocations("/resources/");
}
// Themyleaf resolver,engine etc
#Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/WEB-INF/view/");
resolver.setSuffix(".html");
resolver.setCharacterEncoding("UTF-8");
resolver.setTemplateMode("HTML5");
return resolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
engine.addDialect(new SpringSecurityDialect());
engine.setEnableSpringELCompiler(true);
return engine;
}
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setContentType("text/html; charset=UTF-8");
resolver.setCharacterEncoding("UTF-8");
registry.viewResolver(resolver);
}
}
As I've already said, I'm trying to make Spring/Thymeleaf use UTF-8 charset instead of the standard one. Certainly I could use something like
byte[] bytes = content.getBytes(StandardCharsets.ISO_8859_1);
content = new String(bytes, StandardCharsets.UTF_8);
but I'd like to have it done by Spring/Thymeleaf if it's possible.
UPD: Whatever the input data is I always see '???' in the console. For instance: 'Текстовая строка123' produces '???µ???????????°?? ???????????°123' (except for Non Cyrillic symbols)
I using Spring 5. Have problems with encoding, like this:
ÐÐµÑ Ñакого бÑенда: 1000. ÐожалÑйÑÑа, пÑовеÑÑÑе запÑоÑ.
I tried to fix encoding this way:
#Configuration
public class AppInit extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
addEncodingFilter(servletContext);
super.onStartup(servletContext);
}
...
private void addEncodingFilter(ServletContext servletContext) {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
EnumSet<DispatcherType> dispatcherTypes
= EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ERROR);
FilterRegistration.Dynamic characterEncoding
= servletContext.addFilter("characterEncoding", characterEncodingFilter);
characterEncoding.addMappingForUrlPatterns(dispatcherTypes, true, "/*");
characterEncoding.setAsyncSupported(true);
}
}
but have no result. Please, give me ready solution how to set encoding for Spring 5.
Try using spring Beans.
#Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
encodingFilter.setForceEncoding(true);
registrationBean.setFilter(encodingFilter);
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
Solution was:
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
source.setBasename("i18n/messages");
source.setDefaultEncoding("UTF-8");
return source;
}
I needed simply to set default encoding for i18n files.
I want to post http://localhost:8080/TestSpringMVCAndStuff/hi/zzz?input=abcdef&crap=1234567 to a /hi/* address.
However, I keep getting 404 error.
Is there a way to make this work?
WebAppInitializer
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(WebAppConfiguration.class);
ctx.setServletContext(container);
{
ServletRegistration.Dynamic servlet = container.addServlet(
"dispatcherHi", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/hi/*");
}
}
}
AnotherController
#Controller
#RequestMapping("/hi/*")
public class AnotherController {
#Autowired(required=false)
#RequestMapping(method = RequestMethod.POST)
public void processRequest(HttpServletRequest request, HttpServletResponse response) {
try{
response.getOutputStream().write("hello world!".getBytes());
}
catch(Exception e){
e.printStackTrace();
}
}
}
WebAppConfiguration
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.test.springmvc")
public class WebAppConfiguration extends WebMvcConfigurerAdapter {
/*
* Configure View Resolver
*/
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
/*
* Configure MessageSource to provide internationalized messages
*
*/
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
/*
* Configure ResourceHandlers to serve static resources like CSS/ Javascript etc...
*
*/
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
}
}
In this Context Initializer servlet mapping is /hi/* so each and every request to the server will be like http://localhost:8080/TestSpringMVCAndStuff/hi
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(WebAppConfiguration.class);
ctx.setServletContext(container);
{
ServletRegistration.Dynamic servlet = container.addServlet(
"dispatcherHi", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/hi/*");
}
}
}
so that there is no need of #RequestMapping("/hi/*") this because /hi is already appended in context path so after hi/ only need a request Mapping #RequestMapping( value="/zzz")
#Controller
#RequestMapping("/**")
public class AnotherController {
#RequestMapping(value="/zzz",method = RequestMethod.POST)
#ResponseBody
public String processRequest(HttpServletRequest request, HttpServletResponse response) {
String result="";
try{
result="hello world";
}
catch(Exception e){
e.printStackTrace();
}
return result;
}
}
inCase he change servlet Mapping like this means servlet.addMapping("/") he should Map Request for /hi in Controller and futher request also
I'm trying to develop a spring MVC project which has a index.jsp file as it's view. I searched and found I should do this by the help of two below configuration classes:
public class MainInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
public static HashMap<String, String> response_code = new HashMap<String, String>();
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { MainConfiguration.class,
WebSocketConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
Security.addProvider(new BouncyCastleProvider());
servletContext.addListener(new MainContextListener());
}
}
and this is MainConfiguration class:
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = "-----")
public class MainConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/Content/**")
.addResourceLocations("/Content/");
registry.addResourceHandler("/Scripts/**")
.addResourceLocations("/Scripts/");
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver
= new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
I've configured my project to run on tomcat web-server inside intellij. but when index.jsp is directly in path : webapp/index.jsp it will be opened in browser after running the program but when I move it to a subfolder it doesn't.
Shouldn't this part of code give the address to spring so it find the url and don't give a 404 error?
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
You need to annotate your MainConfiguration.java with #Configuration. Also, you require to register an instance of the DispatcherServlet in the servlet context. Actually, you can refer - spring mvc with jsp example for detailed configurations.
I have a web application on Tomcat 7.0.34, Spring 3.2.3, Spring Security 3.2.0.RC1 and Spring Social 1.1.
For some reason the Spring context is being loaded twice. The second load is happening immediately after the first load has finished. The log below shows the Context Loader loading the Root WebApplicationContext. Everything progresses normally and all the RequstMappingHandlers are registering correctly. Then immediately the context is refreshed again.
I've read several solutions on SO about ensuring you don't load the configuration as part of the Context Loader and the DispatcherServlet at the same time and have tested various combinations of this but that doesn't seem to have fixed it and I'm becoming code blind as well.
All my testing on this has pushed me to an annotation only configuration both for the container and Spring components but the config classes are pretty much copy and paste from the Spring Social examples on github. Although I've included the SocialConfig.java details below, this problem has been happening before I implemented Spring Social but I can't move on without fixing it.
Also, the problem was present with a hybrid xml (web.xml, security-app-context.xml) and annotation configuration.
I'm implementing WebApplicationInitializer rather than having a web.xml
public class WebClientInitialiser implements WebApplicationInitializer {
public void onStartup(ServletContext container) throws ServletException {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
// Manage the lifecycle of the root application context
appContext.setConfigLocation("com.mycompany.webclient.config");
appContext.setServletContext(container);
container.addListener(new ContextLoaderListener(appContext));
container.addListener(new MyCompanyContextListener());
container.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, false, "/*");
// Register and map the dispatcher servlet
Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(appContext));
dispatcher.addMapping("/");
dispatcher.setLoadOnStartup(1);
}
}
My MainConfig.java
/**
* Main configuration class for the application.
* Turns on #Component scanning, loads externalized application properties
* and imports legacy security configuration
*/
#Configuration
#ComponentScan(basePackages = "com.mycompany.webclient", excludeFilters = { #Filter(Configuration.class) })
#PropertySource("classpath:wc.properties")
#ImportResource("/WEB-INF/spring/appServlet/security-app-context.xml")
public class MainConfig {
#Bean
public PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
My WebMvcConfig.java
#Configuration
#EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("/WEB-INF/messages/messages");
return messageSource;
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
My SocialConfig.java
#Configuration
#EnableSocial
public class SocialConfig implements SocialConfigurer {
private SocialUserDAO socialUserDao;
//
// SocialConfigurer implementation methods
//
#Override
public void addConnectionFactories(ConnectionFactoryConfigurer cfConfig, Environment env) {
String clientId="XXXXXX";
String clientSecret="XXXXX";
cfConfig.addConnectionFactory(new FacebookConnectionFactory(clientId, clientSecret));
}
#Override
public UserIdSource getUserIdSource() {
return new UserIdSource() {
#Override
public String getUserId() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
throw new IllegalStateException("Unable to get a ConnectionRepository: no user signed in");
}
return authentication.getName();
}
};
}
#Override
public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
return new HibernateUsersConnectionRepository(socialUserDao, connectionFactoryLocator, Encryptors.noOpText());
}
//
// API Binding Beans
//
#Bean
#Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public Facebook facebook(ConnectionRepository repository) {
Connection<Facebook> connection = repository.findPrimaryConnection(Facebook.class);
return connection != null ? connection.getApi() : null;
}
#Bean
#Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public Twitter twitter(ConnectionRepository repository) {
Connection<Twitter> connection = repository.findPrimaryConnection(Twitter.class);
return connection != null ? connection.getApi() : null;
}
#Bean
#Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
public LinkedIn linkedin(ConnectionRepository repository) {
Connection<LinkedIn> connection = repository.findPrimaryConnection(LinkedIn.class);
return connection != null ? connection.getApi() : null;
}
//
// Web Controller and Filter Beans
//
#Bean
public ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator, ConnectionRepository connectionRepository) {
ConnectController connectController = new ConnectController(connectionFactoryLocator, connectionRepository);
connectController.addInterceptor(new PostToWallAfterConnectInterceptor());
connectController.addInterceptor(new TweetAfterConnectInterceptor());
return connectController;
}
#Bean
public ProviderSignInController providerSignInController(ConnectionFactoryLocator connectionFactoryLocator, UsersConnectionRepository usersConnectionRepository) {
return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new SimpleSignInAdapter(new HttpSessionRequestCache()));
}
#Bean
public DisconnectController disconnectController(UsersConnectionRepository usersConnectionRepository, Environment env) {
return new DisconnectController(usersConnectionRepository, env.getProperty("facebook.clientSecret"));
}
#Bean
public ReconnectFilter apiExceptionHandler(UsersConnectionRepository usersConnectionRepository, UserIdSource userIdSource) {
return new ReconnectFilter(usersConnectionRepository, userIdSource);
}
}
Any help, comments, pointers is greatly appreciated.
This log output is repeated twice at the start of each context refresh:
org.springframework.web.context.ContextLoader- Root WebApplicationContext: initialization started
org.springframework.web.context.support.AnnotationConfigWebApplicationContext- Refreshing Root WebApplicationContext: startup date [Mon Nov 25 22:43:39 GMT 2013]; root of context hierarchy
org.springframework.context.annotation.ClassPathBeanDefinitionScanner- JSR-330 'javax.inject.Named' annotation found and supported for component scanning
org.springframework.web.context.support.AnnotationConfigWebApplicationContext- Registering annotated classes: [class com.mycompany.webclient.config.WebMvcConfig,class com.mycompany.webclient.config.SocialConfig]
You are passing the same context to both the ContextLoaderListener and DispatcherServlet and hence this will trigger loading the configuration twice.
You should have 2 seperate AnnotationConfigWebApplicationContext instances one for the ContextLoaderListener loading all your generic beans (services etc.) and one for the DispatcherServlet loading the web related things.
public class WebClientInitialiser implements WebApplicationInitializer {
public void onStartup(ServletContext container) throws ServletException {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(MainConfig.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
container.addListener(new MyCompanyContextListener());
container.addFilter("springSecurityFilterChain", new DelegatingFilterProxy("springSecurityFilterChain"))
.addMappingForUrlPatterns(null, false, "/*");
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(WebMvcConfig.class, SocialConfig.class);
// Register and map the dispatcher servlet
Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.addMapping("/");
dispatcher.setLoadOnStartup(1);
}
}
Something like this. Also you don't need to set the contextConfigLocation simply register the #Configuration annotated classes. Also setting the ServletContext is already done by Spring so no need for that to.
A note on your configuration, the PropertySourcesPlaceHolderConfigurer is enabled by default so no need to register that again in in MainConfig class.
Another thing to take into account is that now probably your application fails (i.e. your #Controllers don't work anymore). This is due to the fact that everything is inside the root application context whereas #Controllers should be loaded by the DispatcherServlet. To fix this you need to exclude #Controller scanning in your MainConfig and enable #Controller scanning on the WebMvcConfig class.