Spring MVC with Thymeleaf and Tomcat 8 UTF-8 Encoding Issue - spring-mvc

I have some problem about encoding. According to this referance I have to do all of this and I did. But my encoding problem still remain after those. I am using Spring MVC, Spring Security, Thymeleaf, Tomcat 8 and Maven 3.
Here are some screeshots.
I passed string with model and it is working.
This is validation message came from my message.properties file. Encoding error occurred.
I am trying to save some record to db and error occurred again.
Here is what I have done.
I edited Tomcat's server.xml config and added UTF-8 encoding.
server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
useBodyEncodingForURI="true"
URIEncoding="UTF-8"
redirectPort="8443" />
I created CharacterEncodingFilter in my config folder.
CharacterEncodingFilter.java
#WebFilter(urlPatterns = {"/*"})
public class CharacterEncodingFilter implements Filter {
#Override
public void init(FilterConfig filterConfig)
throws ServletException {
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
servletRequest.setCharacterEncoding("UTF-8");
servletResponse.setContentType("text/html; charset=UTF-8");
filterChain.doFilter(servletRequest, servletResponse);
}
#Override
public void destroy() {
}
}
All my html files has this meta tag line for encoding.
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
My Thymeleaf configs are also set to UTF-8 encoding.
#Bean
#Description("Thymeleaf template resolver serving HTML 5")
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();
templateResolver.setPrefix("/WEB-INF/html/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("LEGACYHTML5");
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setCacheable(false);
return templateResolver;
}
#Bean
#Description("Thymeleaf template engine with Spring integration")
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
return templateEngine;
}
#Bean
#Description("Thymeleaf view resolver")
public ThymeleafViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
viewResolver.setContentType("text/html;charset=UTF-8");
viewResolver.setCharacterEncoding("utf-8");
return viewResolver;
}
I created my database with UTF-8 encoding like this.
postgres=# CREATE USER unicodeuser WITH PASSWORD 'mypass123';
postgres=# CREATE DATABASE unicode WITH ENCODING 'UTF8' OWNER unicodeuser;
postgres=# GRANT ALL ON DATABASE unicode TO unicodeuser;
I created JAVA_OPTS environment variable for encoding.
JAVA_OPTS=-DuriEncoding=UTF-8 -Dfile.encoding=UTF-8
I also changed my pom.xml files for UTF-8 encoding.
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
I tried everything on the internet but still can't find a solution. Any idea about what I am missing would be great.

fatiherdem, in all your cases you dont pay attention to Spring Security. Try that https://stackoverflow.com/a/23051264/4380830 answer. I have the same stack of technology with you and this answer work for me

I had the very same issue with a validation message and all the code solutions were still not enough. In my case using Intellij as editor I checked Transaparent native-to-ascii conversion to solve the issue. Please see my complete answer here.

You can use this trick of thymeleaf comment before process:

Related

spring boot - How to load context configuration file

I am trying to convert spring mvc app to spring boot. I used to deploy this application in tomcat and test. Now with spring boot I am trying to do the same thing but I am facing issues to load xml file configuration.
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- Data sources -->
<Environment name="/source/schema" value="${schema}" type="java.lang.String" />
<Resource auth="Container" driverClass="org.postgresql.Driver"
factory="org.apache.naming.factory.BeanFactory"
idleConnectionTestPeriod="30" jdbcUrl="${url}"
maxAdministrativeTaskTime="0" maxConnectionAge="30" maxIdleTime="9" maxPoolSize="3" minPoolSize="2"
name="/source/DataSource" password="${password}"
preferredTestQuery="select 1" testConnectionOnCheckout="true" type="com.mchange.v2.c3p0.ComboPooledDataSource" user="${user}"/>
</Context>
This is my configuration file which I am trying to load. When I put
#ImportResource({"classpath:applicationContext.xml", "classpath:context.xml"})
I am able to load all the bean configuration from applicationcontext.xml but while loading context.xml it is giving
Caused by: org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'Context'.
How should I load these entries when deploying spring boot app in tomcat?
By default, JNDI is disabled in embedded Tomcat. You need to call Tomcat.enableNaming() to enable it.
If you can live by Java config,you can try below snippet to add JNDI and other configurations from context.xml using the java config.
#Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
return new TomcatEmbeddedServletContainerFactory() {
#Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
Tomcat tomcat) {
tomcat.enableNaming();
return super.getTomcatEmbeddedServletContainer(tomcat);
}
};
}
Example :
#Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
return new TomcatEmbeddedServletContainerFactory() {
#Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
Tomcat tomcat) {
tomcat.enableNaming();
return super.getTomcatEmbeddedServletContainer(tomcat);
}
#Override
protected void postProcessContext(Context context) {
ContextResource resource = new ContextResource();
resource.setName("jdbc/myDataSource");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", "your.db.Driver");
resource.setProperty("url", "jdbc:yourDb");
context.getNamingResources().addResource(resource);
}
};
}
#Bean(destroyMethod="")
public DataSource jndiDataSource() throws IllegalArgumentException, NamingException {
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName("java:comp/env/jdbc/myDataSource");
bean.setProxyInterface(DataSource.class);
bean.setLookupOnStartup(false);
bean.afterPropertiesSet();
return (DataSource)bean.getObject();
}
Have a look at this github link for related sample
context.xml should go into the /META-INF/ directory in your war files. It is instructions to the Tomcat server, there's no need to configure anything in Spring to try to load it.

Spring and SiteMesh Error Page is not decorated (skips main filters)

I've been struggling with a rather absurd problem for a few days now:
The project I'm on is using Spring MVC with FreeMarker for it's templating.
This is running atop a Tomcat container (testing locally using Cargo).
The issue I'm working has the brief of implementing uniform behaviour in a standardised error page but covering covering the various types of errors that may be encountered. (Exceptions bubbling up from back-end services, inadequate permissions, http errors, etc)
So far, the results are as follows (Graphic included):
Fig A: Normal navigation to page - renders as expected.
Fig B & Fig C: Service and Permission Exceptions caught by ControllerAdvice.java - likewise, no issues.
Fig D: Any HTTP Error (yes, even 418 if you trigger that response) - Inner freemarker template is correctly retrieved and populated with bindings but decorations applied by filters fail to trigger.
Currently we're using Spring to configure the servlet handling so the web.xml is beautifully sparse:
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--
This application uses the config of the mapping by Spring MVC
This is why you will not see servlet declarations here
The web app is defined in
- butler.SpringWebInit
- butler.SpringWebConfig
-->
<context-param>
<description>Escape HTML form data by default when using Spring tags</description>
<param-name>defaultHtmlEscape</param-name>
<param-value>true</param-value>
</context-param>
<!-- Disabling welcome list file for Tomcat, handling it in Spring MVC -->
<welcome-file-list>
<welcome-file/>
</welcome-file-list>
<!-- Generic Error redirection, allows for handling in Spring MVC -->
<error-page>
<location>/http-error</location>
<!-- Was originally just "/error" it was changed for internal forwarding/proxying/redirection attempts -->
</error-page>
</web-app>
The Configuration is handled by SpringWebInit.java to which I have not made any modifications:
SpringWebInit.java
/**
* Automatically loaded by class org.springframework.web.SpringServletContainerInitializer
*
* #see http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-container-config
*
* According to {#link AbstractSecurityWebApplicationInitializer}, this class should be
* annotated with a Order so that it is loaded before {#link SpringSecurityInit}
*/
#Order(0)
public class SpringWebInit extends AbstractAnnotationConfigDispatcherServletInitializer implements InitializingBean {
private final Logger LOG = LoggerFactory.getLogger(getClass());
#Override
public void afterPropertiesSet() throws Exception {
LOG.info("DispatcherServlet loaded");
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null; // returning null, getRootConfigClasses() will handle this as well
}
#Override
protected String[] getServletMappings() {
return new String[] {"/**"}; // Spring MVC should handle everything
}
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] {SpringWebConfig.class, SpringSecurityConfig.class};
}
#Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter =
new CharacterEncodingFilter(StandardCharsets.UTF_8.name(), true);
return new Filter[] {characterEncodingFilter, new SiteMeshFilter()};
}
}
Which in turn loads The various config for Freemarker and Sitemesh:
SpringWebConfig.java
#EnableWebMvc
#Configuration
#PropertySource("classpath:/butler-init.properties")
#ComponentScan({"butler"})
class SpringWebConfig extends WebMvcConfigurerAdapter implements InitializingBean {
private final Logger LOG = LoggerFactory.getLogger(getClass());
#Autowired
LoggedInUserService loggedInUserService;
#Override
public void afterPropertiesSet() throws Exception {
LOG.info("Web Mvc Configurer loaded");
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userHeaderInterceptor());
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/static/").setCacheControl(
CacheControl.maxAge(30, TimeUnit.MINUTES).noTransform().cachePublic().mustRevalidate());
}
#Bean
FreeMarkerViewResolver viewResolver() throws TemplateException {
FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
resolver.setCache(/*true*/false); // Set to false for debugging
resolver.setPrefix("");
resolver.setSuffix(".ftlh");
resolver.setRequestContextAttribute("rContext");
resolver.setContentType("text/html;charset=UTF-8");
DefaultObjectWrapper wrapper =
new DefaultObjectWrapperBuilder(freemarker.template.Configuration.getVersion()).build();
Map<String, Object> attrs = new HashMap<>();
attrs.put("loggedInUserService", wrapper.wrap(loggedInUserService));
resolver.setAttributesMap(attrs);
return resolver;
}
#Bean
FreeMarkerConfigurer freeMarkerConfig() {
Properties freeMarkerVariables = new Properties();
// http://freemarker.org/docs/pgui_config_incompatible_improvements.html
// http://freemarker.org/docs/pgui_config_outputformatsautoesc.html
freeMarkerVariables.put(freemarker.template.Configuration.INCOMPATIBLE_IMPROVEMENTS_KEY,
freemarker.template.Configuration.getVersion().toString());
FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
freeMarkerConfigurer.setDefaultEncoding("UTF-8");
freeMarkerConfigurer.setTemplateLoaderPath("/WEB-INF/mvc/view/ftl/");
freeMarkerConfigurer.setFreemarkerSettings(freeMarkerVariables);
return freeMarkerConfigurer;
}
#Bean
UserHeaderInterceptor userHeaderInterceptor() {
return new UserHeaderInterceptor();
}
#Bean
static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
SiteMeshFilter.java
public class SiteMeshFilter extends ConfigurableSiteMeshFilter {
#Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
// Don't use decorator REST api pages
builder.addExcludedPath("/api/*");
builder.addDecoratorPath("/*", Views.DECORATOR_HEADER_FOOTER);
builder.setIncludeErrorPages(true);
}
}
Finally, onto the meat of the problem, the error handling is being handled via a combination of DefaultControllerAdvice.java, which provides the rules for intercepting exceptions and ErrorController.java itself, which handles the mappings and eventually, the message handling (displaying information about the error, adapting according to the type of error, etc)
DefaultControllerAdvice.java
#ControllerAdvice(annotations = Controller.class)
class DefaultControllerAdvice {
private static String EXCEPTION = "butlerexception";
#ExceptionHandler(ServiceException.class)
public String exceptionHandler(ServiceException se, Model model) {
model.addAttribute(EXCEPTION, se.getMessage());
return Views.ERROR;
}
#ExceptionHandler(PermissionException.class)
public String exceptionHandler(PermissionException pe, Model model) {
model.addAttribute(EXCEPTION, "Incorrect Permissions");
return Views.ERROR;
}
/*#ResponseStatus(HttpStatus.NOT_FOUND)
#ExceptionHandler(IOException.class)
public String exceptionHandler(Model model) { // Trying another way of intercepting 404 errors
model.addAttribute(EXCEPTION, "HTTP Error: 404");
return Views.ERROR;
}*/
}
ErrorController.java
#Controller
class ErrorController extends AbstractController {
#Autowired
private LoggedInUserService loggedInUserService;
#RequestMapping(path="error",method = {GET,POST}) // Normal Error Controller, Returns fully decorated page without issue for Exceptions and normal requests.
public String error(RedirectAttributes redirectAttributes, HttpServletResponse response,Model model) {
//if (redirectAttributes.containsAttribute("errorCode")) { // Trying to invisibly use redirection
// Map<String, ?> redirAttribs = redirectAttributes.getFlashAttributes();
// model.addAttribute("butlerexception", "HTTP Error: "+redirAttribs.get("errorCode"));
//} else {
model.addAttribute("butlerexception", "Error");
//}
return ERROR;
}
#RequestMapping("/http-error") // Created to test HTTP requests being proxied via ServiceExceptions, Redirections, etc...
public String httpError(/*RedirectAttributes redirectAttributes,*/ HttpServletResponse response, HttpServletRequest request, Model model){
model.addAttribute("butlerexception", "HTTP Error: " + response.getStatus());
//throw new ServiceException("HTTP Error: " + response.getStatus()); // Trying to piggyback off Exception handling
//redirectAttributes.addFlashAttribute("errorCode", response.getStatus()); // Trying to invisibly use redirection
//redirectAttributes.addFlashAttribute("originalURL",request.getRequestURL());
return /*"redirect:"+*/ERROR;
}
}
So Far, I have tried:
Throwing exceptions to piggy-back off the working ControllerAdvice rules. - Result was undecorated.
Adding in Rules for response codes, IONotFound nad NoHandlerFound exceptions - Result was undecorated.
Redirecting to the error page - Result was decorated correctly, but URL and response codes were incorrect, attempting to mask the URL with the original request URL resulted in the correct URL and code, but the same lack of decoration as before.
Additionally, from the debugging logs, I can see that the filters from Spring Security are triggered normally but the ones involved with decorating the site (for both logged in and anonymous requests) fail to trigger for HTTP errors only.
One of the limiting factors currently is that I cannot gut the system and define it all in the web.xml (as many of the solutions here and in the Spring documentation seem to call for) without causing excessive disruption to development at this stage. (nor do I have the authority to effect such a change (Junior rank))
For Convenience sake, a few of the solutions I've tried so far:
Spring MVC 404 Error Page
404 error redirect in Spring with java config
Generic Error Page not decorated
Custom Error Page Not Decorated by Sitemesh in Spring Security Application
Custom 404 using Spring DispatcherServlet
<error-page> setup doesn't work in Spring MVC
At this point I'm really not sure what else to try, what on earth am I missing here?
Edit: it turned out to be a bug in SiteMesh to do with the triggering of .setContentType(...) that was solved via setting the contentType again after sitemesh in order to trigger decoration: Bug report with description and solution
This turned out to a two-part issue, firstly SiteMesh3's handling of error pages means that it believes it has processed all the filters even when an error causes decorators to be skipped. (expanded upon in this issue on github)
The second part was that SiteMesh3 appears to only buffer pages for decoration when SpringMVC calls .setContentType(...).
This was tripping up since Spring will only trigger this on elements with undefined content type whereas errors have already had their content type defined before they even reach Spring. (expanded upon by my lead in this issue)
My lead managed to solve this by adding a filter after SiteMesh that triggered .setContentType(...) and forced SiteMesh to buffer the page for decoration.
It's a little heavy, since it means that the content type is set twice per request, but it works.
Edit: Originally had a note here asking not to upvote to avoid receiving rep for a solution my lead found, but found a blog post explaining that self-answers don't earn rep - huzzah!
Solution 1:
Check if you have disabled property spring.resources.add-mappings=false. Enabling it could solve the problem. But in my case enabling it removed custom error pages at all.
Solution 2:
Based on comments on github issue https://github.com/sitemesh/sitemesh3/issues/25 declare custom selector inside your SiteMeshFilter:
public class SiteMeshFilter extends ConfigurableSiteMeshFilter {
#Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
builder.setCustomSelector(new CustomBasicSelector());
}
private static class CustomBasicSelector extends BasicSelector {
private static final String ALREADY_APPLIED_KEY = BasicSelector.class.getName() + ".APPLIED_ONCE";
public CustomBasicSelector() {
super(true, "text/html");
}
protected boolean filterAlreadyAppliedForRequest(HttpServletRequest request) {
if (request.getDispatcherType().equals(DispatcherType.ERROR)) {
if (Boolean.TRUE.equals(request.getAttribute(ALREADY_APPLIED_KEY + ".ERROR"))) {
return true;
} else {
request.setAttribute(ALREADY_APPLIED_KEY + ".ERROR", true);
return false;
}
}
return super.filterAlreadyAppliedForRequest(request);
}
}
}

How to convert from spring-integration-kafka 1.0.0M (XML config) to spring-integration-kafka 1.2.1 (Java config)?

I implemented spring-integration-kafka 1.0.0M into a Spring MVC project last year using the XML configuration and it was very simple to do. Since Spring seems to be moving in a Java configuration direction (rather than XML), I would like to convert from using the spring-integration-kafka XML configuration to the Java configuration, which the latest version of spring-integration-kafka (1.2.1) supports. The problem is that there really aren't many complete examples of this being done online, and the examples I have found look to be out-of-date from what I can tell. The configuration I have is pretty simple:
<bean id="kafkaStringEncoder" class="org.springframework.integration.kafka.serializer.common.StringEncoder" />
<bean id="customObjectMapper" class="ad.content.api.utils.ObjectMapperFactory" factory-method="getMapper" />
<int:channel id="kafkaConversionRequest" />
<bean id="producerProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="message.send.max.retries">${kafka.retries}</prop>
</props>
</property>
</bean>
<int-kafka:producer-context id="kafkaWidgetProducerContext" producer-properties="producerProperties">
<int-kafka:producer-configurations>
<int-kafka:producer-configuration
broker-list="${kafka.broker}" key-class-type="java.lang.String"
key-encoder="kafkaStringEncoder" value-class-type="java.lang.String"
value-encoder="kafkaStringEncoder" topic="widget-.*"
compression-codec="default" async="true" />
</int-kafka:producer-configurations>
</int-kafka:producer-context>
<!-- declare spring integration gateway for kafka -->
<int:gateway service-interface="ad.content.api.models.kafka.KafkaGateway" default-reply-timeout="2000">
<int:method name="publishConversion" request-channel="kafkaConversionRequest" />
</int:gateway>
<int:chain input-channel="kafkaConversionRequest" output-channel="kafkaToJson">
<int:header-enricher>
<int:header name="topic" value="widget-conversion" />
</int:header-enricher>
</int:chain>
<int:object-to-json-transformer input-channel="kafkaToJson" output-channel="kafkaOutbound" object-mapper="customObjectMapper" />
<int-kafka:outbound-channel-adapter id="kafkaOutbound" kafka-producer-context-ref="kafkaWidgetProducerContext" />
Here's what I can figure out so far:
// gateway
#MessagingGateway(defaultReplyTimeout="2000")
public interface KafkaGateway {
#Gateway(requestChannel="kafkaConversionRequest", headers=#GatewayHeader(name="topic", value="widget-conversion"))
void publishConversion(Conversion conversion);
}
// create channel
#Bean(name="kafkaConversionRequest")
public MessageChannel getConversionRequest() {
return new DirectChannel();
}
#Bean
public KafkaProducerMessageHandler getHandler() throws Exception {
return new KafkaProducerMessageHandler(getContext());
}
#Bean
public KafkaProducerContext getContext() throws Exception {
KafkaProducerContext context = new KafkaProducerContext();
context.setProducerConfigurations(Collections.singletonMap("config", getConfiguration()));
return context;
}
#Bean
public ProducerConfiguration<String, String> getConfiguration() throws Exception {
return new ProducerConfiguration<String, String>(getMetaData(), getProducer());
}
#Bean
#Transformer(inputChannel="kafkaToJson", outputChannel="kafkaOutbound")
public ObjectToJsonTransformer getJsonTransformer() {
return new ObjectToJsonTransformer();
}
#Bean
public ProducerMetadata<String, String> getMetaData() {
StringSerializer serializer = new StringSerializer();
return new ProducerMetadata<String, String>("widget-.*", String.class, String.class, serializer, serializer);
}
#Bean
public Producer<String, String> getProducer() throws Exception {
return new ProducerFactoryBean<String, String>(getMetaData(), "dev.kafka-broker01:9092").getObject();
}
There's an outstanding pull request for a kafka sample that might help you.
Here is a fully functional example of configuring Kafka using Spring Java Config and equivalent XML version as well: https://spring.io/blog/2015/04/15/using-apache-kafka-for-integration-and-data-processing-pipelines-with-spring

How do I get the user when logs incorrectly with Spring Security?

I am using Spring security for interceptor to user wrong logged, but I can not find the way to do.
I specifically want to save the user logged in last, but I can't figure out how to achieve this.
Please help me.
Yes you can do that. You can define following tag in tag in your configuration xml file.
<security:form-login login-page="/sessionexpired"
login-processing-url="/j_spring_security_check"
default-target-url="/submitLogin"
always-use-default-target="true"
authentication-failure-handler-ref="customAuthenticationFailureHandler"/>
You can see the last parameter set authentication-failure-handler-ref its value is a refenrece to following bean defined in the same xml file.
<bean id="customAuthenticationFailureHandler" class="com.xxx.xxx.xxx.CustomFilter">
<constructor-arg type="String" value="loginfailed"></constructor-arg>
<constructor-arg type="org.hibernate.SessionFactory" ref="sessionFactory"></constructor-arg>
</bean>
The class defined in this bean is your own class that will get the information about the failed login details.
public class CustomFilter extends SimpleUrlAuthenticationFailureHandler {
private String defaultFailureUrl;
private SessionFactory sessionFactory;
public CustomFilter(String defaultFailureUrl,SessionFactory sessionFactory) {
super();
this.defaultFailureUrl = defaultFailureUrl;
this.sessionFactory = sessionFactory;
}
#Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
// TODO Auto-generated method stub
String userName = request.getParameter("j_username");;
/*System.out.println("CustomFilter Begins");
System.out.println("CustomeFilter.username :: " + userName);
System.out.println("getMessage :: " + exception.getMessage());
System.out.println("exception :: " + exception.getClass().getSimpleName());
System.out.println("RemoteAddr :: " + request.getRemoteAddr()); */
}
}
When the Authentication will be failed then method onAuthenticationFailure of this class will be called and you can get the user details there to log in database or log file.
Hope this helps you. Cheers.

Importing spring.ftl using Spring MVC, Sitemesh, Freemarker

How can I import the spring.ftl macros into a Freemarker template page using Spring MVC, Sitemesh, and Freemarker?
I've configured a Spring MVC app using Sitemesh and Freemarker based on Ted Young's configuration example. According to the Spring MVC/Freemarker integration reference, it is necessary to import the spring.ftl macros in order to bind the backing model to the view via <#spring.bind "command.name"/>. However, doing this:
<#import "/spring.ftl" as spring>
<#spring.bind "command.user"/>
Results in this exception:
org.springframework.web.util.NestedServletException:
Request processing failed; nested exception is freemarker.
template.TemplateException: Error reading imported file spring.ftl
Others have experienced this issue, but I've yet to find a solution in google land. I also attempted to use this technique (zipping up spring.ftl, placing it in META-INF/lib, and adding the zip to the build path), but it didn't seem to work out.
Thanks!
The problem is that spring dont know where to look after the spring.ftl file:
This is my custom configuration for an MVC project using Boot
/**
* Otras configuraciones de la aplicaciones web, incluyendo algunas definidas en
* xml. Usar #ImportResource("classpath:/extra-config.xml") en caso de quererse
* importar configuracion en xml
*/
#Configuration
#PropertySource("classpath:application.properties")
public class WebAppConfig
{
#Autowired
private ServletContext context;
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer placeHolderConfigurer = new PropertySourcesPlaceholderConfigurer();
return placeHolderConfigurer;
}
#Bean
public FreeMarkerConfigurer freeMarkerConfigurer() throws IOException, TemplateException
{
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer()
{
#Override
protected void postProcessConfiguration(freemarker.template.Configuration config) throws IOException, TemplateException
{
WebappTemplateLoader WebAppTplLoader = new WebappTemplateLoader(context, "/WEB-INF/ftl");
ClassTemplateLoader classTplLoader = new ClassTemplateLoader(context.getClassLoader(), "/templates");
ClassTemplateLoader baseMvcTplLoader = new ClassTemplateLoader(FreeMarkerConfigurer.class, "");
MultiTemplateLoader mtl = new MultiTemplateLoader(new TemplateLoader[]
{
WebAppTplLoader,
classTplLoader,
baseMvcTplLoader
});
config.setTemplateLoader(mtl);
}
};
configurer.setDefaultEncoding("UTF-8");
configurer.setPreferFileSystemAccess(false);
return configurer;
}
#Bean
public FreeMarkerViewResolver viewResolver()
{
FreeMarkerViewResolver viewResolver = new FreeMarkerViewResolver();
viewResolver.setExposeSpringMacroHelpers(true);
viewResolver.setExposeRequestAttributes(true);
viewResolver.setPrefix("");
viewResolver.setSuffix(".ftl");
viewResolver.setContentType("text/html;charset=UTF-8");
return viewResolver;
}
}
The first 2 loaders allow to load .ftl templates in war files from "/WEB-INF/ftl" and from regular jar files from src/resources/templates.
If you want to use security tags in freemarker the escense are this two lines:
viewResolver.setExposeSpringMacroHelpers(true);
viewResolver.setExposeRequestAttributes(true);
And the baseMvcTplLoader loader to get the spring.ftl from org.springframework.web.servlet.view.freemarker. I advice to explore ftl templates in some example project or documentation to have a clue of how spring.ftl works.
The configuration of the placeholder is not related to the freemarker
configuration, yet its very useful for injecting values in variables
from src/resources/application.properties by using the #Value
annotation.
With this you can use all the spring power within freemarker templates.
I like my spring.ftl included by default without having to add it manually within each view. In your configuration.
Define your freemarkerConfigurer as such.
#Bean(name = "freemarkerConfig")
public FreeMarkerConfigurer freemarkerConfig() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("/WEB-INF/views/");
Map<String, Object> map = new HashMap<>();
map.put("xml_escape", new XmlEscape());
configurer.setFreemarkerVariables(map)
def settings = new Properties()
settings['auto_import'] = 'spring.ftl as spring, layout/application.ftl as l'
configurer.setFreemarkerSettings(settings)
println "returning freemarker config"
return configurer;
}
<#import "spring.ftl" as spring/>
Without /

Resources