Jersey - Freemarker - use custom ViewProcessor - jersey

My template is rendered but without the freemarker treatments.
the output is
<html>
<body>
<h1>Welcome ${user}</h1>
</body>
</html>
The variable user has not been replaced by its value.
So I'm not sure Jersey know something about my custom ViewProcessor. How can I say explicitly to Jersey that I want to use the Freemarker ViewProcessor.
I have seen the following sample but it doesn't help
http://search.maven.org/#browse%7C-1697896452
To sum up I have :
in my pom.xml
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-freemarker</artifactId>
<version>1.12</version>
</dependency>
in my JerseyServletModule
Map<String, String> params = new HashMap<String, String>();
params.put("com.sun.jersey.freemarker.templateBasePath", "freemarker");
serve("/*").with(GuiceContainer.class, params);
in my TestResource
#Path("/test")
#GET
#Produces("text/html")
public Viewable getMytestView() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("user", "Peter");
return new Viewable("/test.ftl", map);
}
in my src/main/resources/freemarker/test.ftl
<html>
<body>
<h1>Welcome ${user}</h1>
</body>
</html>
Thanks in advance for your help.

Ok it works now. Sorry, it's certainly a cache problem.

Related

Bootsrap not working with spring boot thymeleaf pdf template

I have a problem adding bootstrap into my thymeleaf template. I want to export that template as pdf.
Bootsrap is not applied to my template. I tried webjars and static bootsrap js and css files but it doesn't work. Is there any other way that i can do? These are webjars links that I have added inside html;
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" th:href="#{webjars/bootstrap/css/bootstrap.min.css}" type="text/css"/>
<script th:src="#{webjars/bootstrap/js/bootstrap.min.js}"></script>
<script th:src="#{webjars/jquery/jquery.min.js}"></script>
</head>
This is java code;
public byte[] getReportByTestId(Long testId, String templateName) throws IOException, DocumentException {
Optional<Test> test = testRepository.findById(testId);
if (test.isPresent()) {
Test _test = test.get();
ObjectMapper oMapper = new ObjectMapper();
Map map = oMapper.convertValue(_test, Map.class);
Context context = new Context();
context.setVariables(map);
String htmlContentToRender = templateEngine.process(templateName, context);
String xHtml = xhtmlConvert(htmlContentToRender);
ITextRenderer renderer = new ITextRenderer();
String baseUrl = FileSystems
.getDefault()
.getPath("src", "main", "resources", "templates")
.toUri()
.toURL()
.toString();
renderer.setDocumentFromString(xHtml, baseUrl);
renderer.layout();
ByteOutputStream outputStream = new ByteOutputStream();
renderer.createPDF(outputStream);
byte[] pdfAsBytes = outputStream.getBytes();
outputStream.close();
return pdfAsBytes;
}
return null;
}
private String xhtmlConvert(String html) throws UnsupportedEncodingException {
Tidy tidy = new Tidy();
tidy.setInputEncoding("UTF-8");
tidy.setOutputEncoding("UTF-8");
tidy.setXHTML(true);
ByteArrayInputStream inputStream = new ByteArrayInputStream(html.getBytes(StandardCharsets.UTF_8));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
tidy.parseDOM(inputStream, outputStream);
return outputStream.toString("UTF-8");
}
When I add like this;
<script th:src="#{../static/vendor/bootstrap5/bootstrap.min.js}"></script>
It partially works. Only colors are applied.
Thanks for any help.

spring-boot-2.0.6 freemarker mvc View print request model values twice

I am using freemarker view with spring-boot-2.0.6.RELEASE,
But my ftl view print request model value twice in HTML like "${errorTitle}" -> "PG ErrorPGError" .
If anybody has a solution, please let me know the way.
I am struggling with these problems for 3 days.
[freemarker configuration bean]
#Bean
public FreeMarkerConfigurer freemarkerConfig()throws IOException, TemplateException {
final FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
freeMarkerConfigurer.setTemplateLoaderPath("classpath:/WEB-INF/view/");
Properties settings = new Properties();
settings.setProperty(
freemarker.template.Configuration.TEMPLATE_EXCEPTION_HANDLER_KEY, "rethrow");
freeMarkerConfigurer.setFreemarkerSettings(settings);
freeMarkerConfigurer.setDefaultEncoding("UTF-8");
return freeMarkerConfigurer;
}
[/paygate/error.ftl]
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Error Page</title>
</head>
<body>
<h1>${errorTitle}</h1>
<p>${errorMessage}</p>
</body>
</html>
[pom.xml]
:::
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
:::
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
#CrossOrigin
#SkipSessionCheck
#GetMapping("/error)
public ModelAndView errorView(#RequestParam("errorMessage") String errorMessage) throws ResultCodeException {
logger.error(AppUtil.excetionToString(e)) ;
ModelAndView model = new ModelAndView();
model.addObject("errorTitle", "PG Error") ;
model.addObject("errorMessage", errorMessage) ;
model.setViewName("paygate/error");
return model ;
}

MimeMessageHelper Spring boot to send email

I am using spring boot to sent an email. Code snippet from my email service
private #Autowired JavaMailSender mailSender;
AND
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message,
MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED, StandardCharsets.UTF_8.name());
helper.setTo(bo.getToEmails().parallelStream().toArray(String[]::new));
helper.setBcc(bo.getBccEmails().parallelStream().toArray(String[]::new));
helper.setCc(bo.getCcEmails().parallelStream().toArray(String[]::new));
helper.setText(htmlBody, true);
helper.setText(textBody, false);
helper.setSubject(bo.getSubject());
helper.setFrom(new InternetAddress(bo.getFromEmail(),bo.getSenderLabel()));
First I set the htmlBody and then textBody
helper.setText(htmlBody, true);
helper.setText(textBody, false);
it override htmlBody to textBody . How can I send both text and html body using org.springframework.mail.javamail.MimeMessageHelper; any update ?
You can use thymeleaf as your HTML template engine.
Sample HTML code:
MySampleHTML.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
<title>Sample Email</title>
</head>
<body>
<div th:text="${sampleText}"></div>
</body>
<html>
Sample Java Code:
public class EmailSample {
#Autowired
private JavaMailSender mailSender;
#Autowired
private TemplateEngine templateEngine; // From Thymeleaf
public void initiateEmailSend() {
String processedHTMLTemplate = this.constructHTMLTemplate();
// Start preparing the email
MimeMessagePreparator preparator = message -> {
MimeMessageHelper helper = new MimeMessageHelper(message, MimeMessageHelper.MULTIPART_MODE_MIXED, "UTF-8");
helper.setFrom("Sample <sample#example.com>");
helper.setTo("recipient#example.com");
helper.setSubject("Sample Subject");
helper.setText(processedHTMLTemplate, true);
};
mailSender.send(preparator); //send the email
}
// Fills up the HTML file
private String constructHTMLTemplate() {
Context context = new Context();
context.setVariable("sampleText", "My text sample here");
return templateEngine.process("MySampleHTML", context);
}
}
And include thymeleaf on your pom.xml
<!-- For email HTML templating -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
NOTE: Put the MySampleHTML.html file on resources/templates/ folder for thymeleaf to see it.
instead of
helper.setText(htmlBody, true);
helper.setText(textBody, false);
Use
helper.setText(htmlBody, textBody);

How to get the session id in FTL

I want the current session id in the ftl page.
I tried many things with the Session (HttpSessionHashModel) available but not able to get the id?
Getting a request header also do my job.
Is there any way to get any of these item in my FTL?
you can put the parameter in your FTL file with java servlet.
I think your project work like this:
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
try
{
Map dataModel = new HashMap();
dataModel.put("session_id", req.getSession().getId());
Configuration cfg = new Configuration();
Template tmpl = cfg.getTemplate("test.ftl");
tmpl.process(dataModel, resp.getWriter());
}
catch (TemplateException ex) {
throw new IOException(ex);
}
}
file test.ftl as
<html>
<head></head>
<body>
<p> ${session_id!""} </p>
</body>
</html>
FreeMarker doesn't expose anything by default. It doesn't even know what servlets are. So it depends on the web application framework your are using. (Unless, you are using freemarker.ext.servlet.FreeMarkerServlet.) Or, you can put these into the data-model directly.

Handling MultipartException with Spring Boot and display error page

I have a very simple file upload set up with Spring Boot.
I was wondering if there was an easy way to display an error page when the maximum file size is exceeded.
I have uploaded a very simple example of what I'm trying to achieve on github.
Basically, the idea is to catch the MultipartException in a global Spring exception handler:
#ControllerAdvice
public class UploadExceptionHandler {
#ExceptionHandler(MultipartException.class)
public ModelAndView handleError(MultipartException exception) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("error", exception.getMessage());
modelAndView.setViewName("uploadPage");
return modelAndView;
}
}
The controller which handles the file upload is really simple:
#RequestMapping("/")
public String uploadPage() {
return "uploadPage";
}
#RequestMapping(value = "/", method = RequestMethod.POST)
public String onUpload(#RequestParam MultipartFile file) {
System.out.println(file.getOriginalFilename());
return "uploadPage";
}
And the uploadPage.html thymeleaf template associated with it too:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
<title>Upload</title>
</head>
<body>
<div style="color: red" th:text="${error}" th:if="${error}">
Error during upload
</div>
<form th:action="#{/}" method="post" enctype="multipart/form-data">
<input type="file" id="file" name="file"/>
<button type="submit" name="save">Submit</button>
</form>
</body>
</html>
The idea is to display an error message in the same upload page when the file is too big.
It was my understanding that one would configure Spring's MultipartResolver to resolve exceptions lazily and be able to catch those exceptions at Spring's level (MVC exception handlers) but this code does not seem to help:
#Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
public StandardServletMultipartResolver multipartResolver() {
StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
multipartResolver.setResolveLazily(true);
return multipartResolver;
}
So before I resort to extreme measures like a filter or extending the MultipartResolver...
Do you know a clean way to handle those exceptions with Spring MVC?
Answer
Thanks to #rossen-stoyanchev.
Here is what I ended up doing:
#RequestMapping("uploadError")
public ModelAndView onUploadError(HttpServletRequest request) {
ModelAndView modelAndView = new ModelAndView("uploadPage");
modelAndView.addObject("error", request.getAttribute(WebUtils.ERROR_MESSAGE_ATTRIBUTE));
return modelAndView;
}
#Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return container -> container.addErrorPages(new ErrorPage(MultipartException.class, "/uploadError"));
}
Works like a charm and feels like an elegant solution.
I updated the project on github if someone is interested.
Many thanks!
Multipart request parsing happens before a handler is selected and hence there is no #Controller and therefore no #ControllerAdvice to speak of yet. You can use an ErrorController (see http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-error-handling) for that.
BTW you don't need #RequestParam. It's enough that the argument type is MultipartFile.

Resources