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
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";
}
}
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>
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.
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);
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.