I've my project on github : https://github.com/QuentinVaut/JavaquariumEE
I've follow many tutorial who say different things and I tried to implement the solutions found in tutorials but nothing wrong, I understand why.
Can you tell me what is wrong with my project and explain me ?
One of many tutorials and Github sample :
http://memorynotfound.com/spring-mvc-internationalization-i18n-example/
I had a cursory look over that tutorial. Here is how I would do it:
First Configure it:
Create a Bean in the configuration class that returns the MessageSource
implementation.
#Bean
public MessageSource messageSource() //The bean must be named messageSource.
{
ReloadableResourceBundleMessageSource messageSource =
new ReloadableResourceBundleMessageSource();
messageSource.setCacheSeconds(-1); //cache time in seconds was set to -1. This disables reloading and makes the message source cache messages forever (until the JVM restarts).
messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name());
messageSource.setBasenames(
"/WEB-INF/i18n/messages", "/WEB-INF/i18n/errors"); //the message source is configured with the basenames /WEB-INF/i18n/messages and /WEB-INF/i18n/errors. This means that the message source will look for filenames like /WEB-INF/i18n/messages_en_US.properties, /WEB-INF/i18n/errors_fr_FR.properties
return messageSource;
}
Now create a bean that returns LocaleResolver:
#Bean
public LocaleResolver localeResolver() //The bean must be named localeResolver.
{
return new SessionLocaleResolver();
}
This makes the LocaleResolver available to any code executed by the DispatcherServlet. That means other non-view JSPs do not have access to the LocaleResolver. To take care of this problem, you can create a Filter and set it up like this:
private ServletContext servletContext;
private LocaleResolver = new SessionLocaleResolver();
#Inject MessageSource messageSource;
...
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
request.setAttribute(
DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver
);
JstlUtils.exposeLocalizationContext(
(HttpServletRequest)request, this.messageSource
);
Now you need to configure Handler Interceptors:
You override the addInterceptors method of WebMvcConfigurerAdapter in your configuration class to set up LocaleChangeInterceptor (or any other interceptor for that matter.):
#Override
public void addInterceptors(InterceptorRegistry registry)
{
super.addInterceptors(registry);
registry.addInterceptor(new LocaleChangeInterceptor());
}
Now you can simply use an #Injected LocaleResolver on your controller. You simply call setLocale on the resolver to update the current locale.
Edit: More Specific Example:
Say you have a simple controller that has this:
#RequestMapping(value = "/", method = RequestMethod.GET)
public String index(Map<String, Object> model)
{
model.put("date", new Date());
model.put("alerts", 12);
model.put("numCritical", 0);
model.put("numImportant", 11);
model.put("numTrivial", 1);
return "home/index";
}
Then say you have messages_en_US.properties file under /WEB-INF/i18n/. This properties file contains messages localized for US English.
title.alerts=Server Alerts Page
alerts.current.date=Current Date and Time:
number.alerts=There {0,choice,0#are no alerts|1#is one alert|1
alert.details={0,choice,0#No alerts are|1#One alert is|1<{0,number,integer} > \
alerts are} critical. {1,choice,0#No alerts are|1#One alert is|1<{1,number,\
integer} alerts are} important. {2,choice,0#No alerts are|1#One alert \
is|1<{2,number,integer} alerts are} trivial.
Then, say that you have messages_es_MX.properties file under /WEB-INF/i18n/ and this file contains messages localized for
Mexican Spanish.
title.alerts=Server Alertas Página
alerts.current.date=Fecha y hora actual:
number.alerts={0,choice,0#No hay alertas|1#Hay una alerta|1
alert.details={0,choice,0#No hay alertas son críticos|1#Una alerta es \
crítica|1<{0,number,integer} alertas son críticos}. \
{1,choice,0#No hay alertas son importantes|1#Una alerta es importante\
|1<{1,number,integer} alertas son importantes}. \
{2,choice,0#No hay alertas son triviales|1#Una alerta es trivial\
|1<{2,number,integer} alertas son triviales}.
Now, you need to use <spring:message> tag in your JSP to translate between English and Spanish. This is how your jsp page will look like:
<spring:htmlEscape defaultHtmlEscape="true" />
<%--#elvariable id="date" type="java.util.Date"--%>
<%--#elvariable id="alerts" type="int"--%>
<%--#elvariable id="numCritical" type="int"--%>
<%--#elvariable id="numImportant" type="int"--%>
<%--#elvariable id="numTrivial" type="int"--%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<head>
<title><spring:message code="title.alerts" /></title>
</head>
<body>
<h2><spring:message code="title.alerts" /></h2>
<i><fmt:message key="alerts.current.date">
<fmt:param value="${date}" />
</fmt:message></i><br /><br />
<fmt:message key="number.alerts">
<fmt:param value="${alerts}" />
</fmt:message><c:if test="${alerts > 0}">
<spring:message code="alert.details">
<spring:argument value="${numCritical}" />
<spring:argument value="${numImportant}" />
<spring:argument value="${numTrivial}" />
</spring:message>
</c:if>
</body>
</html>
In my application.properties, I added this line :
spring.messages.basename=i18n/messages
spring.messages.cache-seconds=-1
spring.messages.encoding=UTF-8
You can remove the MessageSource bean with this.
Before I use
<spring:message code="javaquarium.welcome" text="default text" />
But I've thymleaf need this line :
<h1 th:text="#{javaquarium.welcome}"></h1>
Now message from messages.properties show correctly.
Related
I am learning spring Boot framework right now, I am trying to apply i18n concept on my simple application. But whenever I run the application, the following error returned: "No message found under code 'label.welcomeMessage' for locale 'en_US'.". I have read about this issue and tried a lot before I getting here to ask but noting have worked with me.
Here is my AppClass configuration:
package com.abed.main.configuration;
import java.util.Locale;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
#Configuration
public class AppConfig implements WebMvcConfigurer{
#Bean
public LocaleResolver localeResolver()
{
SessionLocaleResolver slr = new SessionLocaleResolver();
slr.setDefaultLocale(Locale.US);
return slr ;
}
#Bean
public LocaleChangeInterceptor LocaleChangeInterceptor()
{
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci ;
}
{
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(LocaleChangeInterceptor());
}
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource msgSrc = new ReloadableResourceBundleMessageSource();
msgSrc.setBasename("classpath:messages/ticket");
msgSrc.setDefaultEncoding("UTF-8");
return msgSrc;
}
}
Here is the welcome JSP:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix = "spring" uri="http://www.springframework.org/tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><spring:message code="label.welcomePageTitle"></spring:message></title>
</head>
<body>
<h1><spring:message code="label.welcomeMessage"></spring:message></h1>
<form action="ticket" method="GET">
<spring:message code="label.ticketId"></spring:message><input type="text" name="Student_Id">
<input type="submit" value="<spring:message code="label.search"></spring:message>">
</form>
<spring:message code="label.createTicketSubmit"></spring:message>
</body>
</html>
and here is the hierarchy of my application:
Any Help Please , Thanks in advance
You need to configuration a bean named messageSource
here is the code, add it to a java code file, make sure #Configuration can be scan:
#Configuration
public class MessageSourceConfig {
#Bean(name = "messageSource")
public ResourceBundleMessageSource getMessageSource() throws Exception {
ResourceBundleMessageSource resourceBundleMessageSource = new ResourceBundleMessageSource();
resourceBundleMessageSource.setDefaultEncoding("UTF-8");
resourceBundleMessageSource.setBasenames("i18n/messages");
return resourceBundleMessageSource;
}
}
The point is : resourceBundleMessageSource.setBasenames("i18n/messages");
remember the base path is classpath, so the i18n properties resource should set in i18n/messages. In order not to crash problem, I suggest you create the properties by using IDEA.
Quote Spring official doc:
Strategy interface for resolving messages, with support for the parameterization and internationalization of such messages.
Spring provides two out-of-the-box implementations for production:
ResourceBundleMessageSource, built on top of the standard ResourceBundle
ReloadableResourceBundleMessageSource, being able to reload message definitions without restarting the VM.
This is the reason we need to configure a bean named messageSource.
I created a simple application using Spring MVC(annotation based) and I am not able to view the results on JSP page. Below is the code which I have written:
In my AppConfig class:
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
in my controller class
#RequestMapping(value = { "/" }, method = RequestMethod.GET)
public String listNonClosedDeployments(ModelMap model) {
//DB operations to get the data
model.addAttribute("testMsg", "deployments are opened");
return "success";
}
My success JSP is:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<%# page isELIgnored="false" %>
</head>
<body>
${testMsg}
</body>
</html>
My output page is:
${testMsg}
Could you please let me know what am I missing here?
Thanks,
Venkat
it is not displaying the value because JSP's Expression Language is disabled by default. You have to enable it manually.
Add the below line to the top of your jsp page:
<%# page isELIgnored="false" %>
I am trying to create a sample Spring MVC project but static file are not getting loaded.I am getting below mentioned error.
http://localhost:8080/BPMEI/static/css/bootstrap.css Failed to load resource: the server responded with a status of 404 (Not Found)
I will be grateful if someone can help me out to fix this issue.
Project Structure
Configuration Code
package com.dgsl.bpm.configuration;
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.dgsl.bpm")
public class WebConfiguration extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/");
}
}
Initializer code
package com.dgsl.bpm.configuration;
public class WebInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(WebConfiguration.class);
ctx.setServletContext(container);
ServletRegistration.Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
}
}
JSP Code
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Student Enrollment Form</title>
<link href="<c:url value='/static/css/bootstrap.css' />" rel="stylesheet"></link>
</head>
<body>
To F2:if you let it download itself instead of me downloading css files and telling Spring where they are,you must let the js files or somethings publish to the web which is not controlled by yourself.The building-owner’s purpose is how to load the static file in a Spring MVC project.I think the problem is on the code of addResourceLocations,it should be addResourceLocations ("classpath:/static/");
may be you made a wrong mapping.
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
this code should works, i tested it on my local machine.
addResourceLocations("/static/") the last slash is mandatory
in sping-core-4.2.5-release.jar StringUtils.java has the following code
public static String applyRelativePath(String path, String relativePath) {
int separatorIndex = path.lastIndexOf(FOLDER_SEPARATOR);
if (separatorIndex != -1) {
String newPath = path.substring(0, separatorIndex);
if (!relativePath.startsWith(FOLDER_SEPARATOR)) {
newPath += FOLDER_SEPARATOR;
}
return newPath + relativePath;
}
else {
return relativePath;
}
}
if not end with a slash, this method will return relativePath
FYI, when i view your attached picture, i found "bootstrap.min.css" in your project. don't forget to use right file name. i wish my suggestion can help you
change addResourceHandlers like
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("/");
}
and also change css file name 'bootstrap.min.css'
Change your addResourceHandlers definition like below and try:-
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
Please use the context path in your url:
<c:url value='${pageContext.request.contextPath}/static/css/bootstrap.css' />
This will give you the url value:
BPMEI/static/css/bootstrap.css
Let me know if that works.
Why JSP don't convert into HTML? so, I don't know what to show you
#Bean
public UrlBasedViewResolver urlBasedViewResolver(){
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/WEB-INF/views/**").addResourceLocations("/WEB-INF/views/");
}
One of my JSPs...
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Edit word</title>
</head>
<body>
<form action="edit" method="post">
<input name="id" type="hidden" value="${id}">
<input type="submit">
</form>
</body>
</html>
...
#RequestMapping(value = "/words/edit",method = RequestMethod.GET)
public String editWord(Model model, #RequestParam(required = false) String userID){
model.addAttribute("words",wordService.getAll());
return "/words/edit";
}
Displays as just opened JSP in browser:
I believe that using a UrlBasedViewResolver will only redirect to the file but a JSP need to be parse/compile.
The doc of Spring tell you that there is InternalResourceViewResolver and InternalResourceView that internally forward the jsp file. This will parse the file as you need.
For view technologies such as JSPs that are processed through the
Servlet or JSP engine, this resolution is usually handled through the
combination of InternalResourceViewResolver and InternalResourceView,
which issues an internal forward or include via the Servlet API’s
RequestDispatcher.forward(..) method or RequestDispatcher.include()
method.
Source :
http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/mvc.html#mvc-redirecting
Please return "words/edit" instead of "/words/edit". You have already set resolver.setPrefix("/WEB-INF/views/"); returning ""/words/edit" results in "//words/edit" .
I'm currently using Spring MVC 4 for developing a new web application.
I have four files named: header.jsp, menu.jsp, default.jsp and footer.jsp, they are basically the template of my webapp.
So, my default.jsp is the default template for every other page in my application, and it's basically like this:
...
<jsp:include page="header.jsp" />
<jsp:include page="menu.jsp">
<body>
Contents goes here
</body>
<jsp:include page="footer.jsp">
...
The Controller:
...
#RequestMapping("/")
public ModelAndView index() {
return new ModelAndView("default");
}
...
What i want to accomplish is make a java class that can handle header.jsp, one that can handle menu.jsp and so on... Since they will be dynamic pages and their content will change.
I know that i can use java code inside JSP, but that is what i don't wanna do.
Example of what i would like to do:
public class menu {
//this class handles menu.jsp
public List menuItems() {
ArrayList menuItems = new ArrayList();
menuItems.add("Home");
menuItems.add("Contact");
return menuItems;
}
}
And inside menu.jsp:
<%# codebehind="menu.java" %>
<ul>
<li> ${item[0]} </li> <!-- would output 'Home' -->
<li> ${item[1]} </li> <!-- would output 'Contact' -->
</ul>
Is that possible?
Yes that is possible, you just have to add model on your ModelAndView.
"menuItem" - will be name of your model.
"menu.menuItems()" - is your modelObject.
Controller
#RequestMapping("/")
public ModelAndView index() {
Menu menu = new Menu();
return new ModelAndView("default", "menuItems", menu.menuItems());
}
Menu
public class Menu {
//this class handles menu.jsp
public List menuItems() {
ArrayList menuItems = new ArrayList();
menuItems.add("Home");
menuItems.add("Contact");
return menuItems;
}
}
Rather than scriptlets, use jstl.
<%# codebehind="menu.java" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<ul>
<c:forEach var="menu" value="${menuItem}">
<li><c:out value="${menu}"/></li>
</c:forEach>
</ul>
Also I would recommend you to use Apache Tiles with spring for better template framework.