I'm studying Spring 3 and im trying to validate a form using the class org.hibernate.validator.constraints.NotEmpty.
Im able, for instance, to override the #Size message (javax.validation.constraints.Size) and the #Email message (org.hibernate.validator.constraints.Email) retrieving the messages from a .properties file.
But im not able to override the org.hibernate.validator.constraints.NotEmpty default message. I always get the default message "may not be empty"
this is my XXXX-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<mvc:annotation-driven/>
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
</mvc:interceptors>
<context:component-scan base-package="com.springgestioneerrori.controller" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
<property name="defaultEncoding" value="UTF-8"/>
</bean>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" >
<property name="defaultLocale" value="en"/>
</bean>
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<ref bean="localeChangeInterceptor" />
</property>
</bean>
</beans>
This is my User class
package com.springgestioneerrori.model;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;
public class Utente {
#NotEmpty
#Size(min=3,max=20)
private String nome;
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
This is my form
.......
<form:form action="formSent" method="post" commandName="utente">
<form:errors path="*" cssClass="errorblock" element="div" /><br/><br/>
<spring:message code="form.label.utente.nome"/><form:input path="nome"/><form:errors path="nome" cssClass="error" /><br>
<input type="submit">
</form:form>
......
this is my controlller
........
#RequestMapping("/formSent")
public String formSent(Model model, #Valid Utente utente, BindingResult result){
if(result.hasErrors()){
model.addAttribute("utente", utente);
return "form";
}
else{
model.addAttribute("msg", "inserimento effettuato con successo");
return "formSent";
}
}
.........
this is my propertis file
NotEmpy.utente.nome = il campo nome non può essere vuoto //Im NOT able to get this message
Size.utente.nome = Il nome deve contenere tra 2 e 30 lettere //Im able to get this message
You have to create a file ValidationMessages.properties and place it in the classpath of your application. The Hibernate validator use the org.hibernate.validator.constraints.NotEmpty.message key to translate the message
org.hibernate.validator.constraints.NotEmpty.message=il campo nome non può essere vuoto
Have a look here for further information:
http://docs.jboss.org/hibernate/validator/4.3/reference/en-US/html/validator-usingvalidator.html#section-message-interpolation
UPDATE
For customizing a single message use something like this:
#NotEmpty( message = "{NotEmpy.utente.nome}" )
#Size(min=3,max=20, message = "{Size.utente.nome}")
private String nome;
Try this -
#NotEmpty( message = "{NotEmpy.utente.nome}" )
private String nome;
Thank for your help. I made a very stupid error. Inside the properties file i wrote NotEmpy instead of NotEmpty. Sorry for waisting you time :)
Related
I wrote the below code inorder to implement Spring Exception handling. When I run the code it needs to throw an error at the below line and the corresponding exception handler should execute. But, it is not executing. May I know what is wrong in my code. Thanks in advance
throw new SpringException("Error", retStatus);
Code:
#Controller
public class RestController {
#ExceptionHandler(SpringException.class)
public String handleCustomException(SpringException ex) {
String jsonInString = "{}";
JSONObject json = new JSONObject();
Map<String,String> errorMap = new HashMap<String,String>();
errorMap.put("errorMessage",ex.getMessage());
System.out.println("Inside exception handler");
json.putAll(errorMap);
jsonInString = json.toJSONString();
logger.info(jsonInString);
return jsonInString;
}
#RequestMapping(value = "/v1/dist_list/{emailId}/members", method = RequestMethod.GET)
public #ResponseBody String getDistributionListMember(#PathVariable String emailId) throws Exception, SpringException {
String retStatus = null;
retStatus = dataServices.getDistributionListMember(emailId, callerId);
if (!retStatus.isEmpty()) {
if (retStatus.contains("callerid is not valid")) {
throw new SpringException("Error", retStatus);
}
}
}
SpringException class
package com.uniteid.model;
import org.springframework.http.HttpStatus;
public class SpringException extends RuntimeException {
private static final long serialVersionUID = 1L;
private String errCode;
private String errMsg;
public String getErrCode() {
return errCode;
}
public void setErrCode(String errCode) {
this.errCode = errCode;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public SpringException(String errCode, String errMsg) {
this.errCode = errCode;
this.errMsg = errMsg;
}
}
Below is my Spring-config.xml file
<?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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<context:component-scan base-package="com.uniteid.controller" />
<mvc:annotation-driven
content-negotiation-manager="contentNegociationManager" />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:uniteidrest.properties" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url">
<value>${eidms.url}</value>
</property>
<property name="username">
<value>${eidms.username}</value>
</property>
<property name="password">
<value>${eidms.password}</value>
</property>
</bean>
<!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"
/> <property name="url" value="jdbc:oracle:thin:#un.org:1521:EIDMSUAT"
/> <property name="username" value="EIDMSUAT" /> <property name="password"
value="NewPass" /> </bean> -->
<bean id="contentNegociationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="defaultContentType" value="application/json" />
<property name="ignoreAcceptHeader" value="true" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.uniteid.model.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.connection.pool_size">10</prop>
</props>
</property>
</bean>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean class = "org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name = "exceptionMappings">
<props>
<prop key = "com.uniteid.model.SpringException">
ExceptionPage
</prop>
</props>
</property>
<property name = "defaultErrorView" value = "error"/>
</bean>
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean id="dataDao" class="com.uniteid.dao.DataDaoImpl"></bean>
<bean id="dataServices" class="com.uniteid.services.DataServicesImpl"></bean>
</beans>
I get the below error in the console at this line of the code
throw new SpringException("Error", retStatus);
2017-06-01 12:52:58 DEBUG DispatcherServlet:1175 - Handler execution resulted in exception - forwarding to resolved error view: ModelAndView: reference to view with name '{"errorMessage":null}'; model is {}
com.uniteid.model.SpringException
at com.uniteid.controller.RestController.getDistributionListMember(RestController.java:)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
I am trying to define the transaction in my spring mvc project but having problem:
// xml file
<?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:p=
"http://www.springframework.org/schema/p"
xmlns:tx=
"http://www.springframework.org/schema/tx"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- Enable Annotation based Declarative Transaction Management -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Creating TransactionManager Bean, since JDBC we are creating of type DataSourceTransactionManager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Initialization for data source -->
<bean id="dataSource" class= "org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost/bhaiyag_devgrocery"></property>
<property name="username" value="newuser"></property>
<property name="password" value="kim"></property>
</bean>
<bean id="CategoriesDaoImpl" class="org.kmsg.dao.daoImpl.CategoriesDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="CityDaoImpl" class="org.kmsg.dao.daoImpl.CityDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="CustomerDaoImpl" class="org.kmsg.dao.daoImpl.CustomerDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
// This is class where i want to apply the transaction
public class CustomerOrderAdapter
{
public void displayCustomerOrder(String mobileNo)
{ }
#Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = true)
public Map<String, Object> createCustomerOrderData(SalesCommandObject salesCommandObject,long OrderForDelete) throws Exception
{
Map <String, Object> data = new HashMap<String, Object>();
try
{
salesDaoImpl.deleteSalesitems(OrderNo);
salesDaoImpl.deleteSales(OrderNo);
salesDaoImpl.insertSalesItems(updatedOn,OrderNo,CustmobileNo);
salesDaoImpl.insertSales(totalSale, SlotNo, OrderNo);
}
catch(IndexOutOfBoundsException ex)
{
System.out.println("No Record to Save");
data.put("status", "No Record to Save");
}
catch(Exception e)
{
System.out.println(e.toString());
data.put("status", e);
}
data.put("status", "Purchase Successfull");
return data;
}
}
// Help me and suggest , How to implement transaction;
I am importing a spring xml configuration file from another project using import resource. The resource is apparently found since there is no error message saying it isn't, but none of the beans get loaded. Is there something I'm doing wrong here? I should note that when I run my integration tests from within eclipse it all works fine, but it blows up when running the same integration test from within a maven build.
applicationContext.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<import resource="classpath*:httpclient-4x.xml" />
<context:component-scan base-package="com.mycompany.data" />
<bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:properties/client.${deployment.env}.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="false" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="searchSystemEnvironment" value="true" />
</bean>
<bean id="jacksonObjectMapper" class="com.fasterxml.jackson.databind.ObjectMapper" />
</beans>
httpclient-4x.xml
<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:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="secureRestTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg>
<ref bean="secureClientHttpRequestFactory" />
</constructor-arg>
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<util:constant static-field="org.springframework.http.MediaType.APPLICATION_XML" />
<util:constant static-field="org.springframework.http.MediaType.APPLICATION_JSON" />
<util:constant static-field="org.springframework.http.MediaType.TEXT_PLAIN" />
</list>
</property>
</bean>
<bean class="org.springframework.http.converter.FormHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<util:constant static-field="org.springframework.http.MediaType.MULTIPART_FORM_DATA" />
</list>
</property>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</list>
</property>
</bean>
<bean id="secureClientHttpRequestFactory" class="com.cobalt.inventory.security.PreemptiveBasicAuthClientHttpRequestFactory">
<constructor-arg>
<ref bean="secureCloseableHttpClient" />
</constructor-arg>
</bean>
<bean id="secureCloseableHttpClient" factory-bean="secureHttpClientBuilder" factory-method="build" />
<bean id="secureHttpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder" factory-method="create">
<property name="defaultCredentialsProvider" ref="credentialsProvider" />
<property name="defaultSocketConfig" ref="socketConfig" />
<property name="defaultRequestConfig" ref="requestConfig" />
<property name="userAgent" value="${http.user.agent: CDK Cobalt invJava}" />
<property name="maxConnPerRoute" value="${http.max.connections.per.route:100}" />
<property name="maxConnTotal" value="${http.max.connections:100}" />
</bean>
<bean id="credentialsProvider" class="org.apache.http.impl.client.BasicCredentialsProvider" />
<bean id="credentials" class="org.apache.http.auth.UsernamePasswordCredentials">
<constructor-arg index="0" name="userName" value="validUsername" />
<constructor-arg index="1" name="password" value="validPassword" />
</bean>
<bean id="socketConfigBuilder" class="org.apache.http.config.SocketConfig.Builder">
<property name="soKeepAlive" value="true" />
<property name="soTimeout" value="${http.socket.timeout:10000}" />
</bean>
<bean id="socketConfig" factory-bean="socketConfigBuilder" factory-method="build" />
<bean id="requestConfigBuilder" class="org.apache.http.client.config.RequestConfig.Builder">
<property name="connectTimeout" value="${http.connection.timeout:10000}" />
<property name="socketTimeout" value="${http.socket.timeout:10000}" />
<property name="cookieSpec">
<util:constant static-field="org.apache.http.client.config.CookieSpecs.IGNORE_COOKIES" />
</property>
</bean>
<bean id="requestConfig" factory-bean="requestConfigBuilder" factory-method="build" />
<!-- For accessing common authorization service -->
<bean id="commonAuthzSecureRestTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg>
<ref bean="commonAuthzSecureClientHttpRequestFactory" />
</constructor-arg>
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<util:constant static-field="org.springframework.http.MediaType.APPLICATION_XML" />
<util:constant static-field="org.springframework.http.MediaType.APPLICATION_JSON" />
<util:constant static-field="org.springframework.http.MediaType.TEXT_PLAIN" />
</list>
</property>
</bean>
<bean class="org.springframework.http.converter.FormHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<util:constant static-field="org.springframework.http.MediaType.MULTIPART_FORM_DATA" />
</list>
</property>
</bean>
<bean id="jsonMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter ">
<property name="supportedMediaTypes">
<list>
<bean id="jsonMediaTypeApplicationJson" class="org.springframework.http.MediaType">
<constructor-arg value="application" />
<constructor-arg value="json" />
</bean>
</list>
</property>
</bean>
</list>
</property>
</bean>
<bean id="commonAuthzSecureClientHttpRequestFactory" class="com.mycompany.security.PreemptiveBasicAuthClientHttpRequestFactory">
<constructor-arg>
<ref bean="commonAuthzSecureCloseableHttpClient" />
</constructor-arg>
</bean>
<bean id="commonAuthzSecureCloseableHttpClient" factory-bean="commonAuthzSecureHttpClientBuilder" factory-method="build" />
<bean id="commonAuthzSecureHttpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder" factory-method="create">
<property name="defaultCredentialsProvider" ref="commonAuthzCredentialsProvider" />
<property name="defaultSocketConfig" ref="commonAuthzSocketConfig" />
<property name="defaultRequestConfig" ref="commonAuthzRequestConfig" />
<property name="userAgent" value="${http.user.agent: userAgent}" />
<property name="maxConnPerRoute" value="${http.max.connections.per.route:100}" />
<property name="maxConnTotal" value="${http.max.connections:100}" />
</bean>
<bean id="commonAuthzCredentialsProvider" class="org.apache.http.impl.client.BasicCredentialsProvider" />
<bean id="commonAuthzCredentials" class="org.apache.http.auth.UsernamePasswordCredentials">
<constructor-arg index="0" name="userName" value="${common_services.iam.remoting.user:user" />
<constructor-arg index="1" name="password" value="${common_services.iam.remoting.password:password}" />
</bean>
<bean id="commonAuthzSocketConfigBuilder" class="org.apache.http.config.SocketConfig.Builder">
<property name="soKeepAlive" value="true" />
<property name="soTimeout" value="${http.socket.timeout:10000}" />
</bean>
<bean id="commonAuthzSocketConfig" factory-bean="commonAuthzSocketConfigBuilder" factory-method="build" />
<bean id="commonAuthzRequestConfigBuilder" class="org.apache.http.client.config.RequestConfig.Builder">
<property name="connectTimeout" value="${http.connection.timeout:10000}" />
<property name="socketTimeout" value="${http.socket.timeout:10000}" />
<property name="cookieSpec">
<util:constant static-field="org.apache.http.client.config.CookieSpecs.IGNORE_COOKIES" />
</property>
</bean>
<bean id="commonAuthzRequestConfig" factory-bean="commonAuthzRequestConfigBuilder" factory-method="build" />
<util:list id="spel-configuration">
<value>#{credentialsProvider.setCredentials(T(org.apache.http.auth.AuthScope).ANY, credentials)}</value>
<value>#{commonAuthzCredentialsProvider.setCredentials(T(org.apache.http.auth.AuthScope).ANY, commonAuthzCredentials)} </value>
</util:list>
</beans>
I turned debug logging on for Spring and found the following log entries:
[2015-04-13 10:46:56,818][DEBUG][org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - Loaded 0 bean definitions from location pattern [classpath*:httpclient-4x.xml]
[2015-04-13 10:46:56,818][DEBUG][org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader] - Imported 0 bean definitions from URL location [classpath*:httpclient-4x.xml]
I do not have control of the content of httpclient-4x.xml I just reference it.
By request, here is CvsDataClientImpl:
package com.mycompany.data;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import com.mycompany.utility.ConditionalUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
#Component
public class CvsDataClientImpl implements CvsDataClient<JsonNode> {
private static final int MAX_PAGE_SIZE = 100;
private static final String V1 = "/rest/v1.0/vehicles";
#Resource(name = "secureRestTemplate")
private RestTemplate restTemplate;
#Resource(name = "jsonVehiclesNodeMerger")
private JsonVehiclesNodeMerger nodeMerger;
#Value("${inv.vehicle-app.context:inventoryWebApp}")
private String vehicleAppContextPath;
#Value("${services.remoting.url:http://localhost:10080}")
private String remotingUrl;
#Override
public JsonNode read(String urlParameters) {
validateUrlParameters(urlParameters);
ResponseEntity<JsonNode> response = restTemplate.getForEntity(buildBaseRestUrl() + "?" + urlParameters, JsonNode.class);
return response.getBody();
}
#Override
public JsonNode readAll(String urlParameters) {
return readAll(urlParameters, null);
}
public JsonNode readAll(String urlParameters, Integer pageSize) {
int offset = 0;
int actualPageSize = pageSize != null ? pageSize : MAX_PAGE_SIZE;
JsonNode latestResult = null;
JsonNode baseResult = null;
do {
String extendedUrlParameters = buildUrlParameters(urlParameters, offset, actualPageSize);
latestResult = read(extendedUrlParameters);
baseResult = merge(latestResult, baseResult);
offset += actualPageSize;
} while (latestResult.get("searchResult").get("vehicles") != null);
return baseResult;
}
private JsonNode merge(JsonNode latestResult, JsonNode baseResult) {
JsonNode merged = null;
if (baseResult == null) {
merged = latestResult;
} else {
merged = nodeMerger.merge(latestResult, baseResult);
}
JsonNode searchResult = merged.get("searchResult");
((ObjectNode) searchResult).remove("summary");
return merged;
}
private String buildUrlParameters(String urlParameters, int offset, int pageSize) {
String parameters = urlParameters;
parameters += "&limit=" + pageSize + "&offset=" + offset;
return parameters;
}
private String buildBaseRestUrl() {
return remotingUrl + vehicleAppContextPath + V1;
}
private void validateUrlParameters(String urlParameters) {
if (ConditionalUtils.isNullOrEmpty(urlParameters) || urlParameters.indexOf("inventoryOwner") < 0 && urlParameters.indexOf("storeId") < 0) {
throw new IllegalArgumentException("Must provide at least an inventory owner or store ID");
}
}
void setVehicleAppContextPath(String contextPath) {
vehicleAppContextPath = contextPath;
}
void setRemotingUrl(String remotingUrl) {
this.remotingUrl = remotingUrl;
}
}
After some discussion on chat, minion and I found that httpclient-4x.xml is not included in the external project's build jar for some reason. Now I need to investigate that, but it's another story. :-)
When I want to access at the page with address?language=en or language=fr, I use the following controller :
public class AddressController {
private static Logger logger = Logger.getLogger(AddressController.class);
#RequestMapping(value="/address",method=RequestMethod.GET)
public ModelAndView init(HttpServletRequest r){
ApplicationContext context = new FileSystemXmlApplicationContext("/WEB-INF/spring-servlet.xml");
SessionLocaleResolver resolver = (SessionLocaleResolver) context.getBean("localeResolver");
String[] locales = resolver.resolveLocale(r).getISOCountries();
//String[] locales = Locale.getISOCountries();
Map<String,String> countryList = new HashMap<String,String>();
for(String countryCode : locales){
Locale loc = new Locale(resolver.resolveLocale(r).getLanguage(),countryCode);
countryList.put(loc.getDisplayCountry(), loc.getDisplayCountry());
logger.info(loc.getDisplayCountry());
}
Map<String,String> tree = new TreeMap<String,String>(countryList);
ModelAndView modelAndView = new ModelAndView("address");
modelAndView.addObject("address",new Address());
modelAndView.addObject("countriesList", tree);
return modelAndView;
}
}
spring-servlet.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.application.myGoogleAppEngine.controller" />
<!-- <mvc:annotation-driven /> -->
<!-- Register the messageBundle.properties -->
<bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="messageSource">
<property value="classpath:MessageBundle,classpath:Messages" name="basenames" />
<property value="UTF-8" name="defaultEncoding" />
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="fr" />
</bean>
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="language" />
</bean>
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<ref bean="localeChangeInterceptor" />
</property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property value="org.springframework.web.servlet.view.JstlView" name="viewClass" />
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
When I access to the controller by calling /address?language=en or /address?language=fr, I notice with the Logger in the loop 'for(String countryCode : locales)' that every country names print in french and not in english.
Do you have any solutions ?
Why don't you use the request parameter 'language' to create the the countries list? The SessionLocaleProvider will always return the same language as long as the session stays alive.
The following code sample takes the parameter to construct a list of localized country names:
#Controller
public class CountriesController {
#RequestMapping(value="/countries", method=RequestMethod.GET)
public ModelAndView getCountries(#RequestParam("language") String language){
List<String> countries = new ArrayList<>();
Locale locale = new Locale(language);
String[] isoCountries = Locale.getISOCountries();
for (String isoCountry : isoCountries) {
Locale countryLoc = new Locale(language, isoCountry);
String name = countryLoc.getDisplayCountry(locale);
if (!"".equals(name)) {
countries.add(name);
}
}
ModelAndView model = new ModelAndView("countries");
model.addObject("model", countries);
return model;
}
}
I've got a problem with Freemarker's viewResolver with Spring - session attributes are not exposed to view, as it is in Spring's InternalResourceViewResolver.
Now, important part is: when I change from Spring's resolver to Freemarker's one, session attribute is not passed, it's null. When Spring's resolver is working, session is passed.
My code:
dispatcher-servlet.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<bean id="userSession" class="com.revicostudio.web.session.UserSession" scope="session">
</bean>
<context:component-scan base-package="com.revicostudio.web" />
<mvc:annotation-driven />
<!--
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/ftl/"/>
<property name="freemarkerVariables">
<map>
<entry key="xml_escape" value-ref="fmXmlEscape"/>
</map>
</property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".jsp"/>
<property name="exposeSpringMacroHelpers" value="true"/>
<property name="exposeRequestAttributes" value="true"/>
<property name="allowRequestOverride" value="false" />
<property name="exposeSessionAttributes" value="true"/>
<property name="allowSessionOverride" value="false" />
<property name="exposePathVariables" value="true"/>
</bean>
<bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape"/>-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/ftl/" />
<property name="suffix" value=".jsp" />
<property name="exposeContextBeansAsAttributes" value="true" />
</bean>
</beans>
LoginController.java:
#Controller
#RequestMapping("/login")
#SessionAttributes("userSession")
public class LoginController {
#Autowired
private UsersDatabaseService usersDatabaseService;
#RequestMapping(method = RequestMethod.POST)
public String login(
#ModelAttribute UserLoginCredentials userLoginCredentials,
UserSession userSession,
final RedirectAttributes redirectAttributes)
{
int failedLoginAttempts = userSession.getFailedLoginAttempts();
if (failedLoginAttempts < LoginConfig.maxLoginTries ||
System.currentTimeMillis()-userSession.getFailedLoginsWaitTimeStart() > LoginConfig.failedLoginsWaitMinutes*60*1000) {
if (usersDatabaseService.isValidPassword(userLoginCredentials.getUsername(), userLoginCredentials.getPassword())) {
userSession.setUser(usersDatabaseService.getUser(userLoginCredentials.getUsername()));
userSession.setFailedLoginsWaitTimeStart(System.currentTimeMillis());
}
else {
failedLoginAttempts++;
if (failedLoginAttempts == LoginConfig.maxLoginTries) {
redirectAttributes.addFlashAttribute("error",
"You've entered invalid username or password more than "
+ LoginConfig.maxLoginTries + " times. Try again in "
+ LoginConfig.failedLoginsWaitMinutes +" minutes.");
}
else {
redirectAttributes.addFlashAttribute("error", "Invalid username or password");
userSession.setFailedLoginAttempts(failedLoginAttempts);
System.out.println(failedLoginAttempts);
}
}
}
else {
redirectAttributes.addFlashAttribute("error",
"You've entered invalid username or password more than "
+ LoginConfig.maxLoginTries + " times. Try again in "
+ LoginConfig.failedLoginsWaitMinutes +" minutes.");
}
return "redirect:/";
}
}
IndexController:
#Controller
#RequestMapping("/index")
public class IndexController {
#RequestMapping(method=RequestMethod.GET)
public String getIndex(Model model) {
return "index";
}
#ModelAttribute("userRegisterCredentials")
public UserRegisterCredentials getUserRegisterCredentials() {
return new UserRegisterCredentials();
}
#ModelAttribute("userLoginCredentials")
public UserLoginCredentials getUserLoginCredentials() {
return new UserLoginCredentials();
}
}
index.jsp:
<body>
<!-- Code for Freemarker -->
<#if error??>
${error}
</#if>
<#if userSession??>
${userSession}
</#if>
<#if !(userSession??)>
b
</#if>
<!-- Code for JSTL -->
${userSession}
You have a session problem because of that redirectAttributes.addFlashAttribute(). which means addFlashAttribute actually stores the attributes in a flashmap (which is internally maintained in the users session and removed once the next redirected request gets fulfilled),
Just try without redirectAttributes.addFlashAttribute() you will get session.
May be this will help you