diff --git a/qqq-backend-core/pom.xml b/qqq-backend-core/pom.xml
index 21723b83..63a24365 100644
--- a/qqq-backend-core/pom.xml
+++ b/qqq-backend-core/pom.xml
@@ -151,16 +151,21 @@
2.3
-
+
org.jsoup
jsoup
1.15.3
- org.xhtmlrenderer
- flying-saucer-pdf-openpdf
- 9.1.22
+ com.openhtmltopdf
+ openhtmltopdf-core
+ 1.0.10
+
+
+ com.openhtmltopdf
+ openhtmltopdf-pdfbox
+ 1.0.10
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/templates/ConvertHtmlToPdfAction.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/templates/ConvertHtmlToPdfAction.java
index a7f9096f..d2dbdac1 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/templates/ConvertHtmlToPdfAction.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/actions/templates/ConvertHtmlToPdfAction.java
@@ -26,22 +26,31 @@ import java.nio.file.Path;
import java.util.Map;
import com.kingsrook.qqq.backend.core.actions.AbstractQActionFunction;
import com.kingsrook.qqq.backend.core.exceptions.QException;
+import com.kingsrook.qqq.backend.core.logging.QLogger;
import com.kingsrook.qqq.backend.core.model.actions.templates.ConvertHtmlToPdfInput;
import com.kingsrook.qqq.backend.core.model.actions.templates.ConvertHtmlToPdfOutput;
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
+import com.openhtmltopdf.css.constants.IdentValue;
+import com.openhtmltopdf.pdfboxout.PdfBoxFontResolver;
+import com.openhtmltopdf.pdfboxout.PdfBoxRenderer;
+import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
-import org.xhtmlrenderer.layout.SharedContext;
-import org.xhtmlrenderer.pdf.ITextRenderer;
/*******************************************************************************
** Action to convert a string of HTML to a PDF!
**
** Much credit to https://www.baeldung.com/java-html-to-pdf
- *******************************************************************************/
+ **
+ ** Updated in March 2025 to go from flying-saucer-pdf-openpdf lib to openhtmltopdf,
+ ** mostly to get support for max-height on images...
+ ********************************************************************************/
public class ConvertHtmlToPdfAction extends AbstractQActionFunction
{
+ private static final QLogger LOG = QLogger.getLogger(ConvertHtmlToPdfAction.class);
+
+
/*******************************************************************************
**
@@ -62,31 +71,32 @@ public class ConvertHtmlToPdfAction extends AbstractQActionFunction entry : CollectionUtils.nonNullMap(input.getCustomFonts()).entrySet())
- {
- renderer.getFontResolver().addFont(entry.getValue().toAbsolutePath().toString(), entry.getKey(), "UTF-8", true, null);
- }
+ for(Map.Entry entry : CollectionUtils.nonNullMap(input.getCustomFonts()).entrySet())
+ {
+ LOG.warn("Note: Custom fonts appear to not be working in this class at this time...");
+ pdfBoxRenderer.getFontResolver().addFont(
+ entry.getValue().toAbsolutePath().toFile(), // Path to the TrueType font file
+ entry.getKey(), // Font family name to use in CSS
+ 400, // Font weight (e.g., 400 for normal, 700 for bold)
+ IdentValue.NORMAL, // Font style (e.g., NORMAL, ITALIC)
+ true, // Whether to subset the font
+ PdfBoxFontResolver.FontGroup.MAIN // ??
+ );
+ }
- renderer.layout();
- renderer.createPDF(input.getOutputStream());
+ pdfBoxRenderer.createPDF();
+ }
return (output);
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecord.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecord.java
index cc3b0f6c..194e59da 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecord.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecord.java
@@ -468,7 +468,7 @@ public class QRecord implements Serializable
*******************************************************************************/
public String getValueString(String fieldName)
{
- return (ValueUtils.getValueAsString(values.get(fieldName)));
+ return (ValueUtils.getValueAsString(getValue(fieldName)));
}
@@ -479,7 +479,7 @@ public class QRecord implements Serializable
*******************************************************************************/
public Integer getValueInteger(String fieldName)
{
- return (ValueUtils.getValueAsInteger(values.get(fieldName)));
+ return (ValueUtils.getValueAsInteger(getValue(fieldName)));
}
@@ -490,7 +490,7 @@ public class QRecord implements Serializable
*******************************************************************************/
public Long getValueLong(String fieldName)
{
- return (ValueUtils.getValueAsLong(values.get(fieldName)));
+ return (ValueUtils.getValueAsLong(getValue(fieldName)));
}
@@ -500,7 +500,7 @@ public class QRecord implements Serializable
*******************************************************************************/
public BigDecimal getValueBigDecimal(String fieldName)
{
- return (ValueUtils.getValueAsBigDecimal(values.get(fieldName)));
+ return (ValueUtils.getValueAsBigDecimal(getValue(fieldName)));
}
@@ -510,7 +510,7 @@ public class QRecord implements Serializable
*******************************************************************************/
public Boolean getValueBoolean(String fieldName)
{
- return (ValueUtils.getValueAsBoolean(values.get(fieldName)));
+ return (ValueUtils.getValueAsBoolean(getValue(fieldName)));
}
@@ -520,7 +520,7 @@ public class QRecord implements Serializable
*******************************************************************************/
public LocalTime getValueLocalTime(String fieldName)
{
- return (ValueUtils.getValueAsLocalTime(values.get(fieldName)));
+ return (ValueUtils.getValueAsLocalTime(getValue(fieldName)));
}
@@ -530,7 +530,7 @@ public class QRecord implements Serializable
*******************************************************************************/
public LocalDate getValueLocalDate(String fieldName)
{
- return (ValueUtils.getValueAsLocalDate(values.get(fieldName)));
+ return (ValueUtils.getValueAsLocalDate(getValue(fieldName)));
}
@@ -540,7 +540,7 @@ public class QRecord implements Serializable
*******************************************************************************/
public byte[] getValueByteArray(String fieldName)
{
- return (ValueUtils.getValueAsByteArray(values.get(fieldName)));
+ return (ValueUtils.getValueAsByteArray(getValue(fieldName)));
}
@@ -550,7 +550,7 @@ public class QRecord implements Serializable
*******************************************************************************/
public Instant getValueInstant(String fieldName)
{
- return (ValueUtils.getValueAsInstant(values.get(fieldName)));
+ return (ValueUtils.getValueAsInstant(getValue(fieldName)));
}
diff --git a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecordWithJoinedRecords.java b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecordWithJoinedRecords.java
index aa773687..70796b49 100644
--- a/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecordWithJoinedRecords.java
+++ b/qqq-backend-core/src/main/java/com/kingsrook/qqq/backend/core/model/data/QRecordWithJoinedRecords.java
@@ -24,6 +24,7 @@ package com.kingsrook.qqq.backend.core.model.data;
import java.io.Serializable;
import java.util.LinkedHashMap;
+import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
@@ -198,4 +199,62 @@ public class QRecordWithJoinedRecords extends QRecord
return (rs);
}
+
+
+ /***************************************************************************
+ **
+ ***************************************************************************/
+ @Override
+ public Map> getAssociatedRecords()
+ {
+ return mainRecord.getAssociatedRecords();
+ }
+
+
+
+ /***************************************************************************
+ **
+ ***************************************************************************/
+ @Override
+ public QRecord withAssociatedRecord(String name, QRecord associatedRecord)
+ {
+ mainRecord.withAssociatedRecord(name, associatedRecord);
+ return (this);
+ }
+
+
+
+ /***************************************************************************
+ **
+ ***************************************************************************/
+ @Override
+ public QRecord withAssociatedRecords(Map> associatedRecords)
+ {
+ mainRecord.withAssociatedRecords(associatedRecords);
+ return (this);
+ }
+
+
+
+ /***************************************************************************
+ **
+ ***************************************************************************/
+ @Override
+ public void setAssociatedRecords(Map> associatedRecords)
+ {
+ mainRecord.setAssociatedRecords(associatedRecords);
+ }
+
+
+
+ /***************************************************************************
+ **
+ ***************************************************************************/
+ @Override
+ public QRecord withAssociatedRecords(String name, List associatedRecords)
+ {
+ mainRecord.withAssociatedRecords(name, associatedRecords);
+ return (this);
+ }
+
}