jamesnetherton commented on code in PR #9078:
URL: https://github.com/apache/camel-quarkus/pull/9078#discussion_r3911628626
##########
extensions/langchain4j-ingest/deployment/src/main/java/org/apache/camel/quarkus/component/langchain4j/ingest/deployment/Langchain4jIngestProcessor.java:
##########
@@ -68,11 +74,93 @@ FeatureBuildItem feature() {
@BuildStep
AdditionalBeanBuildItem beans() {
return AdditionalBeanBuildItem.builder()
- .addBeanClasses(IngestRoutes.class)
+ .addBeanClasses(IngestRoutes.class, IngestBeanResolver.class)
.setUnremovable()
.build();
}
+ /**
+ * The documented PDF recipe adds {@code tika-parser-pdf-module}, which
drags
+ * {@code jaxb-runtime} → {@code angus-activation} into the image. Angus'
own GraalVM
+ * feature then reflects over every registered data-content handler and
crashes on
+ * BouncyCastle's S/MIME handlers ({@code bcjmail}'s mailcap references
+ * {@code jakarta.mail.Part}, and jakarta.mail is not on the classpath).
The feature only
+ * registers mailcap handlers, which nothing on the ingest path uses, so
its registration
+ * is excluded — but only in the constellation that crashes: PDFBox
present (the recipe) and
+ * jakarta.mail absent. An application that uses mail and angus for real
keeps its feature.
+ */
+ @BuildStep
+ void excludeAngusActivationFeature(BuildProducer<ExcludeConfigBuildItem>
excludeConfig) {
+ if
(!QuarkusClassLoader.isClassPresentAtRuntime("org.apache.pdfbox.pdmodel.PDDocument")
+ ||
QuarkusClassLoader.isClassPresentAtRuntime("jakarta.mail.Part")) {
+ return;
+ }
+ excludeConfig.produce(new
ExcludeConfigBuildItem("org\\.eclipse\\.angus\\.angus-activation-.*\\.jar",
+
"/META-INF/native-image/org.eclipse.angus/angus-activation/native-image.properties"));
+ }
+
+ /**
+ * The same recipe brings PDFBox itself. Native image needs its
AWT-touching classes
+ * initialized at run time and its font metrics, glyph lists and ICC
profile embedded —
+ * mirroring the camel-quarkus-pdf extension's registrations, widened to
the rendering and
+ * graphics packages that Tika's text extraction reaches and camel-pdf
does not. Produced
+ * only when PDFBox is on the classpath.
+ */
+ @BuildStep
+ void pdfboxInNative(
+ BuildProducer<RuntimeInitializedClassBuildItem> runtimeInitialized,
+ BuildProducer<RuntimeInitializedPackageBuildItem>
runtimeInitializedPackages,
+ BuildProducer<NativeImageResourceBuildItem> nativeResources,
+ BuildProducer<ReflectiveClassBuildItem> reflectiveClasses) {
+ if
(!QuarkusClassLoader.isClassPresentAtRuntime("org.apache.pdfbox.pdmodel.PDDocument"))
{
+ return;
+ }
+ for (String className : new String[] {
+ "org.apache.pdfbox.pdmodel.font.PDType1Font",
+ "org.apache.pdfbox.pdmodel.PDDocument",
+ "org.apache.pdfbox.pdmodel.encryption.StandardSecurityHandler"
}) {
+ runtimeInitialized.produce(new
RuntimeInitializedClassBuildItem(className));
+ }
+ // text extraction reaches AWT-holding statics across the rendering
and graphics trees
+ // (SoftMask's DirectColorModel, the CIE color spaces'
ICC_ColorSpace), and Tika's own
+ // PDF classes embed them in enum constants
(PDFParserConfig$TikaImageType wraps
+ // rendering.ImageType), so the packages are deferred wholesale rather
than chasing one
+ // class at a time
+ for (String packageName : new String[] {
+ "org.apache.pdfbox.rendering",
+ "org.apache.pdfbox.pdmodel.graphics",
+ "org.apache.tika.parser.pdf" }) {
+ runtimeInitializedPackages.produce(new
RuntimeInitializedPackageBuildItem(packageName));
+ }
+ reflectiveClasses.produce(ReflectiveClassBuildItem
+
.builder("org.apache.pdfbox.pdmodel.encryption.StandardSecurityHandler",
+
"org.apache.pdfbox.pdmodel.documentinterchange.logicalstructure.PDParentTreeValue")
+ .constructors().methods().build());
+ nativeResources.produce(new NativeImageResourceBuildItem(
+ "org/apache/pdfbox/resources/version.properties",
+ "org/apache/pdfbox/resources/afm/Courier.afm",
+ "org/apache/pdfbox/resources/afm/Courier-Bold.afm",
+ "org/apache/pdfbox/resources/afm/Courier-BoldOblique.afm",
+ "org/apache/pdfbox/resources/afm/Courier-Oblique.afm",
+ "org/apache/pdfbox/resources/afm/Helvetica.afm",
+ "org/apache/pdfbox/resources/afm/Helvetica-Bold.afm",
+ "org/apache/pdfbox/resources/afm/Helvetica-BoldOblique.afm",
+ "org/apache/pdfbox/resources/afm/Helvetica-Oblique.afm",
+ "org/apache/pdfbox/resources/afm/MustRead.html",
+ "org/apache/pdfbox/resources/afm/Symbol.afm",
+ "org/apache/pdfbox/resources/afm/Times-Bold.afm",
+ "org/apache/pdfbox/resources/afm/Times-BoldItalic.afm",
+ "org/apache/pdfbox/resources/afm/Times-Italic.afm",
+ "org/apache/pdfbox/resources/afm/Times-Roman.afm",
+ "org/apache/pdfbox/resources/afm/ZapfDingbats.afm",
+ "org/apache/pdfbox/resources/glyphlist/additional.txt",
+ "org/apache/pdfbox/resources/glyphlist/glyphlist.txt",
+ "org/apache/pdfbox/resources/glyphlist/zapfdingbats.txt",
+ "org/apache/pdfbox/resources/icc/ISOcoated_v2_300_bas.icc",
+ "org/apache/pdfbox/resources/text/BidiMirroring.txt",
+ "org/apache/pdfbox/resources/ttf/LiberationSans-Regular.ttf"));
Review Comment:
**Maintainability.** This resource list mirrors `camel-quarkus-pdf`'s
registrations, as the javadoc notes. On a PDFBox upgrade that adds or renames
AFM/glyphlist/ICC/TTF resources, the two lists can drift apart silently. Could
the comment cross-reference `PdfProcessor` (or the shared list be factored into
a constant both extensions use), so the coupling is discoverable the next time
PDFBox moves?
##########
extensions/langchain4j-ingest/deployment/src/main/java/org/apache/camel/quarkus/component/langchain4j/ingest/deployment/Langchain4jIngestProcessor.java:
##########
@@ -68,11 +74,93 @@ FeatureBuildItem feature() {
@BuildStep
AdditionalBeanBuildItem beans() {
return AdditionalBeanBuildItem.builder()
- .addBeanClasses(IngestRoutes.class)
+ .addBeanClasses(IngestRoutes.class, IngestBeanResolver.class)
.setUnremovable()
.build();
}
+ /**
+ * The documented PDF recipe adds {@code tika-parser-pdf-module}, which
drags
+ * {@code jaxb-runtime} → {@code angus-activation} into the image. Angus'
own GraalVM
+ * feature then reflects over every registered data-content handler and
crashes on
+ * BouncyCastle's S/MIME handlers ({@code bcjmail}'s mailcap references
+ * {@code jakarta.mail.Part}, and jakarta.mail is not on the classpath).
The feature only
+ * registers mailcap handlers, which nothing on the ingest path uses, so
its registration
+ * is excluded — but only in the constellation that crashes: PDFBox
present (the recipe) and
+ * jakarta.mail absent. An application that uses mail and angus for real
keeps its feature.
+ */
+ @BuildStep
+ void excludeAngusActivationFeature(BuildProducer<ExcludeConfigBuildItem>
excludeConfig) {
+ if
(!QuarkusClassLoader.isClassPresentAtRuntime("org.apache.pdfbox.pdmodel.PDDocument")
+ ||
QuarkusClassLoader.isClassPresentAtRuntime("jakarta.mail.Part")) {
+ return;
+ }
+ excludeConfig.produce(new
ExcludeConfigBuildItem("org\\.eclipse\\.angus\\.angus-activation-.*\\.jar",
+
"/META-INF/native-image/org.eclipse.angus/angus-activation/native-image.properties"));
+ }
+
+ /**
+ * The same recipe brings PDFBox itself. Native image needs its
AWT-touching classes
+ * initialized at run time and its font metrics, glyph lists and ICC
profile embedded —
+ * mirroring the camel-quarkus-pdf extension's registrations, widened to
the rendering and
+ * graphics packages that Tika's text extraction reaches and camel-pdf
does not. Produced
+ * only when PDFBox is on the classpath.
+ */
+ @BuildStep
+ void pdfboxInNative(
Review Comment:
**Layering question.** The PDFBox runtime-init/resource registrations here
(and the `excludeAngusActivationFeature` step just above) are gated on PDFBox
being on the classpath, so they only activate for apps that pull in
`langchain4j-ingest`. An app that uses `camel-quarkus-tika` +
`tika-parser-pdf-module` directly — without ingest — would hit the same native
failures with no coverage, since `camel-quarkus-tika`'s deployment has no
PDFBox handling today.
Is scoping this to the ingest extension deliberate (with the tika extension
left as a follow-up), or would this native config be better homed in
`camel-quarkus-tika` so any Tika+PDF user benefits? Happy either way — mainly
want the decision to be explicit.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]