Java Spring Boot & Thymeleaf: An error happened during template parsing - java

I'm developing a Java Spring Boot Web App where users can register. When they register, they get sent a verification email. This is no longer working when I've tried to get the link in the email to actually confirm the registration because I get the error: "An error happened during template parsing (template: "mail/verifyEmail.html")". I'm not sure why this could be. I've attached below the verifyEmail.html file, and then the accompanying EmailService.java file which has the EmailService() and sendVerificationEmail() methods:
<!DOCTYPE html>
<html>
<th:block xmlns:th="http://www.thymeleaf.org">
<span th:text="'Hello ' + ${name}"></span>
<p>Thank you for registering for the bcoreHW site!</p>
<p>Please click here to verify your email address.</p>
</th:block>
</html>
import java.util.Date;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
#Service
public class EmailService {
#Autowired
private JavaMailSender mailSender;
#Value("${mail.enable}")
private boolean enable;
private TemplateEngine templateEngine;
private void send(MimeMessagePreparator preparator) {
if(enable) {
mailSender.send(preparator);
}
}
#Autowired
public EmailService(TemplateEngine templateEngine) {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("mail/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML5");
templateResolver.setCacheable(false);
templateEngine.setTemplateResolver(templateResolver);
this.templateEngine = templateEngine;
}
public void sendVerificationEmail(final String emailAddress) {
Context context = new Context();
context.setVariable("name", "Bob");
final String emailContents = templateEngine.process("verifyEmail", context);
System.out.println(emailContents);
MimeMessagePreparator preparator = new MimeMessagePreparator() {
// not working for some reason: #Override
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
message.setTo(emailAddress);
message.setFrom(new InternetAddress("no-reply#testSite.com"));
message.setSubject("Please Verify Your Email Address");
message.setSentDate(new Date());
message.setText(emailContents, true);
}
};
send(preparator);
}
}
Does anyone see anything wrong with this? Thanks. Also, here is the error message I'm getting:
Caused by: java.io.FileNotFoundException: ClassLoader resource "mail/verifyEmail.html" could not be resolved
at org.thymeleaf.templateresource.ClassLoaderTemplateResource.reader(ClassLoaderTemplateResource.java:130) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:223) ~[thymeleaf-3.0.11.RELEASE.jar:3.0.11.RELEASE]

I found the issue. My prefix "mail/" is incorrect because it's actually in a directory called "mailTemplates". Silly me.

Related

Spring Controller ModelAndView test MockMvc empty Response

I have this simple example setup to unit test spring Controller ModelAndView with MockMvc, but the response is always empty, even though in debug I can see that the controller code is executed.
Here's the code:
/src/main/java/controller/MvcController.java
package controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class MvcController {
#RequestMapping("/hello/{id}")
public ModelAndView hello(#PathVariable("id") String id) {
Map<String, String> model = new HashMap<>();
ModelAndView modelAndView = new ModelAndView("hello", model);
return modelAndView;
}
}
/src/main/webapp/WEB-INF/jsp/hello.jsp
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# taglib prefix="e"
uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project"%>
<%# page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
</head>
<body>HELLO WORLD
</body>
</html>
/src/test/java/controller/MvcControllerTest.java
package controller;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { MvcController.class })
public class MvcControllerTest {
#Autowired
private MvcController mvcController;
private MockMvc mockMvc;
#Before
public void init() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
this.mockMvc = MockMvcBuilders.standaloneSetup(mvcController).setViewResolvers(resolver).build();
}
#Test
public void testHello() throws Exception {
RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/hello/XWQHEDg9e72t");
ResultActions result = mockMvc.perform(requestBuilder);
MvcResult mvcResult = result.andReturn();
MockHttpServletResponse mockHttpServletResponse = mvcResult.getResponse();
String response = mockHttpServletResponse.getContentAsString();
assertThat(response).contains("HELLO WORLD");
}
}
The key word in MockMvc is mock. This framework does not set up a full Servlet container with a JSP engine. As such, it doesn't render the view that your controller returns and the MockHttpServletResponse does not contain a body (for this use case).
You can use MockHttpServletResponse#getForwardedUrl() to get the url of the JSP that the Servlet container would've forwarded the request to, constructed from your view name and the prefix and suffix of your InternalResourceViewResolver.

JSP/SpringMVC not finding the resources folder

I'm developing a webapp using Spring MVC/JSP with Java 11, and SpringMVC 5.2.0, which started with config files, but I wanted to give programatic config (through java) a try. I've got the Servlet running, and I've successfully made the login page to "intercept" any other .jsp view if the user is not logged... However, I haven't been able to get my resources from my resource folder.
Every resource that should be loaded from there (e.g.
<link type="image/png" rel="icon" href="${contextPath}/resources/img/icon.png">) I get a 404 response, and in my IDE (Netbeans 11) I get the following message in the Network Monitor:
Request URL: http://localhost:8080/icon.png
Method: GET
Status: 404
Note: The URL should be http://localhost:8080/dragonline/resources/img/icon.png (<c:set var="contextPath" value="${pageContext.request.contextPath}"/>)
Here's my config java file:
package com.midknightmunch.dragonline.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.ResourceBundleViewResolver;
import org.springframework.web.servlet.view.JstlView;
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = {"com.midknightmunch.dragonline"})
public class WebConfig implements WebMvcConfigurer{
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
//registry.addResourceHandler("/img/**").addResourceLocations("/resources/img/");
//registry.addResourceHandler("/css/**").addResourceLocations("/resources/css/");
//registry.addResourceHandler("/js/**").addResourceLocations("/resources/js/");
//I've tried with and without these 3 (the commented ones)
}
#Bean
public ViewResolver internalViewResolver() {
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setViewClass(JstlView.class);
bean.setPrefix("/WEB-INF/views/");
bean.setSuffix(".jsp");
bean.setOrder(0);
return bean;
}
#Bean
public ViewResolver resourceBundleViewResolver() {
ResourceBundleViewResolver bean = new ResourceBundleViewResolver();
bean.setBasename("views");
bean.setOrder(1);
return bean;
}
#Bean("messageSource")
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource bean = new ReloadableResourceBundleMessageSource();
String[] basenames = {"classpath:validation"};
bean.setBasenames(basenames);
return bean;
}
}
And my project structure:
icon.png: dragonline/src/main/webapp/resources/img/icon.png
views(including the jsp trying to import this image): dragonline/src/main/webapp/WEB-INF/views/login.jsp
I've tried moving the resources folder everywhere, but everytime I get a 404.
Please, any help would be appreciated.
I figured it out. The problem was that I did not grant permission in my Spring Security config file to access the resources folder, so I solved it by adding:
http.authorizeRequests().antMatchers("/resources/**").permitAll()
in my WebSecurityAdapter's config() method

404 - the requested ressource is not available

While trying to do a simple program about the Spring MVC I got always the same error when running http://localhost:8080/project_name/:
404 - the requested resource is not available
This is the architecutre of the project:
src
| +--com
| +--memorynotfound
| +--config
| |--ServletInitializer.java
| |--WebConfig.java
| +--controller
| |--HomeController.java
| +--resources
| +--webapp
| +--WEB-INF
| +--views
| |--index.jsp
Here is the files in the package com.memorynotfound.config:
ServletInitializer.java
package com.memorynotfound.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
}
WebConfig.java
package com.memorynotfound.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
#Configuration
#EnableWebMvc
#ComponentScan(basePackages="com.memorynotfound")
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public InternalResourceViewResolver viewResolver(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
Files in the package com.memorynotfound.controller:
HomeController.java
package com.memorynotfound.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.ui.ModelMap;
#Controller
#RequestMapping("/")
public class HomeController {
#RequestMapping(method = RequestMethod.GET)
public String index(ModelMap model){
System.out.println("This is a test ================>");
model.addAttribute("message", "Spring MVC Java Configuration Example");
return "index";
}
}
And finally the Jsp file:
index.jsp
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Spring MVC Java Configuration Example</title>
</head>
<body>
${message}
</body>
</html>
I thought that when you were using Spring MVC without a web.xml file, you needed to supply an implementation of WebApplicationInitializer
Without such an initializer, you would still need to provide a web.xml file.
Minimally your WebApplicationInitializer instance should probably use setLoadOnStartup(1) and provide a mapping for the dispatcher.
From the referenced web page above
public class MyWebApplicationInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) {
ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
registration.setLoadOnStartup(1);
registration.addMapping("/example/*");
}
}
I solved the problem by doing :
right click on the project name and select properties
Select Deployment assembly
Add spring and JTL jars

Http 404 error in Hello world Spring MVC Web app fully java configured

I'm new to Spring Web MVC and I tried to try Hello world app.
I followed an example from "Spring In Action 4th ed" book which only uses java config (without any XML file). I use Tomcat v7.0 server and servlet 3.
The problem is when I try to go to the home page I get Http 404 error.
The used Java classes are :
DispatcherServlet configuration:
package config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class FirstWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
}
Spring MVC configuration :
package config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#EnableWebMvc
#ComponentScan("web")
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
Configuration used to get other Beans (doesn't do any thing in the hello world app)
package config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
#Configuration
#ComponentScan(basePackages={"lgmi_cr"},excludeFilters={#Filter(type=FilterType.ANNOTATION, value=EnableWebMvc.class)})
public class RootConfig {
}
Home page controller
package web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class HomeController {
#RequestMapping(value="/")
public String home() {
return "home";
}
}
A JSP file "home" uneder /WEB-INF/views/
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>First app</title>
</head>
<body>
<h1>Hello world</h1>
</body>
</html>
Since it 404 error, my first impression is that it could not find any controller but I don't know why.
Thank you for any help
I have just found the problem.
Actually, I added the external Spring jar files to the project classpath and I forget to add them to myProject/WebContent/WEB-INF/lib.

How to include css in my JSP?

I need to include css style file in my JSP page.
But cant find properly url. Please help.
My JavaConfig:
package com.sprhib.init;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;
public class Initializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext)
throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(WebAppConfig.class);
servletContext.addListener(new ContextLoaderListener(ctx));
ctx.setServletContext(servletContext);
Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
FilterRegistration.Dynamic filterRegistration = servletContext.addFilter("encodingFilter",
new CharacterEncodingFilter());
filterRegistration.setInitParameter("encoding", "UTF-8");
filterRegistration.setInitParameter("forceEncoding", "true");
filterRegistration.addMappingForUrlPatterns(null,true,"/*");
}
}
_
package com.sprhib.init;
import java.util.Properties;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
#Configuration
#ComponentScan("com.sprhib")
#EnableWebMvc
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
public class WebAppConfig {
private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";
#Resource
private Environment env;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
return dataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
sessionFactoryBean.setHibernateProperties(hibProperties());
return sessionFactoryBean;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
return properties;
}
#Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
}
I need to include css style file in my JSP page.
But cant find properly url. Please help.
web.xml is empty.
Image of project structure:
Java Configuration :
Since you are using a java config here is how to do it :
#Configuration
#EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/resources/**")
.addResourceLocations("(/resources/");
}
}
On the client side (jsp):
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<link href="<c:url value="/resources/styleTabl.css" />" rel="stylesheet">
<title>Home</title>
</head>
In case someone is using XML configuration the following will do :
<mvc:resources mapping="/resources/**" location="/resources/" />
If you want to add a css file in your jsp you simply add a link as the following:
<link rel="stylesheet" href="ui/custom-jquery-ui2/css/custom-theme/jquery-ui-1.10.4.custom.css" type="text/css">
Make sure that the css files are somewhere under your webapp folder, and your url path should start after that. In the example above, the href starts at "ui",which means that under webapp, I have a folder "ui".

Categories