3

I'm following the Spring Getting Started tutorials and I'm breaking my brains on how to do something that should be relatively simple like accessing the result of another path in the same Controller.

What I'm trying to do:

  1. Return a filled Thymeleaf template as HTML to the browser <- this works out of the box
  2. Return the same page as a pdf

GreetingController:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.thymeleaf.TemplateEngine;

@Controller
@RequestMapping(path = "/")
public class GreetingController {

    @Autowired private TemplateEngine templateEngine;

    @RequestMapping(value = "/index", method = RequestMethod.GET, produces = "application/html")
    public String html(Model model) {
        model.addAttribute("some_data", some_data.getIt());
        return "some_template";
    }

    @RequestMapping(value = "/pdf", method = RequestMethod.GET, produces = "application/pdf")
    public String pdf() {
        // Option 1: get HTML output from html path
        // Option 2: put the same data in some_template via the template engine and get the resulting HTML
        // write HTML to a file using FileWriter
        // then print the temporary file with HTML to PDF via wkhtml2pdf
        return "generated_pdf";
    }

}`

Maybe I'm going about this all wrong and there is a much easier way to get the filled HTML, please advise.

EDIT:

Gradle dependencies for people trying to do something similar:

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.springframework.boot:spring-boot-starter-thymeleaf")
    compile("org.springframework.boot:spring-boot-devtools")
    testCompile("org.springframework.boot:spring-boot-starter-test")
}
2
  • 1
    Try this ? https://stackoverflow.com/questions/16652760/return-generated-pdf-using-spring-mvc Commented May 23, 2019 at 16:24
  • 1
    Just setting produces will not work here. when you return generated_pdf it tries to show generated_pdf.html since your View Resolver is Thymeleaf Commented May 23, 2019 at 16:26

1 Answer 1

2

If you're interested in obtaining the generated HTML, the easiest solution is probably to use Thymeleaf's TemplateEngine, like you already did:

Context context = new Context(Locale.getDefault());
context.setVariable("some_data", someData.getIt());
String html = templateEngine.process("some_template", context);

After that, you could process it with any HTML to PDF library. For example, if you're using Flying Saucer, you could write something like this:

try (ServletOutputStream stream = response.getOutputStream()) {
    ITextRenderer renderer = new ITextRenderer();
    renderer.setDocumentFromString(html);
    renderer.layout();
    renderer.createPDF(stream);
    renderer.finishPDF();
} catch (IOException | DocumentException ex) {
    // Error handling
}

Since ITextRenderer allows you to directly write to an OutputStream, you could use HttpServletResponse.getOutputStream() to do this:

@GetMapping("/pdf")
public void pdf(HttpServletResponse response) {
    // Generate HTML + PDF
}
Sign up to request clarification or add additional context in comments.

1 Comment

Worked like a charm! Since iText requires commercial licensing I'll explore different stream-based options like wkhtmltopdf and the openPDF fork of iText.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.