How can use Thymeleaf with Cyrillic keywords (token) - java

How can use Thymeleaf with Cyrillic keywords (token) my settings is:
config:
#Bean
public SpringTemplateEngine springTemplateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
StringTemplateResolver stringTemplateResolver = new StringTemplateResolver();
templateEngine.addTemplateResolver(stringTemplateResolver);
return templateEngine;
}
class:
public class TemplateConverter {
private SpringTemplateEngine templateEngine;
private final static String TEMPLATE_LOCAL = "RU";
public String getTemplateFromAttributes(String template, Map<String, Object> attr) {
Context context = new Context(new Locale(TEMPLATE_LOCAL));
if (!CollectionUtils.isEmpty(attr)) {
attr.forEach((k, v) -> context.setVariable(k, v));
}
return templateEngine.process(template, context);
}
}
works:
//..
String template = "Привет [(${keyword})]";
String result = templateConverter.getTemplateFromAttributes(template, Map.of("keyword", "мир"));
System.out.println(result); // "Привет мир"
But when I try make it with cyrillic words it don't works
//..
String template = "Привет [(${ключевое_слово})]";
String result = templateConverter.getTemplateFromAttributes(template, Map.of("ключевое_слово", "мир")); // exception
System.out.println(result);
UPDATE
00:47:07.123 [main] DEBUG org.thymeleaf.TemplateEngine - [THYMELEAF] TEMPLATE ENGINE INITIALIZED
00:47:07.196 [main] ERROR org.thymeleaf.TemplateEngine - [THYMELEAF][main] Exception processing template "Привет [(${ключевое_слово})]": An error happened during template parsing (template: "Привет [(${ключевое_слово})]")
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "Привет [(${ключевое_слово})]")
at org.thymeleaf.templateparser.text.AbstractTextTemplateParser.parse(AbstractTextTemplateParser.java:180)
at org.thymeleaf.templateparser.text.AbstractTextTemplateParser.parseStandalone(AbstractTextTemplateParser.java:92)
at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1098)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1059)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1048)
at ru.mm.util.converter.TemplateConverter.getTemplateFromAttributes(TemplateConverter.java:35)
at ru.mm.util.converter.TemplateConverterTest.whenPutRightStringThenRightPlainText(TemplateConverterTest.java:39)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
...
UPDATE
all stac trace
docs.google.com
TEMPLATE_LOCAL = "RU" - not effect
StringTemplateResolver doesn't have something for setup UTF-8 key
UPDATE - !!SOLUTION!!
changed maven dependency
from:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.7.5</version>
</dependency>
to:
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
and change engine SpringTemplateEngine -> TemplateEngine
config:
#Bean
public TemplateEngine springTemplateEngine() {
TemplateEngine templateEngine = new TemplateEngine();
StringTemplateResolver stringTemplateResolver = new StringTemplateResolver();
templateEngine.addTemplateResolver(stringTemplateResolver);
return templateEngine;
}

Related

Field templateEngine in '....' required a bean of type 'org.thymeleaf.TemplateEngine' that could not be found

So i'm trying to generate a pdf file from a thymeleaf template but I get this error when running my app.
***************************
APPLICATION FAILED TO START
***************************
Description:
Field templateEngine in com.example.app.service.PdfService required a bean of type 'org.thymeleaf.TemplateEngine' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'org.thymeleaf.TemplateEngine' in your configuration.
Process finished with exit code 0
HERE IS HOW MY APPLICATION LOOKS LIKE. Everything looks correct and I don't know what i've done wrong
my configuration file :
#Configuration
public class ThymeleafConfig {
#Bean
public ClassLoaderTemplateResolver templateResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("templates/");
templateResolver.setTemplateMode("HTML5");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("XHTML");
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setOrder(1);
return templateResolver;
}
}
my PdfService :
#Service
public class PdfService {
#Autowired
private TemplateEngine templateEngine;
public void createPDF() throws DocumentException, IOException {
Context context = new Context();
context.setVariable("name","developper.com");
String processHtml = templateEngine.process("helloworld",context);
OutputStream outputStream = new FileOutputStream("message.pdf");
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(processHtml);
renderer.layout();
renderer.createPDF(outputStream,false);
renderer.finishPDF();
outputStream.close();
}
}
my main app :
#Bean
CommandLineRunner run(PdfService pdfService) {
return args -> {
System.out.println("creating pdf...");
pdfService.createPDF();
System.out.println("pdf creation complete!");
};
}
EDIT : i managed to overcome the problem, but now i've been hit with another error :
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:772) ~[spring-boot-2.6.3.jar:2.6.3]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:753) ~[spring-boot-2.6.3.jar:2.6.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:309) ~[spring-boot-2.6.3.jar:2.6.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.6.3.jar:2.6.3]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.6.3.jar:2.6.3]
at com.example.app.AppApplication.main(AppApplication.java:35) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.6.3.jar:2.6.3]
Caused by: org.xhtmlrenderer.util.XRRuntimeException: Can't load the XML resource (using TrAX transformer). org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.
at org.xhtmlrenderer.resource.XMLResource$XMLResourceBuilder.transform(XMLResource.java:222) ~[flying-saucer-core-9.1.4.jar:na]
at org.xhtmlrenderer.resource.XMLResource$XMLResourceBuilder.createXMLResource(XMLResource.java:181) ~[flying-saucer-core-9.1.4.jar:na]
at org.xhtmlrenderer.resource.XMLResource.load(XMLResource.java:84) ~[flying-saucer-core-9.1.4.jar:na]
at org.xhtmlrenderer.pdf.ITextRenderer.setDocumentFromString(ITextRenderer.java:161) ~[flying-saucer-pdf-itext5-9.1.4.jar:na]
at org.xhtmlrenderer.pdf.ITextRenderer.setDocumentFromString(ITextRenderer.java:156) ~[flying-saucer-pdf-itext5-9.1.4.jar:na]
at com.example.app.service.PdfService.createPDF(PdfService.java:28) ~[classes/:na]
at com.example.app.AppApplication.lambda$run_again$1(AppApplication.java:74) ~[classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:769) ~[spring-boot-2.6.3.jar:2.6.3]
... 10 common frames omitted
Caused by: javax.xml.transform.TransformerException: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.
at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:794) ~[na:na]
at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:397) ~[na:na]
at org.xhtmlrenderer.resource.XMLResource$XMLResourceBuilder.transform(XMLResource.java:220) ~[flying-saucer-core-9.1.4.jar:na]
... 17 common frames omitted
Caused by: org.xml.sax.SAXParseException: Content is not allowed in prolog.
at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1251) ~[na:na]
at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:695) ~[na:na]
at java.xml/com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:782) ~[na:na]
... 19 common frames omitted
In configuration class, you need to create template engine bean and set template resolver which you have created:
#Bean
public SpringTemplateEngine templateEngine() {
var templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
return templateEngine;
}
NOTE: TemplateEngine bean is not autoconfigured.
TemplateEngine is not autoconfigured, so you need to add to your configuration something like (remember to set the TemplateResolvers)
#Bean
public TemplateEngine templateEngine() {
return new TemplateEngine();
}
or alternatively, you can just inject it in the service via
final TemplateEngine templateEngine = new TemplateEngine();

After switching to SpringBoot from TomcatServerConf Request method 'POST' not supported

Initially, I started the project with IntelliJ Idea Tomcat Local Server configuration (everything worked), but decided to use Spring Boot Application. I added the main class, changed pom.xml (delete spring-context and add spring-boot-starter-parent, spring-boot, spring-boot-starter-tomcat, spring-boot-starter-web, spring-boot-autoconfigure), after that application runs , GET-Method works, but POST - not supported. Help me please!!! Thank you!
Main.class
#SpringBootApplication(scanBasePackageClasses = {SpringConfig.class})
public class Main extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
Pom.xml to springBoot
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
Main configuration class
#Configuration
#ComponentScan("ru")
#PropertySource("classpath:application.properties")
#EnableWebMvc
public class SpringConfig implements WebMvcConfigurer {
private final ApplicationContext applicationContext;
#Autowired
public SpringConfig(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
/*
* Dispatcher configuration for serving static resources
*/
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
WebMvcConfigurer.super.addResourceHandlers(registry);
registry.addResourceHandler("/images/**").addResourceLocations("/images/");
registry.addResourceHandler("/webjars/bootstrap/4.6.0/css/**").addResourceLocations("/webjars/bootstrap/4.6.0/css/bootstrap.min.css");
registry.addResourceHandler("assets/select2-develop/**").addResourceLocations("/assets/");
registry.addResourceHandler("/css/**").addResourceLocations("/css/");
registry.addResourceHandler("/js/**").addResourceLocations("/js/");
}
/*
* Message externalization/internationalization
*/
#Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("Messages");
return messageSource;
}
#Bean
public SpringResourceTemplateResolver templateResolver(){
// SpringResourceTemplateResolver automatically integrates with Spring's own
// resource resolution infrastructure, which is highly recommended.
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(this.applicationContext);
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
templateResolver.setCharacterEncoding("UTF-8");
// HTML is the default value, added here for the sake of clarity.
templateResolver.setTemplateMode(TemplateMode.HTML);
// Template cache is true by default. Set to false if you want
// templates to be automatically updated when modified.
templateResolver.setCacheable(true);
return templateResolver;
}
#Bean
public SpringTemplateEngine templateEngine(){
// SpringTemplateEngine automatically applies SpringStandardDialect and
// enables Spring's own MessageSource message resolution mechanisms.
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
// Enabling the SpringEL compiler with Spring 4.2.4 or newer can
// speed up execution in most scenarios, but might be incompatible
// with specific cases when expressions in one template are reused
// across different data types, so this flag is "false" by default
// for safer backwards compatibility.
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding("UTF-8");
registry.viewResolver(resolver);
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://localhost:5432/postgres");
dataSource.setUsername("over");
// dataSource.setPassword("postgres"); Можно установить пароль для базы данных.
return dataSource;
}
#Bean
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(dataSource());
}
}
DispatcherSerlvet config
public class MySpringMvcDispatcherSerlvetIntitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
/* Класс знает теперь где находится spring конфигурация */
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringConfig.class};
}
/* Все http запросы от пользователя посылаем на dispatcher servlet */
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
#Override
public void onStartup(ServletContext aServletContext) throws ServletException {
super.onStartup(aServletContext);
registerCharacterEncodingFilter(aServletContext);
registerHiddenFieldFilter(aServletContext);
}
private void registerHiddenFieldFilter(ServletContext aContext) {
aContext.addFilter("hiddenHttpMethodFilter",
new HiddenHttpMethodFilter()).addMappingForUrlPatterns(null ,true, "/*");
}
private void registerCharacterEncodingFilter(ServletContext aContext) {
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
FilterRegistration.Dynamic characterEncoding = aContext.addFilter("characterEncoding", characterEncodingFilter);
characterEncoding.addMappingForUrlPatterns(dispatcherTypes, true, "/*");
}
}
This is my exeption :
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.logException - Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
Controller
#RequestMapping("/categories")
#Controller
public class CategoriesController {
private CategoriesDao categoriesDAO;
#Autowired
public void setCategoriesDAO(CategoriesDao categoriesDAO)
{
this.categoriesDAO = categoriesDAO;
}
#GetMapping
public String index(Model model) {
model.addAttribute("category", new Category());
model.addAttribute("categories", categoriesDAO.index());
return "categories/index";
}
#PostMapping
public String addCategory(#ModelAttribute("category") #Valid Category category,
BindingResult bindingResult, Model model) {
if(bindingResult.hasErrors()) {
model.addAttribute("categories", categoriesDAO.index());
return "categories/index";
}
categoriesDAO.addCategory(category);
return "redirect:categories";
}
#DeleteMapping("/{id}")
public String deleteCategory(#PathVariable("id") int id) {
categoriesDAO.deleteCategory(id);
return "redirect:/categories";
}
#GetMapping("/{id}/edit")
public String editCategory(Model model, #PathVariable("id") int id) {
model.addAttribute("editCategory", categoriesDAO.editCategory(id));
return "categories/edit";
}
#PatchMapping("/{id}")
public String updateCategory(#ModelAttribute("editCategory") Category updateCategory,
#PathVariable("id") int id) {
categoriesDAO.updateCategory(id, updateCategory);
return "redirect:{id}/edit";
}
}
To implement the configure method in the main class you could do:
#SpringBootApplication
public class Main extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
#Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder builder) {
return builder.sources(Main.class);
}
}
I think these dependencies should be enough (assuming you are using Thymeleaf):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
EDIT: Your ModelAttribute 'Category' might not be parsed successfully. Either the mapping fails, or maybe the validation? You might find out by adding an error handler and/or debugging the sessions.
Other ideas: Use #RestController instead of #Controller. Try to make the request mappings more explicit. Instead of on the class, put one on each method:
#RequestMapping(value = "/categories", produces = "application/json", method=RequestMethod.GET)
public String index(Model model) {
...
#RequestMapping(value = "/categories", produces = "application/json", method=RequestMethod.POST)
public String addCategory(#ModelAttribute("category") #Valid Category category,
BindingResult bindingResult, Model model) {
...
Thanks everyone! I found answer on my question. It was some problems with HiddenHttpMethodFilter. I just added this code in my Spring Config and extra dependencies was . It stared to work!!!
public FilterRegistrationBean<HiddenHttpMethodFilter> hiddenHttpMethodFilter() {
FilterRegistrationBean<HiddenHttpMethodFilter> filterRegistrationBean =
new FilterRegistrationBean<HiddenHttpMethodFilter>(new HiddenHttpMethodFilter());
filterRegistrationBean.setUrlPatterns(Collections.singletonList("/*"));
return filterRegistrationBean;
}

How can I pass object to thymeleaf template and access its attributes?

Is it possible to pass object let's say User (who contains 3 String attributes - name, password, detail) to thymeleaf template via context myContext.setVariable("user", myUser) and access it attributes from template like this <div th:text="${user.name}"/> ?
If so how can I do that ?
My object contains a lot of attributes and I am trying to avoid creating context with a lot of variables.
I am very new to thymeleaf so thank you for any help.
If you are using spring and thymeleaf then they should work for you like a charm. In the case it's as simple as:
private static final VAR_USER = "user"
#Autowired
private SpringTemplateEngine templateEngine;
...
public void method(User user,...) {
Map<String, Object> variables;
variables.put(VAR_USER, user);
context.setVariables(variables);
org.thymeleaf.context.Context context = new Context(locale);
String evaluated = templateEngine.process("myTemplate", context);
}
where myTemplate refers to resources/mails/myTemplate.html and it's content looks like:
<p th:text="#{email.userActivity.greeting}">Hello</p>
<p th:text="#{email.userActivity.text1}">Following user activity...</p>
<ul>
...
<li th:text="#{email.userActivity.phone(${user.phoneNumber}?: #{error.not.provided})}">Phone number:</li>
<li th:text="#{email.userActivity.membershipNumber(${user.membershipNumber}?: #{error.not.provided})}">Membership number:</li>
...
</ul>
<p th:text="#{email.userActivity.text2}">Thanks for taking care of this demand within the agreed period!</p>
<p th:text="#{email.userActivity.text3}">Regards</p>
and my User entity
public class User implements Serializable {
...
#Column(name = "membership_number")
private String membershipNumber;
#Column(name = "phone_number")
private String phoneNumber;
...
}
Then, my Thymeleaf configuration:
package my.package.config;
import my.package.MyTemplateEngine;
import org.apache.commons.lang3.CharEncoding;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;
import org.thymeleaf.templateresolver.StringTemplateResolver;
#Configuration
public class ThymeleafConfiguration {
private MyTemplateEngine templateEngine;
#Bean
#Description("Thymeleaf template resolver serving HTML 5 emails from template file")
public ITemplateResolver htmlTemplateResolver() {
ClassLoaderTemplateResolver emailTemplateResolver = new ClassLoaderTemplateResolver();
emailTemplateResolver.setPrefix("mails/");
emailTemplateResolver.setSuffix(".html");
emailTemplateResolver.setTemplateMode(TemplateMode.HTML);
emailTemplateResolver.setCharacterEncoding(CharEncoding.UTF_8);
emailTemplateResolver.setCheckExistence(true);
return emailTemplateResolver;
}
#Description("Thymeleaf template resolver serving HTML 5 emails from input string")
#Bean
public ITemplateResolver stringTemplateResolver() {
final StringTemplateResolver templateResolver = new StringTemplateResolver();
templateResolver.setTemplateMode(TemplateMode.HTML);
return templateResolver;
}
#Bean
public MyTemplateEngine createTemplateEngine() {
templateEngine = new MyTemplateEngine();
return templateEngine;
}
}
and the version of Thymeleaf that I use:
<properties>
...
<thymeleaf-layout-dialect.version>2.2.1</thymeleaf-layout-dialect.version>
<thymeleaf.version>3.0.6.RELEASE</thymeleaf.version>
...
</properties>
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.6.RELEASE</version>
</dependency>
...
</dependencies>

Thymeleaf : org.thymeleaf.exceptions.TemplateInputException

i am trying to use thymeleaf 3.0.7.RELEASEwith spring mvc java based configuration.
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.sagar")
public class MvcConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware{
#Autowired
RoleToUserProfileConverter roleToUserProfileConverter;
private ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
#Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
#Bean
public TemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setEnableSpringELCompiler(true);
engine.setTemplateResolver(templateResolver());
return engine;
}
private ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/WEB-INF/templates/");
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
public void addResourceHandlers(ResourceHandlerRegistry registry){
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
}
}
methods inside springsecurity configuration class.
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth)
throws Exception{
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(authenticationProvider());
}
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers( "/admin/list")
.access("hasRole('USER') or hasRole('ADMIN') or hasRole('DBA')")
.antMatchers("/newuser/**", "/delete-user-*").access("hasRole
('ADMIN')").antMatchers("/edit-user-*")
.access("hasRole('ADMIN') or hasRole('DBA')").and().formLogin()
.loginPage("/login")
.loginProcessingUrl("/login").usernameParameter("ssoId").
passwordParameter("password").and()
.rememberMe().rememberMeParameter("remember-me").
tokenRepository(tokenRepository)
.tokenValiditySeconds(86400).and().csrf().and().exceptionHandling()
.accessDeniedPage("/Access_Denied");
}
and my home.html file
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
this is home page using thymeleaf
</body>
</html>
my pom.xml dependencies includes
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring4</artifactId>
<version>3.0.7.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.7.RELEASE</version>
</dependency>
the spring security version is 4.2.3.RELEASE and spring version is 4.3.9.RELEASE
the errors i am getting are:-
Message Request processing failed; nested exception is
org.thymeleaf.exceptions.TemplateInputException:
An error happened during template parsing
(template: "ServletContext resource [/WEB-INF/templates/home]")
Root Cause
java.io.FileNotFoundException: Could not open ServletContext
resource [/WEB-INF/templates/home]
Root Cause
org.thymeleaf.exceptions.TemplateInputException:
An error happened during template parsing
(template: "ServletContext resource [/WEB-INF/templates/home]")
The templateResolver method needs to be fixed.
Try setting suffix
resolver.setSuffix(".html");
Try setting correct TemplateMode
resolver.setTemplateMode("HTML5");
I think this should solve the problem

Springfox Swagger2 - #ApiOperation not working

I use springfox-swagger2 for my Spring MVC REST API. Everything works good with swagger but my problem is I cannot add additional information to my swagger documentation.
Maven Dependency:
<!-- Swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.2.2</version>
</dependency>
My Swagger config class:
#Configuration
#EnableWebMvc
#EnableSwagger2
#ComponentScan("path.to.controller.package")
public class SwaggerConfig {
#Bean
public Docket customImplementation() {
return new Docket(DocumentationType.SPRING_WEB).apiInfo(apiInfo());
}
#Bean
public UiConfiguration uiConfig() {
return UiConfiguration.DEFAULT;
}
private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfo("Service API", "Simple REST Service", "0.0.1",
"mail#mail.com", "mail#mail.com", " ", " ");
return apiInfo;
}
}
My controller class:
#RestController
#RequestMapping("/persons")
public class PersonController {
Logger LOGGER = LoggerFactory.getLogger(PersonController.class);
#RequestMapping(value = "/{id}", method = RequestMethod.GET, headers = "Accept=application/json")
#ApiOperation(value = "doStuff", response = Person.class)
#ApiImplicitParams({#ApiImplicitParam(name="Authorization", value="MY DESCRIPTION")})
public #ResponseBody Person getPerson(#PathVariable String id,
#RequestHeader(value = "Authorization") String authToken) throws Exception {
//do things and return
}
}
So, calling the swagger-ui the controller is shown, the method, everything except my additional infos defined in #ApiOperation and #ApiImplicitParams. Does anyone have an idea from where the problem can come from? The params are also not in the JSON file which is created from swagger.
Try to replace your customImplementation() method by:
#Bean
public Docket customImplementation() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.build()
.apiInfo(apiInfo());
}
Build the project, and then your additional infos should appear.
EDIT: I don't know if it makes any difference, but I am using these dependencies:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.1.2</version>
</dependency>

Categories