flyingsaucerproject / flyingsaucer

XML/XHTML and CSS 2.1 renderer in pure Java
Other
1.97k stars 553 forks source link

Make it possible to add resources with `classpath:` prefix #216

Closed lowcasz closed 7 months ago

lowcasz commented 10 months ago

I can't generate pdf using externally loaded css stylesheet. It is generate without any styles. Images with classpath prefix are not loaded too. Everything works when I specify absolute path to file (with prefix file://), but this is not acceptable in my app.

My code:

final ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(html);
renderer.getFontResolver().addFontDirectory(properties.fonts(), EMBEDDED);
renderer.layout();
final ByteArrayOutputStream pdf = new ByteArrayOutputStream();
renderer.createPDF(pdf);
write(properties.output(), pdf.toByteArray());

My HTML:

<html lang="pl-PL">
<head>
    <title>Title</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta http-equiv="Content-Language" content="pl-PL"/>
    <link href="classpath:templates/css/stylesheet.css" rel="stylesheet" type="text/css" media="print"/>
</head>
<body>...</body>
</html>

My maven dependecies:

<?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>3.1.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>pdf-generator</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>pdf-generator</name>
    <description>pdf-generator</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf-openpdf</artifactId>
            <version>9.3.1</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
asolntsev commented 10 months ago

@lowcasz Did it ever work? Do you mean that FlyingSaucer did load resources from classpath, and this feature was broken with some release? Or it never really worked, and you just wish such a feature?

lowcasz commented 10 months ago

It was worked on my other project. HTML is copied from old project for test, it was work there. I don't see any other configuration and configuration classes between them. In old project is older version of saucer. (9.1.22)

pbrant commented 10 months ago

Some frameworks will supply a classpath:// URL handler. See e.g. https://stackoverflow.com/questions/861500/url-to-load-resources-from-the-classpath-in-java. We've done something similar internally before.

Could that be why it worked before?

I don't think this is something that FS has supplied out of the box though.

On Fri, Oct 6, 2023 at 1:13 PM Cezary Hadrzyński @.***> wrote:

It was worked on my other project.

— Reply to this email directly, view it on GitHub https://github.com/flyingsaucerproject/flyingsaucer/issues/216#issuecomment-1750436113, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAF42FAAXLXT4DB3WVO7S3X57RWZAVCNFSM6AAAAAA5U3E442VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONJQGQZTMMJRGM . You are receiving this because you are subscribed to this thread.Message ID: @.***>

lowcasz commented 10 months ago

I don't know, maybe... Do you know any dependency, especially spring dependency which can do it in background? It can helps me to find it, I don't see any additional parameters, configuration or classes which do it.

pbrant commented 10 months ago

I do not, I'm afraid.

On Fri, Oct 6, 2023 at 1:28 PM Cezary Hadrzyński @.***> wrote:

I don't know, maybe... Do you know any dependency, especially spring dependency which can do it in background? It can helps me to find it, I don't see any additional parameters, configuration or classes which do it.

— Reply to this email directly, view it on GitHub https://github.com/flyingsaucerproject/flyingsaucer/issues/216#issuecomment-1750468997, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAF42EOC7HEPBEXOGL4NODX57TMZAVCNFSM6AAAAAA5U3E442VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONJQGQ3DQOJZG4 . You are receiving this because you commented.Message ID: @.***>

asolntsev commented 7 months ago

@lowcasz implemented in https://github.com/flyingsaucerproject/flyingsaucer/pull/241, released version 9.3.2 today.

andrzej-talarek commented 7 months ago

Funny thing, but in my case it worked perfectly fine (classpath:/static/css/custom.css) in 9.3.1 version and broke with 9.3.2 :(. It's broken both for bootJar task, that I'm using for system development usually and normal building jar for running it with java -jar. Can't upgrade.

2023-12-31 06:18:15.880 ERROR -  o.a.j.l.DirectJDKLog : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.NullPointerException: Cannot invoke "java.net.URL.toString()" because "resource" is null] with root cause
java.lang.NullPointerException: Cannot invoke "java.net.URL.toString()" because "resource" is null
    at org.xhtmlrenderer.swing.NaiveUserAgent.resolveURI(NaiveUserAgent.java:370)
    at org.xhtmlrenderer.context.StyleReference.getStylesheets(StyleReference.java:224)
    at org.xhtmlrenderer.context.StyleReference.setDocumentContext(StyleReference.java:85)
    at org.xhtmlrenderer.pdf.ITextRenderer.setDocument(ITextRenderer.java:183)
    at org.xhtmlrenderer.pdf.ITextRenderer.setDocument(ITextRenderer.java:144)
    at org.xhtmlrenderer.pdf.ITextRenderer.setDocumentFromString(ITextRenderer.java:167)
    at org.xhtmlrenderer.pdf.ITextRenderer.setDocumentFromString(ITextRenderer.java:160)
asolntsev commented 7 months ago

@andrzej-talarek Thank you for the feedback. First of all, I assume that FS 9.3.1 didn't really load custom.css file, but just silently ignored it. And FS 9.3.2 started searching this file in classpath and complaining if the file cannot be found.

Are you sure you have folder static in the classpath?

If yes, how can I reproduce the problem? Could you create a simple reproducible example?

andrzej-talarek commented 7 months ago

I'm 100% sure it worked fine - I've used several included styles (custom ones and bootstrap styles) and I know styles worked OK then (looking at final pdf). Since it's spring-boot app, I'm not sure it would be that easy, but I can try to prepare a repo with as little code as it only requires.

pbrant commented 7 months ago

@andrzej-talarek This should be fixed in #250.

asolntsev commented 7 months ago

@andrzej-talarek The fix #250 has been released as FlyingSaucer 9.4.1 Can you please check if it helps?

andrzej-talarek commented 7 months ago

Confirmed, works perfectly again :-). Great thanks @asolntsev !