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

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 ;
}

Related

Template might not exist or might not be accessible by any of the configured Template Resolvers springboot

I have a microservice app built-in spring boot, the main module is working at 8080 port and the other module is working at 7070 port. At /clicker endpoint I'm trying to redirect to
the site which is located on this port but always when I'm using /clicker endpoint I can see an error like this. But when I try to get [http://192.168.254.115:7070] directly from the browser, everything is working fine so I think that's not because of the bad config in the application.properties.
Error resolving template [http://192.168.254.115:7070], template might not exist or might not be accessible by any of the configured Template Resolvers
This controller works at 8080 port.
#CrossOrigin(origins = "*")
public class MainController {
#RequestMapping("/")
public String index() {
return "redirect:/login";
}
#RequestMapping("/home")
public String home(){
return "home.html";
}
#CrossOrigin
#RequestMapping("/clicker")
public ModelAndView goToClicker(HttpServletRequest request) {
//http://localhost:7070/
//http://192.168.254.115:7070/
String url = "http://" + request.getServerName() + ":" + "7070";
return new ModelAndView(url);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home</title>
<link rel="stylesheet" type="text/css" th:href="#{/styles/style.css}"/>
</head>
<body>
<div class = "main">
<div class = "container">
<button type="button">CLICKER</button>
</div>
</div>
</body>
</html>
And that's the controller which works at 7070 port.
#Controller
#CrossOrigin(origins = "*")
public class ClickerController {
#CrossOrigin
#RequestMapping("/")
public String index() {
return "clicker.html";
}
}

How to read a parameter in url coming via POST method in spring boot

The application requires driver and their locations to be registered. There are two api's one to register driver and one to save location.
The api's are
POST /api/v1/driver/register/
POST /api/v1/driver/:id/sendLocation/
The first api will request, response structure is as below
Request:
{
"name": "Rakesh123",
"email":"rakesh#abc1.com",
"phone_number":9876899979,
"license_number":"DL12CDRWG1",
"car_number":"DL1T43241"
}
Response:
{
"driverId": 2,
"name": "Rakesh123",
"email": "rakesh#abc1.com",
"phone_number": "9876899979",
"license_number": "DL12CDRWG1",
"car_number": "DL1T43241",
"location": null
}
In the second api, the ":id" will be the driver id received and contains the request body with latitude and longitude
Request:
{
"latitude": 12.972442,
"longitude": 77.580643
}
I am facing problem while reading the ":id" parameter from request. I tried printing the request URI value and that's how the request is coming
/api/v1/driver/$id/sendLocation/
The methods are written as below
1.
#PostMapping("/register")
public ResponseEntity<?> registerDriver(#RequestBody DriverDetails driver){
responseMap = new HashMap<>();
try {
DriverDetails registeredDriver = service.registerDriver(driver);
responseMap.put("driver", registeredDriver);
responseEntity = new ResponseEntity<>(responseMap, HttpStatus.CREATED);
}catch(Exception e) {
responseMap.put("status", "failure");
responseMap.put("reason", e.getMessage());
responseEntity = new ResponseEntity<>(responseMap, HttpStatus.BAD_REQUEST);
}
return responseEntity;
}
#PostMapping("/{id}/sendLocation")
public ResponseEntity<?> saveDriverLocation(#PathVariable String id, #RequestBody Location location){
responseMap = new HashMap<>();
try {
service.addLocation(Integer.parseInt(id), location);
responseMap.put("status", "success");
responseEntity = new ResponseEntity<>(responseMap, HttpStatus.ACCEPTED);
}catch(Exception e) {
responseMap.put("status", "failure");
responseMap.put("reason", e.getMessage());
responseEntity = new ResponseEntity<>(responseMap, HttpStatus.BAD_REQUEST);
}
return responseEntity;
}
Will appreciate help
Your code looks fine to me. Maybe it's a problem with the client that sends the request? Did it realy contains the Id value in the URL?
Here a small example with spring boot that reads the Id and print to console:
DemoApplication.java
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
ExampleController.java
#RestController
#RequestMapping("/api/v1/driver")
public class ExampleController {
/**
* Call this Endpoint with e.g. http://localhost:8080/api/v1/driver/123/sendLocation
*/
#PostMapping("/{id}/sendLocation")
public ResponseEntity saveDriverLocation(#PathVariable String id, #RequestBody String location) {
System.out.println("received id: " + id);
System.out.println("received location: "+ location);
return ResponseEntity.ok().build();
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

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.

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);

Jersey - Freemarker - use custom ViewProcessor

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.

Resources