This is an automated email from the ASF dual-hosted git repository.

mbrohl pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new a41f0540ba Improved: ContentWrapper empty string result breaks simple 
FTL null check and default syntax (OFBIZ-10194)
a41f0540ba is described below

commit a41f0540ba3c7f99a1deb1d2d1efb55510cd19e1
Author: Adrian Wolf <adrian.w...@ecomify.de>
AuthorDate: Fri Apr 21 14:08:14 2023 +0200

    Improved: ContentWrapper empty string result breaks simple FTL null
    check and default syntax (OFBIZ-10194)
---
 .../ofbiz/content/content/ContentWrapper.java      |  85 +++++++++++++
 .../ofbiz/order/order/OrderContentWrapper.java     |  51 ++++----
 .../ofbiz/party/content/PartyContentWrapper.java   | 132 +++++++++------------
 .../product/category/CategoryContentWrapper.java   | 113 +++++++++---------
 .../config/ProductConfigItemContentWrapper.java    |  94 ++++++++-------
 .../product/product/ProductContentWrapper.java     | 129 +++++++++-----------
 .../product/ProductPromoContentWrapper.java        |  80 ++++++-------
 7 files changed, 375 insertions(+), 309 deletions(-)

diff --git 
a/applications/content/src/main/java/org/apache/ofbiz/content/content/ContentWrapper.java
 
b/applications/content/src/main/java/org/apache/ofbiz/content/content/ContentWrapper.java
index 15115c90e1..5a0db6df11 100644
--- 
a/applications/content/src/main/java/org/apache/ofbiz/content/content/ContentWrapper.java
+++ 
b/applications/content/src/main/java/org/apache/ofbiz/content/content/ContentWrapper.java
@@ -18,7 +18,18 @@
  
*******************************************************************************/
 package org.apache.ofbiz.content.content;
 
+import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.StringUtil;
+import org.apache.ofbiz.base.util.UtilCodec;
+import org.apache.ofbiz.base.util.UtilValidate;
+import org.apache.ofbiz.entity.Delegator;
+import org.apache.ofbiz.entity.GenericEntityException;
+import org.apache.ofbiz.entity.GenericValue;
+import org.apache.ofbiz.entity.condition.EntityCondition;
+import org.apache.ofbiz.entity.model.ModelEntity;
+import org.apache.ofbiz.entity.model.ModelUtil;
+import org.apache.ofbiz.entity.util.EntityQuery;
+import org.apache.ofbiz.entity.util.EntityUtilProperties;
 
 /**
  * ContentWrapper Interface
@@ -26,6 +37,80 @@ import org.apache.ofbiz.base.util.StringUtil;
 
 public interface ContentWrapper {
 
+    String MDOULE = ContentWrapper.class.getName();
+
     StringUtil.StringWrapper get(String contentTypeId, String encoderType);
 
+    /**
+     * Get the configured default for content mimeTypeId.
+     * @param delegator
+     * @return
+     */
+    static String getDefaultMimeTypeId(Delegator delegator) {
+        return EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8", delegator);
+    }
+
+    /**
+     * Check modelObject for existance of a field named like given 
contentTypeId and
+     * return its value as String.
+     * @param modelObject
+     * @param contentTypeId
+     * @return
+     */
+    static String getCandidateFieldValue(GenericValue modelObject, String 
contentTypeId) {
+        if (modelObject != null) {
+            String candidateFieldName = 
ModelUtil.dbNameToVarName(contentTypeId);
+            if (modelObject.getModelEntity().isField(candidateFieldName)) {
+                return modelObject.getString(candidateFieldName);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Check if modelEntityName is an existing entity and has a field named 
like
+     * given contentTypeId and get the unique modelObject entry by 
modelObjectPk and
+     * return the candidate field value as String.
+     * @param delegator
+     * @param modelEntityName
+     * @param modelObjectPk
+     * @param contentTypeId
+     * @param useCache
+     * @return
+     * @throws GenericEntityException
+     */
+    static String getCandidateFieldValue(Delegator delegator, String 
modelEntityName, EntityCondition modelObjectPk,
+            String contentTypeId, boolean useCache) throws 
GenericEntityException {
+
+        ModelEntity modelEntity = delegator.getModelEntity(modelEntityName);
+        if (modelEntity != null) {
+            String candidateFieldName = 
ModelUtil.dbNameToVarName(contentTypeId);
+
+            if (modelEntity.isField(candidateFieldName)) {
+                GenericValue modelObject = 
EntityQuery.use(delegator).from(modelEntityName).where(modelObjectPk).cache(useCache).queryOne();
+                if (modelObject != null) {
+                    return modelObject.getString(candidateFieldName);
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Encode given content string via given encoderType.
+     * @param value
+     * @param encoderType
+     * @return
+     */
+    static String encodeContentValue(String value, String encoderType) {
+        if (UtilValidate.isNotEmpty(value)) {
+            UtilCodec.SimpleEncoder encoder = 
UtilCodec.getEncoder(encoderType);
+            if (encoder != null) {
+                value = encoder.sanitize(value, null);
+            } else {
+                Debug.logWarning("Unknown encoderType %s for encoding content 
value!", MDOULE, encoderType);
+            }
+        }
+        return value;
+    }
 }
diff --git 
a/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderContentWrapper.java
 
b/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderContentWrapper.java
index fb36697642..06e7ae347c 100644
--- 
a/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderContentWrapper.java
+++ 
b/applications/order/src/main/java/org/apache/ofbiz/order/order/OrderContentWrapper.java
@@ -30,7 +30,6 @@ import javax.servlet.http.HttpServletRequest;
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.GeneralException;
 import org.apache.ofbiz.base.util.StringUtil;
-import org.apache.ofbiz.base.util.UtilCodec;
 import org.apache.ofbiz.base.util.UtilHttp;
 import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.base.util.cache.UtilCache;
@@ -51,8 +50,8 @@ public class OrderContentWrapper implements ContentWrapper {
     private static final String MODULE = OrderContentWrapper.class.getName();
     private static final String SEPARATOR = "::";    // cache key separator
 
-    private static final UtilCache<String, String> ORDER_CONTENT_CACHE = 
UtilCache.createUtilCache("order.content", true);
-    // use soft reference to free up memory if needed
+    private static final UtilCache<String, String> ORDER_CONTENT_CACHE = 
UtilCache.createUtilCache(
+            "order.content.rendered", true); // use soft reference to free up 
memory if needed
 
     public static OrderContentWrapper makeOrderContentWrapper(GenericValue 
order, HttpServletRequest request) {
         return new OrderContentWrapper(order, request);
@@ -74,8 +73,7 @@ public class OrderContentWrapper implements ContentWrapper {
         this.dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
         this.order = order;
         this.locale = UtilHttp.getLocale(request);
-        this.mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8",
-                (Delegator) request.getAttribute("delegator"));
+        this.mimeTypeId = ContentWrapper.getDefaultMimeTypeId((Delegator) 
request.getAttribute("delegator"));
     }
 
     @Override
@@ -86,7 +84,7 @@ public class OrderContentWrapper implements ContentWrapper {
 
     public static String getOrderContentAsText(GenericValue order, String 
orderContentTypeId, HttpServletRequest request, String encoderType) {
         LocalDispatcher dispatcher = (LocalDispatcher) 
request.getAttribute("dispatcher");
-        String mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8", order.getDelegator());
+        String mimeTypeId = 
ContentWrapper.getDefaultMimeTypeId(order.getDelegator());
         return getOrderContentAsText(order, orderContentTypeId, 
UtilHttp.getLocale(request), mimeTypeId, order.getDelegator(), dispatcher,
                 encoderType);
     }
@@ -98,32 +96,40 @@ public class OrderContentWrapper implements ContentWrapper {
 
     public static String getOrderContentAsText(GenericValue order, String 
orderContentTypeId, Locale locale, String mimeTypeId, Delegator delegator,
                                                LocalDispatcher dispatcher, 
String encoderType) {
+        if (order == null) {
+            return null;
+        }
+        String orderItemSeqId = ("OrderItem".equals(order.getEntityName()) ? 
order.getString("orderItemSeqId")
+                : "_NA_");
+
+        /* Look for a previously cached entry (may also be an entry with null 
value if
+         * there was no content to retrieve)
+         */
         /* caching: there is one cache created, "order.content"  Each order's 
content is cached with a key of
          * contentTypeId::locale::mimeType::orderId::orderItemSeqId, or 
whatever the SEPARATOR is defined above to be.
          */
-        UtilCodec.SimpleEncoder encoder = UtilCodec.getEncoder(encoderType);
 
-        String orderItemSeqId = ("OrderItem".equals(order.getEntityName()) ? 
order.getString("orderItemSeqId") : "_NA_");
+        String cacheKey = orderContentTypeId + SEPARATOR + locale + SEPARATOR 
+ mimeTypeId + SEPARATOR + order.get(
+                "orderId") + SEPARATOR + orderItemSeqId + SEPARATOR + 
encoderType + SEPARATOR + delegator;
+        String cachedValue = ORDER_CONTENT_CACHE.get(cacheKey);
+        if (cachedValue != null || ORDER_CONTENT_CACHE.containsKey(cacheKey)) {
+            return cachedValue;
+        }
+
+        // Get content of given contentTypeId
+        String outString = null;
 
-        String cacheKey = orderContentTypeId + SEPARATOR + locale + SEPARATOR 
+ mimeTypeId + SEPARATOR + order.get("orderId") + SEPARATOR
-                + orderItemSeqId + SEPARATOR + encoderType + SEPARATOR + 
delegator;
         try {
-            String cachedValue = ORDER_CONTENT_CACHE.get(cacheKey);
-            if (cachedValue != null) {
-                return cachedValue;
-            }
-
             Writer outWriter = new StringWriter();
-            getOrderContentAsText(null, null, order, orderContentTypeId, 
locale, mimeTypeId, delegator, dispatcher, outWriter, false);
-            String outString = outWriter.toString();
-            outString = encoder.sanitize(outString, null);
+            getOrderContentAsText(null, orderItemSeqId, order, 
orderContentTypeId, locale, mimeTypeId, delegator,
+                    dispatcher, outWriter, false);
+            // Encode found content via given encoderType
+            outString = 
ContentWrapper.encodeContentValue(outWriter.toString(), encoderType);
             ORDER_CONTENT_CACHE.put(cacheKey, outString);
-            return outString;
-
         } catch (GeneralException | IOException e) {
-            Debug.logError(e, "Error rendering OrderContent, inserting empty 
String", MODULE);
-            return "";
+            Debug.logError(e, "Error rendering OrderContent", MODULE);
         }
+        return outString;
     }
 
     public static void getOrderContentAsText(String orderId, String 
orderItemSeqId, GenericValue order, String orderContentTypeId, Locale locale,
@@ -165,4 +171,3 @@ public class OrderContentWrapper implements ContentWrapper {
         }
     }
 }
-
diff --git 
a/applications/party/src/main/java/org/apache/ofbiz/party/content/PartyContentWrapper.java
 
b/applications/party/src/main/java/org/apache/ofbiz/party/content/PartyContentWrapper.java
index 4d43003f29..6a6c526b61 100644
--- 
a/applications/party/src/main/java/org/apache/ofbiz/party/content/PartyContentWrapper.java
+++ 
b/applications/party/src/main/java/org/apache/ofbiz/party/content/PartyContentWrapper.java
@@ -34,7 +34,6 @@ import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.GeneralException;
 import org.apache.ofbiz.base.util.GeneralRuntimeException;
 import org.apache.ofbiz.base.util.StringUtil;
-import org.apache.ofbiz.base.util.UtilCodec;
 import org.apache.ofbiz.base.util.UtilHttp;
 import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.base.util.cache.UtilCache;
@@ -42,11 +41,9 @@ import org.apache.ofbiz.content.content.ContentWorker;
 import org.apache.ofbiz.content.content.ContentWrapper;
 import org.apache.ofbiz.entity.Delegator;
 import org.apache.ofbiz.entity.GenericValue;
-import org.apache.ofbiz.entity.model.ModelEntity;
-import org.apache.ofbiz.entity.model.ModelUtil;
+import org.apache.ofbiz.entity.condition.EntityCondition;
 import org.apache.ofbiz.entity.util.EntityQuery;
 import org.apache.ofbiz.entity.util.EntityUtil;
-import org.apache.ofbiz.entity.util.EntityUtilProperties;
 import org.apache.ofbiz.service.LocalDispatcher;
 
 /**
@@ -75,8 +72,7 @@ public class PartyContentWrapper implements ContentWrapper {
         this.dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
         this.party = party;
         this.locale = UtilHttp.getLocale(request);
-        this.mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8",
-                (Delegator) request.getAttribute("delegator"));
+        this.mimeTypeId = 
ContentWrapper.getDefaultMimeTypeId(party.getDelegator());
     }
 
     /**
@@ -147,7 +143,7 @@ public class PartyContentWrapper implements ContentWrapper {
     // static methods
     public static String getPartyContentAsText(GenericValue party, String 
partyContentId, HttpServletRequest request, String encoderType) {
         LocalDispatcher dispatcher = (LocalDispatcher) 
request.getAttribute("dispatcher");
-        String mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8", party.getDelegator());
+        String mimeTypeId = 
ContentWrapper.getDefaultMimeTypeId(party.getDelegator());
         return getPartyContentAsText(party, partyContentId, null, 
UtilHttp.getLocale(request), mimeTypeId, party.getDelegator(), dispatcher,
                 true, encoderType);
     }
@@ -168,44 +164,47 @@ public class PartyContentWrapper implements 
ContentWrapper {
             return null;
         }
 
-        UtilCodec.SimpleEncoder encoder = UtilCodec.getEncoder(encoderType);
-        String candidateFieldName = 
ModelUtil.dbNameToVarName(partyContentTypeId);
-        String cacheKey;
-        if (contentId != null) {
-            cacheKey = contentId + CACHE_KEY_SEPARATOR + locale + 
CACHE_KEY_SEPARATOR + mimeTypeId
-                    + CACHE_KEY_SEPARATOR + party.get("partyId");
-        } else {
-            cacheKey = partyContentTypeId + CACHE_KEY_SEPARATOR + locale + 
CACHE_KEY_SEPARATOR + mimeTypeId
-                    + CACHE_KEY_SEPARATOR + party.get("partyId");
-        }
+        String cacheKey = null;
+        if (useCache) {
+            if (contentId != null) {
+                cacheKey = contentId + CACHE_KEY_SEPARATOR + locale + 
CACHE_KEY_SEPARATOR + mimeTypeId
+                        + CACHE_KEY_SEPARATOR + party.get("partyId");
+            } else {
+                cacheKey = partyContentTypeId + CACHE_KEY_SEPARATOR + locale + 
CACHE_KEY_SEPARATOR + mimeTypeId
+                        + CACHE_KEY_SEPARATOR + party.get("partyId");
+            }
 
-        try {
-            if (useCache) {
-                String cachedValue = PARTY_CONTENT_CACHE.get(cacheKey);
-                if (cachedValue != null) {
-                    return cachedValue;
-                }
+            String cachedValue = PARTY_CONTENT_CACHE.get(cacheKey);
+            if (cachedValue != null || 
PARTY_CONTENT_CACHE.containsKey(cacheKey)) {
+                return cachedValue;
             }
+        }
 
+        // Get content of given contentTypeId
+        String outString = null;
+        try {
             Writer outWriter = new StringWriter();
-            getPartyContentAsText(contentId, party.getString("partyId"), 
party, partyContentTypeId, locale, mimeTypeId, delegator, dispatcher,
-                    outWriter, false);
-
-            String outString = outWriter.toString();
-            if (UtilValidate.isEmpty(outString)) {
-                outString = party.getModelEntity().isField(candidateFieldName) 
? party.getString(candidateFieldName) : "";
-                outString = outString == null ? "" : outString;
-            }
-            outString = encoder.sanitize(outString, null);
-            if (PARTY_CONTENT_CACHE != null) {
-                PARTY_CONTENT_CACHE.put(cacheKey, outString);
-            }
-            return outString;
+            getPartyContentAsText(contentId, party.getString("partyId"), 
party, partyContentTypeId, locale, mimeTypeId,
+                    delegator, dispatcher, outWriter, false);
+            outString = outWriter.toString();
         } catch (GeneralException | IOException e) {
-            Debug.logError(e, "Error rendering PartyContent, inserting empty 
String", MODULE);
-            String candidateOut = 
party.getModelEntity().isField(candidateFieldName) ? 
party.getString(candidateFieldName) : "";
-            return candidateOut == null ? "" : encoder.sanitize(candidateOut, 
null);
+            Debug.logError(e, "Error rendering PartyContent", MODULE);
+            useCache = false;
         }
+
+        /* If we did not found any content (or got an error), get the content 
of a
+         * candidateFieldName matching the given contentTypeId
+         */
+        if (UtilValidate.isEmpty(outString)) {
+            outString = ContentWrapper.getCandidateFieldValue(party, 
partyContentTypeId);
+        }
+        // Encode found content via given encoderType
+        outString = ContentWrapper.encodeContentValue(outString, encoderType);
+
+        if (useCache) {
+            PARTY_CONTENT_CACHE.put(cacheKey, outString);
+        }
+        return outString;
     }
 
     public static void getPartyContentAsText(String contentId, String partyId, 
GenericValue party, String partyContentTypeId, Locale locale,
@@ -223,15 +222,14 @@ public class PartyContentWrapper implements 
ContentWrapper {
         if (delegator == null && party != null) {
             delegator = party.getDelegator();
         }
-
-        if (UtilValidate.isEmpty(mimeTypeId)) {
-            mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8", delegator);
-        }
-
         if (delegator == null) {
             throw new GeneralRuntimeException("Unable to find a delegator to 
use!");
         }
 
+        if (UtilValidate.isEmpty(mimeTypeId)) {
+            mimeTypeId = ContentWrapper.getDefaultMimeTypeId(delegator);
+        }
+
         // Honor party content over Party entity fields.
         GenericValue partyContent;
         if (contentId != null) {
@@ -240,46 +238,26 @@ public class PartyContentWrapper implements 
ContentWrapper {
             partyContent = getFirstPartyContentByType(partyId, party, 
partyContentTypeId, delegator);
         }
         if (partyContent != null) {
-            // when rendering the product content, always include the Product 
and ProductContent records that this comes from
+            /* when rendering the party content, always include the Party and 
PartyContent
+             * records that this comes from
+             */
             Map<String, Object> inContext = new HashMap<>();
             inContext.put("party", party);
             inContext.put("partyContent", partyContent);
             ContentWorker.renderContentAsText(dispatcher, 
partyContent.getString("contentId"), outWriter, inContext, locale, mimeTypeId,
                     null, null, cache);
-            return;
-        }
-
-        if (partyContentTypeId != null) {
-            String candidateFieldName = 
ModelUtil.dbNameToVarName(partyContentTypeId);
-
+            // check person and group entity fields, if no content was found
+        } else if (partyContentTypeId != null) {
             // first check for a person field
-            ModelEntity partyPersonModel = 
delegator.getModelEntity("PartyAndPerson");
-            if (partyPersonModel != null && 
partyPersonModel.isField(candidateFieldName)) {
-                if (party == null) {
-                    party = 
EntityQuery.use(delegator).from("PartyAndPerson").where("partyId", 
partyId).cache().queryOne();
-                }
-                if (party != null) {
-                    String candidateValue = 
party.getString(candidateFieldName);
-                    if (UtilValidate.isNotEmpty(candidateValue)) {
-                        outWriter.write(candidateValue);
-                        return;
-                    }
-                }
+            String candidateValue = 
ContentWrapper.getCandidateFieldValue(delegator, "PartyAndPerson", 
EntityCondition
+                    .makeCondition("partyId", partyId), partyContentTypeId, 
cache);
+            if (UtilValidate.isEmpty(candidateValue)) {
+                // next check for group field
+                candidateValue = 
ContentWrapper.getCandidateFieldValue(delegator, "PartyAndGroup", 
EntityCondition
+                        .makeCondition("partyId", partyId), 
partyContentTypeId, cache);
             }
-
-            // next check for group field
-            ModelEntity partyGroupModel = 
delegator.getModelEntity("PartyAndGroup");
-            if (partyGroupModel != null && 
partyGroupModel.isField(candidateFieldName)) {
-                if (party == null) {
-                    party = 
EntityQuery.use(delegator).from("PartyAndGroup").where("partyId", 
partyId).cache().queryOne();
-                }
-                if (party != null) {
-                    String candidateValue = 
party.getString(candidateFieldName);
-                    if (UtilValidate.isNotEmpty(candidateValue)) {
-                        outWriter.write(candidateValue);
-                        return;
-                    }
-                }
+            if (UtilValidate.isNotEmpty(candidateValue)) {
+                outWriter.write(candidateValue);
             }
         }
     }
diff --git 
a/applications/product/src/main/java/org/apache/ofbiz/product/category/CategoryContentWrapper.java
 
b/applications/product/src/main/java/org/apache/ofbiz/product/category/CategoryContentWrapper.java
index 3e35ac68da..a4d05c6bbf 100644
--- 
a/applications/product/src/main/java/org/apache/ofbiz/product/category/CategoryContentWrapper.java
+++ 
b/applications/product/src/main/java/org/apache/ofbiz/product/category/CategoryContentWrapper.java
@@ -30,9 +30,7 @@ import javax.servlet.http.HttpServletRequest;
 
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.GeneralException;
-import org.apache.ofbiz.base.util.GeneralRuntimeException;
 import org.apache.ofbiz.base.util.StringUtil;
-import org.apache.ofbiz.base.util.UtilCodec;
 import org.apache.ofbiz.base.util.UtilHttp;
 import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.base.util.cache.UtilCache;
@@ -40,11 +38,8 @@ import org.apache.ofbiz.content.content.ContentWorker;
 import org.apache.ofbiz.content.content.ContentWrapper;
 import org.apache.ofbiz.entity.Delegator;
 import org.apache.ofbiz.entity.GenericValue;
-import org.apache.ofbiz.entity.model.ModelEntity;
-import org.apache.ofbiz.entity.model.ModelUtil;
 import org.apache.ofbiz.entity.util.EntityQuery;
 import org.apache.ofbiz.entity.util.EntityUtil;
-import org.apache.ofbiz.entity.util.EntityUtilProperties;
 import org.apache.ofbiz.service.LocalDispatcher;
 
 /**
@@ -54,8 +49,8 @@ public class CategoryContentWrapper implements ContentWrapper 
{
 
     private static final String MODULE = 
CategoryContentWrapper.class.getName();
     public static final String SEPARATOR = "::";    // cache key separator
-    private static final UtilCache<String, String> CATEGORY_CONTENT_CACHE = 
UtilCache.createUtilCache("category.content", true);
-    // use soft reference to free up memory if needed
+    private static final UtilCache<String, String> CATEGORY_CONTENT_CACHE = 
UtilCache.createUtilCache(
+            "category.content.rendered", true); // use soft reference to free 
up memory if needed
 
     private LocalDispatcher dispatcher;
     private GenericValue productCategory;
@@ -77,8 +72,7 @@ public class CategoryContentWrapper implements ContentWrapper 
{
         this.dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
         this.productCategory = productCategory;
         this.locale = UtilHttp.getLocale(request);
-        this.mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8",
-                (Delegator) request.getAttribute("delegator"));
+        this.mimeTypeId = ContentWrapper.getDefaultMimeTypeId((Delegator) 
request.getAttribute("delegator"));
     }
 
     @Override
@@ -90,8 +84,7 @@ public class CategoryContentWrapper implements ContentWrapper 
{
     public static String getProductCategoryContentAsText(GenericValue 
productCategory, String prodCatContentTypeId, HttpServletRequest request,
                                                          String encoderType) {
         LocalDispatcher dispatcher = (LocalDispatcher) 
request.getAttribute("dispatcher");
-        String mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8",
-                productCategory.getDelegator());
+        String mimeTypeId = 
ContentWrapper.getDefaultMimeTypeId(productCategory.getDelegator());
         return getProductCategoryContentAsText(productCategory, 
prodCatContentTypeId, UtilHttp.getLocale(request), mimeTypeId,
                 productCategory.getDelegator(), dispatcher, encoderType);
     }
@@ -101,56 +94,79 @@ public class CategoryContentWrapper implements 
ContentWrapper {
         return getProductCategoryContentAsText(productCategory, 
prodCatContentTypeId, locale, null, null, dispatcher, encoderType);
     }
 
-    public static String getProductCategoryContentAsText(GenericValue 
productCategory, String prodCatContentTypeId, Locale locale, String mimeTypeId,
-                                                         Delegator delegator, 
LocalDispatcher dispatcher, String encoderType) {
-        String candidateFieldName = 
ModelUtil.dbNameToVarName(prodCatContentTypeId);
-        UtilCodec.SimpleEncoder encoder = UtilCodec.getEncoder(encoderType);
-        String cacheKey = prodCatContentTypeId + SEPARATOR + locale + 
SEPARATOR + mimeTypeId + SEPARATOR + productCategory.get("productCategoryId")
+    public static String getProductCategoryContentAsText(GenericValue 
productCategory, String prodCatContentTypeId,
+            Locale locale, String mimeTypeId,
+            Delegator delegator, LocalDispatcher dispatcher, String 
encoderType) {
+        if (productCategory == null) {
+            return null;
+        }
+
+        /*
+         * Look for a previously cached entry (may also be an entry with null 
value if
+         * there was no content to retrieve)
+         */
+        String cacheKey = prodCatContentTypeId + SEPARATOR + locale + 
SEPARATOR + mimeTypeId + SEPARATOR
+                + productCategory.get("productCategoryId")
                 + SEPARATOR + encoderType + SEPARATOR + delegator;
+        String cachedValue = CATEGORY_CONTENT_CACHE.get(cacheKey);
+        if (cachedValue != null || 
CATEGORY_CONTENT_CACHE.containsKey(cacheKey)) {
+            return cachedValue;
+        }
+
+        // Get content of given contentTypeId
+        boolean doCache = true;
+        String outString = null;
         try {
-            String cachedValue = CATEGORY_CONTENT_CACHE.get(cacheKey);
-            if (cachedValue != null) {
-                return cachedValue;
-            }
             Writer outWriter = new StringWriter();
-            getProductCategoryContentAsText(null, productCategory, 
prodCatContentTypeId, locale, mimeTypeId, delegator, dispatcher, outWriter, 
false);
-            String outString = outWriter.toString();
-            if (UtilValidate.isEmpty(outString)) {
-                outString = 
productCategory.getModelEntity().isField(candidateFieldName) ? 
productCategory.getString(candidateFieldName) : "";
-                outString = outString == null ? "" : outString;
-            }
-            outString = encoder.sanitize(outString, null);
-            CATEGORY_CONTENT_CACHE.put(cacheKey, outString);
-            return outString;
+            getProductCategoryContentAsText(null, productCategory, 
prodCatContentTypeId, locale, mimeTypeId, delegator,
+                    dispatcher, outWriter, false);
+            outString = outWriter.toString();
         } catch (GeneralException | IOException e) {
-            Debug.logError(e, "Error rendering CategoryContent, inserting 
empty String", MODULE);
-            return productCategory.getString(candidateFieldName);
+            Debug.logError(e, "Error rendering CategoryContent", MODULE);
+            doCache = false;
         }
+
+        /*
+         * If we did not found any content (or got an error), get the content 
of a
+         * candidateFieldName matching the given contentTypeId
+         */
+        if (UtilValidate.isEmpty(outString)) {
+            outString = ContentWrapper.getCandidateFieldValue(productCategory, 
prodCatContentTypeId);
+        }
+        // Encode found content via given encoderType
+        outString = ContentWrapper.encodeContentValue(outString, encoderType);
+
+        if (doCache) {
+            CATEGORY_CONTENT_CACHE.put(cacheKey, outString);
+        }
+        return outString;
     }
 
     public static void getProductCategoryContentAsText(String 
productCategoryId, GenericValue productCategory, String prodCatContentTypeId,
             Locale locale, String mimeTypeId, Delegator delegator, 
LocalDispatcher dispatcher, Writer outWriter)
             throws GeneralException, IOException {
-        getProductCategoryContentAsText(null, productCategory, 
prodCatContentTypeId, locale, mimeTypeId, delegator, dispatcher, outWriter, 
true);
+        getProductCategoryContentAsText(productCategoryId, productCategory, 
prodCatContentTypeId, locale, mimeTypeId,
+                delegator, dispatcher, outWriter, true);
     }
 
     public static void getProductCategoryContentAsText(String 
productCategoryId, GenericValue productCategory, String prodCatContentTypeId,
             Locale locale, String mimeTypeId, Delegator delegator, 
LocalDispatcher dispatcher, Writer outWriter, boolean cache)
             throws GeneralException, IOException {
-        if (productCategoryId == null && productCategory != null) {
+        if (productCategory != null) {
             productCategoryId = productCategory.getString("productCategoryId");
+        } else if (productCategoryId != null) {
+            productCategory = 
EntityQuery.use(delegator).from("ProductCategory").where("productCategoryId",
+                    productCategoryId).cache(cache).queryOne();
+        } else {
+            throw new GeneralException("Missing parameter productCategory or 
productCategoryId!");
         }
 
-        if (delegator == null && productCategory != null) {
+        if (delegator == null) {
             delegator = productCategory.getDelegator();
         }
 
         if (UtilValidate.isEmpty(mimeTypeId)) {
-            mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8", delegator);
-        }
-
-        if (delegator == null) {
-            throw new GeneralRuntimeException("Unable to find a delegator to 
use!");
+            mimeTypeId = ContentWrapper.getDefaultMimeTypeId(delegator);
         }
 
         List<GenericValue> categoryContentList = 
EntityQuery.use(delegator).from("ProductCategoryContent").where("productCategoryId",
@@ -163,21 +179,10 @@ public class CategoryContentWrapper implements 
ContentWrapper {
             inContext.put("categoryContent", categoryContent);
             ContentWorker.renderContentAsText(dispatcher, 
categoryContent.getString("contentId"), outWriter, inContext,
                     locale, mimeTypeId, null, null, cache);
-            return;
-        }
-
-        String candidateFieldName = 
ModelUtil.dbNameToVarName(prodCatContentTypeId);
-        ModelEntity categoryModel = 
delegator.getModelEntity("ProductCategory");
-        if (categoryModel.isField(candidateFieldName)) {
-            if (productCategory == null) {
-                productCategory = 
EntityQuery.use(delegator).from("ProductCategory").where("productCategoryId", 
productCategoryId).cache().queryOne();
-            }
-            if (productCategory != null) {
-                String candidateValue = 
productCategory.getString(candidateFieldName);
-                if (UtilValidate.isNotEmpty(candidateValue)) {
-                    outWriter.write(candidateValue);
-                    return;
-                }
+        } else {
+            String candidateValue = 
ContentWrapper.getCandidateFieldValue(productCategory, prodCatContentTypeId);
+            if (UtilValidate.isNotEmpty(candidateValue)) {
+                outWriter.write(candidateValue);
             }
         }
     }
diff --git 
a/applications/product/src/main/java/org/apache/ofbiz/product/config/ProductConfigItemContentWrapper.java
 
b/applications/product/src/main/java/org/apache/ofbiz/product/config/ProductConfigItemContentWrapper.java
index f5b8f45873..08c97d947b 100644
--- 
a/applications/product/src/main/java/org/apache/ofbiz/product/config/ProductConfigItemContentWrapper.java
+++ 
b/applications/product/src/main/java/org/apache/ofbiz/product/config/ProductConfigItemContentWrapper.java
@@ -31,7 +31,6 @@ import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.GeneralException;
 import org.apache.ofbiz.base.util.StringUtil;
 import org.apache.ofbiz.base.util.StringUtil.StringWrapper;
-import org.apache.ofbiz.base.util.UtilCodec;
 import org.apache.ofbiz.base.util.UtilHttp;
 import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.base.util.cache.UtilCache;
@@ -40,10 +39,8 @@ import org.apache.ofbiz.content.content.ContentWrapper;
 import org.apache.ofbiz.entity.Delegator;
 import org.apache.ofbiz.entity.DelegatorFactory;
 import org.apache.ofbiz.entity.GenericValue;
-import org.apache.ofbiz.entity.model.ModelEntity;
-import org.apache.ofbiz.entity.model.ModelUtil;
+import org.apache.ofbiz.entity.condition.EntityCondition;
 import org.apache.ofbiz.entity.util.EntityQuery;
-import org.apache.ofbiz.entity.util.EntityUtilProperties;
 import org.apache.ofbiz.service.LocalDispatcher;
 import org.apache.ofbiz.service.ServiceContainer;
 
@@ -54,8 +51,8 @@ public class ProductConfigItemContentWrapper implements 
ContentWrapper {
 
     private static final String MODULE = 
ProductConfigItemContentWrapper.class.getName();
     public static final String SEPARATOR = "::";    // cache key separator
-    private static final UtilCache<String, String> CONFIG_ITEM_CONTENT_CACHE = 
UtilCache.createUtilCache("configItem.content", true);
-    // use soft reference to free up memory if needed
+    private static final UtilCache<String, String> CONFIG_ITEM_CONTENT_CACHE = 
UtilCache.createUtilCache(
+            "configItem.content.rendered", true); // use soft reference to 
free up memory if needed
 
     private transient LocalDispatcher dispatcher;
     private String dispatcherName;
@@ -87,7 +84,7 @@ public class ProductConfigItemContentWrapper implements 
ContentWrapper {
         this.delegatorName = delegator.getDelegatorName();
         this.productConfigItem = productConfigItem;
         this.locale = UtilHttp.getLocale(request);
-        this.mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8", this.delegator);
+        this.mimeTypeId = ContentWrapper.getDefaultMimeTypeId(this.delegator);
     }
 
     @Override
@@ -121,8 +118,7 @@ public class ProductConfigItemContentWrapper implements 
ContentWrapper {
     public static String getProductConfigItemContentAsText(GenericValue 
productConfigItem, String confItemContentTypeId,
                                                            HttpServletRequest 
request, String encoderType) {
         LocalDispatcher dispatcher = (LocalDispatcher) 
request.getAttribute("dispatcher");
-        String mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8",
-                productConfigItem.getDelegator());
+        String mimeTypeId = 
ContentWrapper.getDefaultMimeTypeId(productConfigItem.getDelegator());
         return getProductConfigItemContentAsText(productConfigItem, 
confItemContentTypeId, UtilHttp.getLocale(request), mimeTypeId,
                 productConfigItem.getDelegator(), dispatcher, encoderType);
     }
@@ -134,32 +130,46 @@ public class ProductConfigItemContentWrapper implements 
ContentWrapper {
 
     public static String getProductConfigItemContentAsText(GenericValue 
productConfigItem, String confItemContentTypeId, Locale locale,
                                                            String mimeTypeId, 
Delegator delegator, LocalDispatcher dispatcher, String encoderType) {
-        UtilCodec.SimpleEncoder encoder = UtilCodec.getEncoder(encoderType);
-        String candidateFieldName = 
ModelUtil.dbNameToVarName(confItemContentTypeId);
-        String cacheKey = confItemContentTypeId + SEPARATOR + locale + 
SEPARATOR + mimeTypeId + SEPARATOR + productConfigItem.get("configItemId")
-                + SEPARATOR + encoderType + SEPARATOR + delegator;
+        if (productConfigItem == null) {
+            return null;
+        }
+        /* Look for a previously cached entry (may also be an entry with null 
value if
+         * there was no content to retrieve)
+         */
+        String cacheKey = confItemContentTypeId + SEPARATOR + locale + 
SEPARATOR + mimeTypeId + SEPARATOR
+                + productConfigItem.get("configItemId") + SEPARATOR + 
encoderType + SEPARATOR + delegator;
+        String cachedValue = CONFIG_ITEM_CONTENT_CACHE.get(cacheKey);
+        if (cachedValue != null || 
CONFIG_ITEM_CONTENT_CACHE.containsKey(cacheKey)) {
+            return cachedValue;
+        }
+
+        // Get content of given contentTypeId
+        boolean doCache = true;
+        String outString = null;
+
         try {
-            String cachedValue = CONFIG_ITEM_CONTENT_CACHE.get(cacheKey);
-            if (cachedValue != null) {
-                return cachedValue;
-            }
             Writer outWriter = new StringWriter();
             getProductConfigItemContentAsText(null, productConfigItem, 
confItemContentTypeId, locale, mimeTypeId, delegator, dispatcher,
                     outWriter, false);
-            String outString = outWriter.toString();
-            if (UtilValidate.isEmpty(outString)) {
-                outString = 
productConfigItem.getModelEntity().isField(candidateFieldName) ? 
productConfigItem.getString(candidateFieldName) : "";
-                outString = outString == null ? "" : outString;
-            }
-            outString = encoder.sanitize(outString, null);
-            CONFIG_ITEM_CONTENT_CACHE.put(cacheKey, outString);
-            return outString;
+            outString = outWriter.toString();
         } catch (GeneralException | IOException e) {
-            Debug.logError(e, "Error rendering ProdConfItemContent, inserting 
empty String", MODULE);
-            String candidateOut = 
productConfigItem.getModelEntity().isField(candidateFieldName)
-                    ? productConfigItem.getString(candidateFieldName) : "";
-            return candidateOut == null ? "" : encoder.sanitize(candidateOut, 
null);
+            Debug.logError(e, "Error rendering ProdConfItemContent", MODULE);
+            doCache = false;
+        }
+
+        /* If we did not found any content (or got an error), get the content 
of a
+         * candidateFieldName matching the given contentTypeId
+         */
+        if (UtilValidate.isEmpty(outString)) {
+            outString = 
ContentWrapper.getCandidateFieldValue(productConfigItem, confItemContentTypeId);
         }
+        // Encode found content via given encoderType
+        outString = ContentWrapper.encodeContentValue(outString, encoderType);
+
+        if (doCache) {
+            CONFIG_ITEM_CONTENT_CACHE.put(cacheKey, outString);
+        }
+        return outString;
     }
 
     public static void getProductConfigItemContentAsText(String configItemId, 
GenericValue productConfigItem, String confItemContentTypeId,
@@ -181,7 +191,7 @@ public class ProductConfigItemContentWrapper implements 
ContentWrapper {
         }
 
         if (UtilValidate.isEmpty(mimeTypeId)) {
-            mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8", delegator);
+            mimeTypeId = ContentWrapper.getDefaultMimeTypeId(delegator);
         }
 
         GenericValue productConfigItemContent = 
EntityQuery.use(delegator).from("ProdConfItemContent")
@@ -198,23 +208,17 @@ public class ProductConfigItemContentWrapper implements 
ContentWrapper {
             inContext.put("productConfigItemContent", 
productConfigItemContent);
             ContentWorker.renderContentAsText(dispatcher, 
productConfigItemContent.getString("contentId"), outWriter, inContext, locale,
                     mimeTypeId, null, null, cache);
-            return;
-        }
-
-        String candidateFieldName = 
ModelUtil.dbNameToVarName(confItemContentTypeId);
-        ModelEntity productConfigItemModel = 
delegator.getModelEntity("ProductConfigItem");
-        if (productConfigItemModel.isField(candidateFieldName)) {
-            if (productConfigItem == null) {
-                productConfigItem = 
EntityQuery.use(delegator).from("ProductConfigItem").where("configItemId", 
configItemId).cache().queryOne();
-            }
+        } else {
+            String candidateValue = null;
             if (productConfigItem != null) {
-                String candidateValue = 
productConfigItem.getString(candidateFieldName);
-                if (UtilValidate.isNotEmpty(candidateValue)) {
-                    outWriter.write(candidateValue);
-                    return;
-                }
+                candidateValue = 
ContentWrapper.getCandidateFieldValue(productConfigItem, confItemContentTypeId);
+            } else {
+                candidateValue = 
ContentWrapper.getCandidateFieldValue(delegator, "ProductConfigItem", 
EntityCondition
+                        .makeCondition("configItemId", configItemId), 
confItemContentTypeId, cache);
+            }
+            if (UtilValidate.isNotEmpty(candidateValue)) {
+                outWriter.write(candidateValue);
             }
         }
     }
 }
-
diff --git 
a/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductContentWrapper.java
 
b/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductContentWrapper.java
index 4e103cea8c..243a811f77 100644
--- 
a/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductContentWrapper.java
+++ 
b/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductContentWrapper.java
@@ -30,9 +30,7 @@ import javax.servlet.http.HttpServletRequest;
 
 import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.GeneralException;
-import org.apache.ofbiz.base.util.GeneralRuntimeException;
 import org.apache.ofbiz.base.util.StringUtil;
-import org.apache.ofbiz.base.util.UtilCodec;
 import org.apache.ofbiz.base.util.UtilHttp;
 import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.base.util.cache.UtilCache;
@@ -40,11 +38,8 @@ import org.apache.ofbiz.content.content.ContentWorker;
 import org.apache.ofbiz.content.content.ContentWrapper;
 import org.apache.ofbiz.entity.Delegator;
 import org.apache.ofbiz.entity.GenericValue;
-import org.apache.ofbiz.entity.model.ModelEntity;
-import org.apache.ofbiz.entity.model.ModelUtil;
 import org.apache.ofbiz.entity.util.EntityQuery;
 import org.apache.ofbiz.entity.util.EntityUtil;
-import org.apache.ofbiz.entity.util.EntityUtilProperties;
 import org.apache.ofbiz.service.LocalDispatcher;
 
 /**
@@ -77,8 +72,7 @@ public class ProductContentWrapper implements ContentWrapper {
         this.dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
         this.product = product;
         this.locale = UtilHttp.getLocale(request);
-        this.mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8",
-                (Delegator) request.getAttribute("delegator"));
+        this.mimeTypeId = ContentWrapper.getDefaultMimeTypeId((Delegator) 
request.getAttribute("delegator"));
     }
 
     @Override
@@ -94,7 +88,7 @@ public class ProductContentWrapper implements ContentWrapper {
 
     public static String getProductContentAsText(GenericValue product, String 
productContentTypeId, HttpServletRequest request, String encoderType) {
         LocalDispatcher dispatcher = (LocalDispatcher) 
request.getAttribute("dispatcher");
-        String mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8", product.getDelegator());
+        String mimeTypeId = 
ContentWrapper.getDefaultMimeTypeId(product.getDelegator());
         return getProductContentAsText(product, productContentTypeId, 
UtilHttp.getLocale(request), mimeTypeId, null, null,
                 product.getDelegator(), dispatcher, encoderType);
     }
@@ -104,41 +98,56 @@ public class ProductContentWrapper implements 
ContentWrapper {
         return getProductContentAsText(product, productContentTypeId, locale, 
null, null, null, null, dispatcher, encoderType);
     }
 
-    public static String getProductContentAsText(GenericValue product, String 
productContentTypeId, Locale locale, String mimeTypeId, String partyId,
+    public static String getProductContentAsText(GenericValue product, String 
productContentTypeId, Locale locale,
+            String mimeTypeId, String partyId,
             String roleTypeId, Delegator delegator, LocalDispatcher 
dispatcher, String encoderType) {
         if (product == null) {
             return null;
         }
 
-        UtilCodec.SimpleEncoder encoder = UtilCodec.getEncoder(encoderType);
-        String candidateFieldName = 
ModelUtil.dbNameToVarName(productContentTypeId);
-        /* caching: there is one cache created, "product.content"  Each 
product's content is cached with a key of
-         * contentTypeId::locale::mimeType::productId, or whatever the 
SEPARATOR is defined above to be.
+        /*
+         * Look for a previously cached entry (may also be an entry with null 
value if
+         * there was no content to retrieve) caching: there is one cache 
created,
+         * "product.content" Each product's content is cached with a key of
+         * contentTypeId::locale::mimeType::productId, or whatever the 
SEPARATOR is
+         * defined above to be.
          */
-        String cacheKey = productContentTypeId + SEPARATOR + locale + 
SEPARATOR + mimeTypeId + SEPARATOR + product.get("productId") + SEPARATOR
+        String cacheKey = productContentTypeId + SEPARATOR + locale + 
SEPARATOR + mimeTypeId + SEPARATOR + product.get(
+                "productId") + SEPARATOR
                 + encoderType + SEPARATOR + delegator;
-        try {
-            String cachedValue = PRODUCT_CONTENT_CACHE.get(cacheKey);
-            if (cachedValue != null) {
-                return cachedValue;
-            }
+        String cachedValue = PRODUCT_CONTENT_CACHE.get(cacheKey);
+        if (cachedValue != null || 
PRODUCT_CONTENT_CACHE.containsKey(cacheKey)) {
+            return cachedValue;
+        }
 
+        // Get content of given contentTypeId
+        boolean doCache = true;
+        String outString = null;
+        try {
             Writer outWriter = new StringWriter();
-            getProductContentAsText(null, product, productContentTypeId, 
locale, mimeTypeId, partyId, roleTypeId, delegator, dispatcher,
+            getProductContentAsText(null, product, productContentTypeId, 
locale, mimeTypeId, partyId, roleTypeId,
+                    delegator, dispatcher,
                     outWriter, false);
-            String outString = outWriter.toString();
-            if (UtilValidate.isEmpty(outString)) {
-                outString = 
product.getModelEntity().isField(candidateFieldName) ? 
product.getString(candidateFieldName) : "";
-                outString = outString == null ? "" : outString;
-            }
-            outString = encoder.sanitize(outString, null);
-            PRODUCT_CONTENT_CACHE.put(cacheKey, outString);
-            return outString;
+            outString = outWriter.toString();
         } catch (GeneralException | IOException e) {
-            Debug.logError(e, "Error rendering ProductContent, inserting empty 
String", MODULE);
-            String candidateOut = 
product.getModelEntity().isField(candidateFieldName) ? 
product.getString(candidateFieldName) : "";
-            return candidateOut == null ? "" : encoder.sanitize(candidateOut, 
null);
+            Debug.logError(e, "Error rendering ProductContent", MODULE);
+            doCache = false;
+        }
+
+        /*
+         * If we did not found any content (or got an error), get the content 
of a
+         * candidateFieldName matching the given contentTypeId
+         */
+        if (UtilValidate.isEmpty(outString)) {
+            outString = ContentWrapper.getCandidateFieldValue(product, 
productContentTypeId);
+        }
+        // Encode found content via given encoderType
+        outString = ContentWrapper.encodeContentValue(outString, encoderType);
+
+        if (doCache) {
+            PRODUCT_CONTENT_CACHE.put(cacheKey, outString);
         }
+        return outString;
     }
 
     public static void getProductContentAsText(String productId, GenericValue 
product, String productContentTypeId, Locale locale, String mimeTypeId,
@@ -151,29 +160,30 @@ public class ProductContentWrapper implements 
ContentWrapper {
     public static void getProductContentAsText(String productId, GenericValue 
product, String productContentTypeId, Locale locale, String mimeTypeId,
                                                String partyId, String 
roleTypeId, Delegator delegator, LocalDispatcher dispatcher,
                                                Writer outWriter, boolean 
cache) throws GeneralException, IOException {
-        if (productId == null && product != null) {
+        if (product != null) {
             productId = product.getString("productId");
+        } else if (productId != null) {
+            product = 
EntityQuery.use(delegator).from("Product").where("productId", 
productId).cache(cache).queryOne();
+        } else {
+            throw new GeneralException("Missing parameter product or 
productId!");
         }
 
-        if (delegator == null && product != null) {
+        if (delegator == null) {
             delegator = product.getDelegator();
         }
-
         if (UtilValidate.isEmpty(mimeTypeId)) {
-            mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8", delegator);
-        }
-
-        if (delegator == null) {
-            throw new GeneralRuntimeException("Unable to find a delegator to 
use!");
+            mimeTypeId = ContentWrapper.getDefaultMimeTypeId(delegator);
         }
 
+        GenericValue parentProduct = null;
         List<GenericValue> productContentList = 
EntityQuery.use(delegator).from("ProductContent").where("productId", productId,
                 "productContentTypeId", 
productContentTypeId).orderBy("-fromDate").cache(cache).filterByDate().queryList();
-        if (UtilValidate.isEmpty(productContentList) && 
("Y".equals(product.getString("isVariant")))) {
-            GenericValue parent = ProductWorker.getParentProduct(productId, 
delegator);
-            if (parent != null) {
-                productContentList = 
EntityQuery.use(delegator).from("ProductContent").where("productId", 
parent.get("productId"),
-                        "productContentTypeId", 
productContentTypeId).orderBy("-fromDate").cache(cache).filterByDate().queryList();
+        if (UtilValidate.isEmpty(productContentList) && 
("Y".equals(product.get("isVariant")))) {
+            parentProduct = ProductWorker.getParentProduct(productId, 
delegator);
+            if (parentProduct != null) {
+                productContentList = 
EntityQuery.use(delegator).from("ProductContent").where("productId", 
parentProduct
+                        .get("productId"), "productContentTypeId", 
productContentTypeId).orderBy("-fromDate").cache(
+                                cache).filterByDate().queryList();
             }
         }
         GenericValue productContent = EntityUtil.getFirst(productContentList);
@@ -184,34 +194,13 @@ public class ProductContentWrapper implements 
ContentWrapper {
             inContext.put("productContent", productContent);
             ContentWorker.renderContentAsText(dispatcher, 
productContent.getString("contentId"), outWriter, inContext, locale, mimeTypeId,
                     partyId, roleTypeId, cache);
-            return;
-        }
-
-        String candidateFieldName = 
ModelUtil.dbNameToVarName(productContentTypeId);
-        ModelEntity productModel = delegator.getModelEntity("Product");
-        if (product == null) {
-            product = 
EntityQuery.use(delegator).from("Product").where("productId", 
productId).cache().queryOne();
-        }
-        if (UtilValidate.isEmpty(product)) {
-            Debug.logWarning("No Product entity found for productId: " + 
productId, MODULE);
-            return;
-        }
-
-        if (productModel.isField(candidateFieldName)) {
-            String candidateValue = product.getString(candidateFieldName);
+        } else {
+            String candidateValue = 
ContentWrapper.getCandidateFieldValue(product, productContentTypeId);
+            if (UtilValidate.isEmpty(candidateValue) && parentProduct != null) 
{
+                candidateValue = 
ContentWrapper.getCandidateFieldValue(parentProduct, productContentTypeId);
+            }
             if (UtilValidate.isNotEmpty(candidateValue)) {
                 outWriter.write(candidateValue);
-                return;
-            } else if ("Y".equals(product.getString("isVariant"))) {
-                // look up the virtual product
-                GenericValue parent = 
ProductWorker.getParentProduct(productId, delegator);
-                if (parent != null) {
-                    candidateValue = parent.getString(candidateFieldName);
-                    if (UtilValidate.isNotEmpty(candidateValue)) {
-                        outWriter.write(candidateValue);
-                        return;
-                    }
-                }
             }
         }
     }
diff --git 
a/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductPromoContentWrapper.java
 
b/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductPromoContentWrapper.java
index 83f818a2e2..70fcfe69e1 100644
--- 
a/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductPromoContentWrapper.java
+++ 
b/applications/product/src/main/java/org/apache/ofbiz/product/product/ProductPromoContentWrapper.java
@@ -33,7 +33,6 @@ import org.apache.ofbiz.base.util.Debug;
 import org.apache.ofbiz.base.util.GeneralException;
 import org.apache.ofbiz.base.util.GeneralRuntimeException;
 import org.apache.ofbiz.base.util.StringUtil;
-import org.apache.ofbiz.base.util.UtilCodec;
 import org.apache.ofbiz.base.util.UtilHttp;
 import org.apache.ofbiz.base.util.UtilValidate;
 import org.apache.ofbiz.base.util.cache.UtilCache;
@@ -44,11 +43,8 @@ import org.apache.ofbiz.entity.GenericValue;
 import org.apache.ofbiz.entity.condition.EntityCondition;
 import org.apache.ofbiz.entity.condition.EntityExpr;
 import org.apache.ofbiz.entity.condition.EntityOperator;
-import org.apache.ofbiz.entity.model.ModelEntity;
-import org.apache.ofbiz.entity.model.ModelUtil;
 import org.apache.ofbiz.entity.util.EntityQuery;
 import org.apache.ofbiz.entity.util.EntityUtil;
-import org.apache.ofbiz.entity.util.EntityUtilProperties;
 import org.apache.ofbiz.service.LocalDispatcher;
 
 /**
@@ -82,8 +78,7 @@ public class ProductPromoContentWrapper implements 
ContentWrapper {
         this.dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
         this.productPromo = productPromo;
         this.locale = UtilHttp.getLocale(request);
-        this.mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8",
-                (Delegator) request.getAttribute("delegator"));
+        this.mimeTypeId = ContentWrapper.getDefaultMimeTypeId((Delegator) 
request.getAttribute("delegator"));
     }
 
     @Override
@@ -102,7 +97,7 @@ public class ProductPromoContentWrapper implements 
ContentWrapper {
         LocalDispatcher dispatcher = (LocalDispatcher) 
request.getAttribute("dispatcher");
         Delegator delegator = (Delegator) request.getAttribute("delegator");
         return getProductPromoContentAsText(productPromo, 
productPromoContentTypeId, UtilHttp.getLocale(request),
-                EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8", delegator),
+                ContentWrapper.getDefaultMimeTypeId(delegator),
                 null, null, productPromo.getDelegator(), dispatcher, 
encoderType);
     }
 
@@ -117,35 +112,45 @@ public class ProductPromoContentWrapper implements 
ContentWrapper {
             return null;
         }
 
-        UtilCodec.SimpleEncoder encoder = UtilCodec.getEncoder(encoderType);
-        String candidateFieldName = 
ModelUtil.dbNameToVarName(productPromoContentTypeId);
+        /* Look for a previously cached entry (may also be an entry with null 
value if
+         * there was no content to retrieve)
+         */
         /* caching: there is one cache created, "product.promo.content"  Each 
productPromo's content is cached with a key of
          * contentTypeId::locale::mimeType::productPromoId, or whatever the 
SEPARATOR is defined above to be.
          */
         String cacheKey = productPromoContentTypeId + SEPARATOR + locale + 
SEPARATOR + mimeTypeId + SEPARATOR + productPromo.get("productPromoId")
                 + SEPARATOR + encoderType + SEPARATOR + delegator;
-        try {
-            String cachedValue = PRODUCT_PROMO_CONTENT_CACHE.get(cacheKey);
-            if (cachedValue != null) {
-                return cachedValue;
-            }
+        String cachedValue = PRODUCT_PROMO_CONTENT_CACHE.get(cacheKey);
+        if (cachedValue != null || 
PRODUCT_PROMO_CONTENT_CACHE.containsKey(cacheKey)) {
+            return cachedValue;
+        }
 
+        // Get content of given contentTypeId
+        boolean doCache = true;
+        String outString = null;
+        try {
             Writer outWriter = new StringWriter();
             getProductPromoContentAsText(null, productPromo, 
productPromoContentTypeId, locale, mimeTypeId, partyId, roleTypeId,
                     delegator, dispatcher, outWriter, false);
-            String outString = outWriter.toString();
-            if (UtilValidate.isEmpty(outString)) {
-                outString = 
productPromo.getModelEntity().isField(candidateFieldName) ? 
productPromo.getString(candidateFieldName) : "";
-                outString = outString == null ? "" : outString;
-            }
-            outString = encoder.sanitize(outString, null);
-            PRODUCT_PROMO_CONTENT_CACHE.put(cacheKey, outString);
-            return outString;
+            outString = outWriter.toString();
         } catch (GeneralException | IOException e) {
-            Debug.logError(e, "Error rendering ProductPromoContent, inserting 
empty String", MODULE);
-            String candidateOut = 
productPromo.getModelEntity().isField(candidateFieldName) ? 
productPromo.getString(candidateFieldName) : "";
-            return candidateOut == null ? "" : encoder.sanitize(candidateOut, 
null);
+            Debug.logError(e, "Error rendering ProductPromoContent", MODULE);
+            doCache = false;
         }
+
+        /* If we did not found any content (or got an error), get the content 
of a
+         * candidateFieldName matching the given contentTypeId
+         */
+        if (UtilValidate.isEmpty(outString)) {
+            outString = ContentWrapper.getCandidateFieldValue(productPromo, 
productPromoContentTypeId);
+        }
+        // Encode found content via given encoderType
+        outString = ContentWrapper.encodeContentValue(outString, encoderType);
+
+        if (doCache) {
+            PRODUCT_PROMO_CONTENT_CACHE.put(cacheKey, outString);
+        }
+        return outString;
     }
 
     public static void getProductPromoContentAsText(String productPromoId, 
GenericValue productPromo, String productPromoContentTypeId,
@@ -167,7 +172,7 @@ public class ProductPromoContentWrapper implements 
ContentWrapper {
         }
 
         if (UtilValidate.isEmpty(mimeTypeId)) {
-            mimeTypeId = EntityUtilProperties.getPropertyValue("content", 
"defaultMimeType", "text/html; charset=utf-8", delegator);
+            mimeTypeId = ContentWrapper.getDefaultMimeTypeId(delegator);
         }
 
         if (UtilValidate.isEmpty(delegator)) {
@@ -192,21 +197,16 @@ public class ProductPromoContentWrapper implements 
ContentWrapper {
             inContext.put("productPromoContent", productPromoContent);
             ContentWorker.renderContentAsText(dispatcher, 
productPromoContent.getString("contentId"), outWriter,
                     inContext, locale, mimeTypeId, partyId, roleTypeId, cache);
-            return;
-        }
-
-        String candidateFieldName = 
ModelUtil.dbNameToVarName(productPromoContentTypeId);
-        ModelEntity productModel = delegator.getModelEntity("ProductPromo");
-        if (productModel.isField(candidateFieldName)) {
-            if (UtilValidate.isEmpty(productPromo)) {
-                productPromo = 
EntityQuery.use(delegator).from("ProductPromo").where("productPromoId", 
productPromoId).cache().queryOne();
-            }
+        } else {
+            String candidateValue = null;
             if (productPromo != null) {
-                String candidateValue = 
productPromo.getString(candidateFieldName);
-                if (UtilValidate.isNotEmpty(candidateValue)) {
-                    outWriter.write(candidateValue);
-                    return;
-                }
+                candidateValue = 
ContentWrapper.getCandidateFieldValue(productPromo, productPromoContentTypeId);
+            } else {
+                candidateValue = 
ContentWrapper.getCandidateFieldValue(delegator, "ProductPromo", EntityCondition
+                        .makeCondition("productPromoId", productPromoId), 
productPromoContentTypeId, cache);
+            }
+            if (UtilValidate.isNotEmpty(candidateValue)) {
+                outWriter.write(candidateValue);
             }
         }
     }

Reply via email to