diff options
| author | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2026-08-15 10:51:11 +0200 |
|---|---|---|
| committer | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2026-08-15 10:51:11 +0200 |
| commit | 2b1841e17533543d1cb15220ca86a2a37c853daf (patch) | |
| tree | 01b940cb06c5abc36704d2d4853343ee7b38ce02 /pom.xml | |
| parent | 5700bbcb89186e432c5c7dd232b61c052de8e784 (diff) | |
Die Web-App rechnet im Browser statt auf dem Server
Bisher lief die Weboberfläche auf einem JDK-HttpServer: Uploads landeten als
temporäre Dateien auf dem Server, die Synopse entstand dort. Das kostete
Betrieb (systemd, Reverse Proxy, Rate-Limiting, Timeouts) und verlangte ein
Datenschutzversprechen, das nur zusicherbar, nicht nachprüfbar war — gerade
Entwurfstexte verließen den Rechner der Nutzer:innen.
Neu übersetzt `./mvnw -Pwasm package` dieselbe Pipeline mit GraalVM Web Image
(`native-image --tool:svm-wasm`) nach WebAssembly, PDFBox eingeschlossen.
Ausgeliefert werden nur noch statische Dateien; gerechnet wird im Browser.
Die erzeugte Synopse ist byteweise identisch mit der der Befehlszeile
(SHA-256 verglichen für IfSG 48/27/21 und BayJG 151/3/54).
Die Befehlszeile bleibt unberührt: `./mvnw package` erzeugt unverändert das
JAR, alle Optionen und Meldungstexte sind gleich, das Wasm-Profil ist rein
additiv und verlangt Oracle GraalVM 25.1+ (die CE hat kein Web Image).
Portabilitätsschnitt (nützt beiden Fassungen):
* `Quelle` (Name + Bytes) ersetzt `Path` in der Pipeline; nur die
Befehlszeile kennt noch ein Dateisystem. Der Name trägt genau den
bisherigen `getFileName()`-Text, damit Warnungen und Quellenzeile
wortgleich bleiben.
* `DateiTyp` erkennt PDF/XML/Klartext an den Signaturbytes. Tika entfällt —
eine schwergewichtige Abhängigkeit samt ServiceLoader- und
XML-Konfiguration weniger, was der Wasm-Übersetzung unmittelbar zugutekommt.
Vier Eigenheiten von Web Image, die der Quelltext jeweils an Ort und Stelle
vermerkt:
* `java.util.zip.Inflater` ist nicht angebunden (GR-65205), ohne Inflate ist
kein PDF lesbar. `InflaterErsatz` substituiert ihn durch jzlib.
* Typisierte JS-Felder lassen sich nicht nach `byte[]` umsetzen
(„byteArrayHub is not defined“); der Dateiinhalt wandert als Base64.
* JULs Standardformatter ruft `StackWalker`, den es dort nicht gibt.
* Im Worker fehlt `document.currentScript`, worauf die Laufzeit das
Wasm-Modul neben `worker.js` sucht; die VM wird deshalb mit ausdrücklichem
Pfad ein zweites Mal gestartet.
Die Reachability-Metadaten stammen aus einem Lauf des Tracing-Agents über die
Pipeline; die PDFBox- und FontBox-Ressourcen sind als Globs ergänzt, sonst
scheitern PDFs an „Could not find referenced cmap stream Identity-H“.
Entfallen: WebMain, UploadHandler, StaticHandler, Multipart und die
systemd-Unit. Die nginx-Vorlage liefert jetzt statische Dateien aus, und die
Datenschutzseite sagt, was nun stimmt: Die Dateien verlassen den Rechner
nicht.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Change-Id: I38faf2ac0f764d601f080d4276babe4747773683
Diffstat (limited to 'pom.xml')
| -rw-r--r-- | pom.xml | 150 |
1 files changed, 142 insertions, 8 deletions
@@ -19,6 +19,7 @@ <enforced.maven-version>3.9.0</enforced.maven-version> + <build-helper-plugin.version>3.6.0</build-helper-plugin.version> <compiler-plugin.version>3.15.0</compiler-plugin.version> <dependency-plugin.version>3.11.0</dependency-plugin.version> <enforcer-plugin.version>3.6.3</enforcer-plugin.version> @@ -33,12 +34,12 @@ <assertj.version>3.27.7</assertj.version> <java-diff-utils.version>4.17</java-diff-utils.version> <jboss-logging.version>3.6.3.Final</jboss-logging.version> + <jzlib.version>1.1.5</jzlib.version> <jspecify.version>1.0.0</jspecify.version> <junit.version>5.13.4</junit.version> <pdfbox.version>3.0.8</pdfbox.version> <picocli.version>4.7.7</picocli.version> <slf4j.version>2.0.18</slf4j.version> - <tika.version>3.3.1</tika.version> </properties> <dependencyManagement> @@ -86,13 +87,6 @@ <version>${slf4j.version}</version> </dependency> - <!-- Document type detection --> - <dependency> - <groupId>org.apache.tika</groupId> - <artifactId>tika-core</artifactId> - <version>${tika.version}</version> - </dependency> - <!-- PDF text extraction --> <dependency> <groupId>org.apache.pdfbox</groupId> @@ -267,4 +261,144 @@ </build> + <profiles> + + <!-- + Browserfassung: übersetzt dieselbe Pipeline mit GraalVM Web Image nach WebAssembly. + Ausdrücklich anzufordern (`-Pwasm`); der Standard-Build bleibt unberührt und braucht + kein GraalVM. + + Voraussetzung: Oracle GraalVM 25.1+ (Web Image ist dort enthalten, in der CE nicht): + + JAVA_HOME=/pfad/zu/oracle-graalvm ./mvnw -Pwasm package + + Ergebnis: target/web/ — aendggner.js, aendggner.js.wasm und die statischen Seiten. + --> + <profile> + <id>wasm</id> + + <properties> + <native-image.executable>${java.home}/bin/native-image</native-image.executable> + <wasm.output.directory>${project.build.directory}/web</wasm.output.directory> + <!-- + Die Option „release 21“ beschränkte den Modulpfad auf die dokumentierte JDK-API; die + Web-Image-API des GraalVM wäre damit unsichtbar. Deshalb hier source/target statt + release — übersetzt wird ohnehin nur mit dem GraalVM, gegen dessen eigene Klassen. + --> + <maven.compiler.release/> + <maven.compiler.source>21</maven.compiler.source> + <maven.compiler.target>21</maven.compiler.target> + </properties> + + <dependencies> + <!-- + Reines Java-zlib. Web Image bindet die nativen zlib-Funktionen des JDK nicht an + (GR-65205); ohne Inflate ist kein PDF lesbar. Siehe + src/wasm/java/.../InflaterErsatz.java. + --> + <dependency> + <groupId>org.jruby</groupId> + <artifactId>jzlib</artifactId> + <version>${jzlib.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + + <!-- Der Wasm-Quellbaum kommt nur in diesem Profil hinzu: Er braucht die + Web-Image-API und svm.jar, die es nur im GraalVM gibt. --> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>${build-helper-plugin.version}</version> + <executions> + <execution> + <id>wasm-quellen</id> + <phase>generate-sources</phase> + <goals> + <goal>add-source</goal> + </goals> + <configuration> + <sources> + <source>src/wasm/java</source> + </sources> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <compilerArgs> + <arg>-Aproject=${project.groupId}/${project.artifactId}</arg> + <arg>--add-modules</arg> + <arg>org.graalvm.webimage.api</arg> + </compilerArgs> + <annotationProcessorPaths> + <path> + <groupId>info.picocli</groupId> + <artifactId>picocli-codegen</artifactId> + <version>${picocli.version}</version> + </path> + </annotationProcessorPaths> + </configuration> + </plugin> + + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <executions> + <execution> + <id>statische-seiten</id> + <phase>package</phase> + <goals> + <goal>copy-resources</goal> + </goals> + <configuration> + <outputDirectory>${wasm.output.directory}</outputDirectory> + <resources> + <resource> + <directory>src/main/resources/eu/mulk/aendggner/web</directory> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <executions> + <execution> + <id>web-image</id> + <phase>package</phase> + <goals> + <goal>exec</goal> + </goals> + <configuration> + <executable>${native-image.executable}</executable> + <arguments> + <argument>--tool:svm-wasm</argument> + <!-- Der Textzwischenschritt (aendggner.js.wat) wird sonst mehrere hundert + Megabyte groß; auf die Größe des .wasm hat das keinen Einfluss. --> + <argument>-H:WasmComments=NONE</argument> + <argument>-classpath</argument> + <classpath/> + <argument>-o</argument> + <argument>${wasm.output.directory}/aendggner</argument> + <argument>eu.mulk.aendggner.wasm.BrowserMain</argument> + </arguments> + </configuration> + </execution> + </executions> + </plugin> + + </plugins> + </build> + </profile> + + </profiles> + </project> |
