Search code examples
javathymeleafinputstreamtemplate-engine

Java - Thymeleaf - How to process an InputStream in TemplateEngine ? (Stand-alone Templating)


I'm facing a scenario where I need to process an HTML template (index.html) which is unzipped from a ZIP file (via ZipInputStream) via the Thymeleaf TemplateEngine with my Data POJO. So what I have right now is the InputStream of the unzipped template file. I believe TemplateResolver will help me to solve this case.

TemplateResolver is a generic implementation, allowing you to specify your own IResourceResolver implementation that obtains input streams in whichever way you need. You can create your own resource resolver (implementing IResourceResolver) and set it to a TemplateResolver instance.

How to accomplish this task? Any insights ?

    // index.html is the byte[] here, 'resourceData'
    InputStream fileinputStream = new ByteArrayInputStream(resourceData);
    FileResourceResolver fileResourceResolver = new FileResourceResolver();
    TemplateResolver resolver = new TemplateResolver();
    resolver.setTemplateMode("XHTML");
    resolver.setSuffix(".html");
    resolver.setResourceResolver(fileResourceResolver);
    TemplateEngine engine = new TemplateEngine();
    engine.setTemplateResolver(resolver);
    Context context = new Context(Locale.US);
    context.setVariable("data", myDataPojo);
    return engine.process("index", context);

Solution

  • I found the way :) Hope anyone facing the same issue can use this solution.

    private static class CustomTemplateResolver implements IResourceResolver {
            private InputStream inputStream;
            private String templateName;
    
            public CustomTemplateResolver(String templateName, InputStream inputStream) {
                this.templateName = templateName;
                this.inputStream = inputStream;
            }
    
            @Override
            public String getName() {
                return templateName;
            }
    
            @Override
            public InputStream getResourceAsStream(TemplateProcessingParameters templateProcessingParameters, String resourceName) {
                return inputStream;
            }
        }
    

    The Test Class

    @Test
        public void createPdfFromZip() throws Exception {
            String fileBundleZipFile = "sample.zip";
            String templateFileName = "index";
            String fileExt = ".html";
            ClassPathResource resourceZip = new ClassPathResource(fileBundleZipFile);
            ZipFile zipFile = new ZipFile(new File(this.getClass().getResource("/" + fileBundleZipFile).getFile()));
            ZipInputStream zipInputStream = new ZipInputStream(resourceZip.getInputStream());
            ZipEntry zipEntry = zipInputStream.getNextEntry();
            while (zipEntry != null) {
                if (zipEntry.getName().equals(templateFileName + fileExt)) {
                    TemplateResolver resolver = new TemplateResolver();
                    resolver.setTemplateMode("XHTML");
                    resolver.setSuffix(fileExt);
                    resolver.setResourceResolver(new CustomTemplateResolver(templateFileName, zipFile.getInputStream(zipEntry)));
                    MyPojo data= getData();
                    TemplateEngine engine = new TemplateEngine();
                    engine.setTemplateResolver(resolver);
                    Context context = new Context(Locale.US);
                    context.setVariable("data", data);
                    String dataHTMLString = engine.process(templateFileName, context);
                    Path tempFile = Files.createTempFile("unzipped-data-html", ".pdf");
                    createDataPdfWithCss(tempFile, dataHTMLString);
                }
                zipEntry = zipInputStream.getNextEntry();
            }
            zipInputStream.closeEntry();
            zipInputStream.close();
        }