Images and css do not load on the page when executed by the jar

Asked

Viewed 129 times

1

Hello, I see you’ve had similar questions to my own but you haven’t answered my question. I’m developing an API that goes into a database, takes the data and returns a pdf report using Thymeleaf and Flying saucer. When I run the program through the IDE( which in the case is spring boot) everything works normally. But when I run through the jar, the images don’t appear and neither does css. I’ve already checked inside the jar and as many of my images as the css are inside it. The dependencies of Flying Saucer (who adds the images and css) tbm are. Here are the details, first the structure of my project:

![Estrutura do projeto

Below follows the code where the rendering engine, use Thymeleaf, Jtidy and Flying Sauce to generate a pdf:

@Service
public class GeneratePdfService {

    private static final String OUTPUT_FILE = "report.pdf";
    private static final String UTF_8 = "UTF-8";

    @Autowired
    private AgfService service;

    @Autowired
    private DateUteisComponent dataUtil;

    public OutputStream generatePdf(Object dataReport, String template) throws Exception {

        String renderedHtmlContent = generateHtml(dataReport, template);
        String xHtml = convertToXhtml(renderedHtmlContent);

        ITextRenderer renderer = new ITextRenderer();
        renderer.getFontResolver().addFont("template/Code39.ttf", IDENTITY_H, EMBEDDED);

        String baseUrl = FileSystems.getDefault().getPath("src", "main", "resources").toUri().toURL().toString();
        renderer.setDocumentFromString(xHtml, baseUrl);
        renderer.layout();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        renderer.createPDF(outputStream);
        outputStream.close();
        return outputStream;
    }

    private String convertToXhtml(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(UTF_8));
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        tidy.parseDOM(inputStream, outputStream);
        return outputStream.toString(UTF_8);
    }

    public String generateHtml(Object dataReport, String template) {
        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        templateResolver.setPrefix("/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode(HTML);
        templateResolver.setCharacterEncoding(UTF_8);

        TemplateEngine templateEngine = new TemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);

        Date instanteAtual = new Date();
        String[] instanteAtualF = dataUtil.formatDateInstant(instanteAtual);

        Context context = new Context();
        context.setVariable("instante", instanteAtualF);
        context.setVariable("data", dataReport);

        String renderedHtmlContent = templateEngine.process(template, context);

        return renderedHtmlContent;
    }

This class is as a service and the class that uses this service tbm is a service as follows::

public OutputStream gerarRelatorioPrePostagemPorEstadoPdf(String estado) throws Exception {
    List<PrePostagemBean> prePostagensBeans = generateDataForReportForUf(estado);
    ByteArrayOutputStream outputStream = (ByteArrayOutputStream) this.generatePdfService.generatePdf(prePostagensBeans, "template/templateE");
    this.sendConfirmationHtmlEmail(outputStream.toByteArray());
    return outputStream;
}

Finally this service is called from a Rest controller:

@GetMapping(value = "agfs/{estado}/pdf", produces = "application/pdf")
public ResponseEntity<?> prepostReportEstadoPdf(@PathVariable("estado") String estado) throws Exception {
    ByteArrayOutputStream os = (ByteArrayOutputStream) this.agfService.gerarRelatorioPrePostagemPorEstadoPdf(estado);
    byte[] content = os.toByteArray();
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_PDF);
    ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(content, headers, HttpStatus.OK);
    return response;
}

The goal is to return on the screen a pdf with the report. The problem is that when I run the project from the spring boot, everything works perfectly and I have the answer as follows:: inserir a descrição da imagem aqui

However when I do and deploy (via the command mvn clean install) and I put the jar in any folder of my machine and I raise application by this jar, css and images do not appear and I get the following answer in pure HTML:

inserir a descrição da imagem aqui

The strange thing is that when I run the jar without moving it, that is, inside the target folder generated in the Maven’s own structure the css and image appear. But as I said before, when I move this jar and run it in another environment any css and image are lost.

Below follows me HTML tbm to help:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">

<head>
<meta charset="UTF-8"></meta>
<link rel="stylesheet" type="text/css" media="all" href="static/css/style.css"/>
<script type="text/javascript" src="static/js/jquery.js"></script>
<link rel="stylesheet" type="text/css" media="all" href="static/css/bootstrap.css"/>
<script type="text/javascript" src="static/js/bootstrap.js" ></script>
</head>

<body>
    <div class='header' th:include="template/header::header"></div>


    <h1 class="tit-relatorio">Relatorio Agfs x Pre Postagem</h1>

    <div class="periodo">Período: [[${data[0].dataInicio}]] até [[${data[0].dataFim}]]</div>

    <div class="periodo">Estado: [[${data[0].empresa.uf}]] </div>

    <div class="emitido">Relatório emitido em [[${instante[0]}]] as [[${instante[1]}]]</div>

    <hr></hr>

    <div class="div-table table-sm p-3" style="max-width:600px">
        <table class="table table-striped mb-3">
            <thead class="thead-dark">
                <tr>
                    <th scope="col">Agf:</th>
                    <th scope="col">Fizeram Pré-Postagem:</th>
                    <th scope="col">Não fizeram Pré-Postagem:</th>
                </tr>
            </thead>
            <tr th:each="data : ${data}">
                <td scope="row" th:text="${data.empresa.empresa}">nome</td>
                <td th:text="${data.qtdPrePost}">prePost</td>
                <td th:text="${data.qtdNoPrePost}">noPrePost</td>
            </tr>
        </table>
    </div>

    <div class="mt-1">
        <div><i>A segunda coluna indica a quantidade de clientes ativos que fizeram pré-postagem</i></div>
        <div><i>A terceira coluna indica a qauntidade de clientes ativos que não fizeram pré-postagem</i></div>
    </div>


    <div class='footer' th:include="template/footer::footer"></div>
</body>

</html>

I tried to formulate my question in the best possible way, but any doubt or criticism only command that I explain or rephrase the question. I really need to find the solution to this problem because I have a deadline

  • 1

    Hello @Satyan, welcome to Sopt, before you start a look at our [Tour]. On your question, you may need to add more information about your project so the community can better understand your problem and help you get a solution. = D

  • 1

    Okay, I’ll read yes and redo, I’m new around here, thanks!

  • 1

    @Icaromartins tried to improve my question and leave in the standards of the site, any criticism just say that I set

1 answer

1

Oops, I found the problem, this in the part:

String baseUrl = FileSystems.getDefault().getPath("src", "main", "resources").toUri().toURL().toString();
    renderer.setDocumentFromString(xHtml, baseUrl);

Because when I am running by the jar the path is not really, so I had to define a path for PROD and another for DEV, for pPROD was as follows:

String baseUrl = "jar:file:" + System.getProperty("user.dir") + "/joaquina.reports.jar!/BOOT-INF/classes!/";

Browser other questions tagged

You are not signed in. Login or sign up in order to post.