From 6a5d45cba73e2000690c6aa46edc8322ed5ec452 Mon Sep 17 00:00:00 2001 From: hengsin Date: Tue, 7 Mar 2023 01:33:57 +0800 Subject: [PATCH] IDEMPIERE-5542 [DisplayType] - Cache issue (#1687) --- .../src/org/compiere/util/DisplayType.java | 162 ++++++++++++++---- .../idempiere/test/performance/CacheTest.java | 2 + 2 files changed, 128 insertions(+), 36 deletions(-) diff --git a/org.adempiere.base/src/org/compiere/util/DisplayType.java b/org.adempiere.base/src/org/compiere/util/DisplayType.java index 988dac954b..d719bc6669 100644 --- a/org.adempiere.base/src/org/compiere/util/DisplayType.java +++ b/org.adempiere.base/src/org/compiere/util/DisplayType.java @@ -231,21 +231,28 @@ public final class DisplayType || displayType == Image || displayType == Chart || displayType == RecordID) return true; + //not custom type, don't have to check factory + if (displayType < 1000000) + return false; + IServiceReferenceHolder cache = s_displayTypeFactoryCache.get(displayType); if (cache != null) { IDisplayTypeFactory service = cache.getService(); if (service != null) return service.isID(displayType); + else + s_displayTypeFactoryCache.remove(displayType); } - if (! s_displayTypeFactoryCache.containsKey(displayType)) { + String customTypeKey = displayType+"|isID"; + if (! s_customDisplayTypeNegativeCache.containsKey(customTypeKey)) { Optional> found = getDisplayTypeFactories().stream() .filter(e -> e.getService() != null && e.getService().isID(displayType)) .findFirst(); if (found.isPresent()) { s_displayTypeFactoryCache.put(displayType, found.get()); - return found.get().getService().isID(displayType); + return true; } - s_displayTypeFactoryCache.put(displayType, null); + s_customDisplayTypeNegativeCache.put(customTypeKey, Boolean.TRUE); } return false; @@ -263,21 +270,28 @@ public final class DisplayType || displayType == Integer || displayType == Quantity) return true; + //not custom type, don't have to check factory + if (displayType < 1000000) + return false; + IServiceReferenceHolder cache = s_displayTypeFactoryCache.get(displayType); if (cache != null) { IDisplayTypeFactory service = cache.getService(); if (service != null) return service.isNumeric(displayType); + else + s_displayTypeFactoryCache.remove(displayType); } - if (! s_displayTypeFactoryCache.containsKey(displayType)) { + String customTypeKey = displayType + "|isNumeric"; + if (! s_customDisplayTypeNegativeCache.containsKey(customTypeKey)) { Optional> found = getDisplayTypeFactories().stream() .filter(e -> e.getService() != null && e.getService().isNumeric(displayType)) .findFirst(); if (found.isPresent()) { s_displayTypeFactoryCache.put(displayType, found.get()); - return found.get().getService().isNumeric(displayType); + return true; } - s_displayTypeFactoryCache.put(displayType, null); + s_customDisplayTypeNegativeCache.put(customTypeKey, Boolean.TRUE); } return false; @@ -299,15 +313,23 @@ public final class DisplayType || displayType == Quantity) return 4; + //not custom type, don't have to check factory + if (displayType < 1000000) + return 0; + IServiceReferenceHolder cache = s_displayTypeFactoryCache.get(displayType); if (cache != null) { IDisplayTypeFactory service = cache.getService(); if (service != null) { Integer v = service.getDefaultPrecision(displayType); return v != null ? v.intValue() : 0; + } else { + s_displayTypeFactoryCache.remove(displayType); } } - if (! s_displayTypeFactoryCache.containsKey(displayType)) { + + String customTypeKey = displayType + "|getDefaultPrecision"; + if (! s_customDisplayTypeNegativeCache.containsKey(customTypeKey)) { Optional> found = getDisplayTypeFactories().stream() .filter(e -> e.getService() != null && e.getService().getDefaultPrecision(displayType) != null) .findFirst(); @@ -316,7 +338,7 @@ public final class DisplayType Integer v = found.get().getService().getDefaultPrecision(displayType); return v != null ? v.intValue() : 0; } - s_displayTypeFactoryCache.put(displayType, null); + s_customDisplayTypeNegativeCache.put(customTypeKey, Boolean.TRUE); } return 0; } // getDefaultPrecision @@ -342,21 +364,29 @@ public final class DisplayType || displayType == TimeZoneId) return true; + //not custom type, don't have to check factory + if (displayType < 1000000) + return false; + IServiceReferenceHolder cache = s_displayTypeFactoryCache.get(displayType); if (cache != null) { IDisplayTypeFactory service = cache.getService(); if (service != null) return service.isText(displayType); + else + s_displayTypeFactoryCache.remove(displayType); } - if (! s_displayTypeFactoryCache.containsKey(displayType)) { + + String customTypeKey = displayType + "|isText"; + if (! s_customDisplayTypeNegativeCache.containsKey(customTypeKey)) { Optional> found = getDisplayTypeFactories().stream() .filter(e -> e.getService() != null && e.getService().isText(displayType)) .findFirst(); if (found.isPresent()) { s_displayTypeFactoryCache.put(displayType, found.get()); - return found.get().getService().isText(displayType); + return true; } - s_displayTypeFactoryCache.put(displayType, null); + s_customDisplayTypeNegativeCache.put(customTypeKey, Boolean.TRUE); } return false; } // isText @@ -375,21 +405,29 @@ public final class DisplayType if (isTimestampWithTimeZone(displayType)) return true; + //not custom type, don't have to check factory + if (displayType < 1000000) + return false; + IServiceReferenceHolder cache = s_displayTypeFactoryCache.get(displayType); if (cache != null) { IDisplayTypeFactory service = cache.getService(); if (service != null) return service.isDate(displayType); + else + s_displayTypeFactoryCache.remove(displayType); } - if (! s_displayTypeFactoryCache.containsKey(displayType)) { + + String customTypeKey = displayType + "|isDate"; + if (! s_customDisplayTypeNegativeCache.containsKey(customTypeKey)) { Optional> found = getDisplayTypeFactories().stream() .filter(e -> e.getService() != null && e.getService().isDate(displayType)) .findFirst(); if (found.isPresent()) { s_displayTypeFactoryCache.put(displayType, found.get()); - return found.get().getService().isDate(displayType); + return true; } - s_displayTypeFactoryCache.put(displayType, null); + s_customDisplayTypeNegativeCache.put(customTypeKey, Boolean.TRUE); } return false; @@ -408,21 +446,29 @@ public final class DisplayType || DisplayType.Payment == displayType) return true; + //not custom type, don't have to check factory + if (displayType < 1000000) + return false; + IServiceReferenceHolder cache = s_displayTypeFactoryCache.get(displayType); if (cache != null) { IDisplayTypeFactory service = cache.getService(); if (service != null) return service.isList(displayType); + else + s_displayTypeFactoryCache.remove(displayType); } - if (! s_displayTypeFactoryCache.containsKey(displayType)) { + + String customTypeKey = displayType + "|isList"; + if (! s_customDisplayTypeNegativeCache.containsKey(customTypeKey)) { Optional> found = getDisplayTypeFactories().stream() .filter(e -> e.getService() != null && e.getService().isList(displayType)) .findFirst(); if (found.isPresent()) { s_displayTypeFactoryCache.put(displayType, found.get()); - return found.get().getService().isList(displayType); + return true; } - s_displayTypeFactoryCache.put(displayType, null); + s_customDisplayTypeNegativeCache.put(customTypeKey, Boolean.TRUE); } return false; @@ -444,21 +490,29 @@ public final class DisplayType || displayType == ChosenMultipleSelectionList) return true; + //not custom type, don't have to check factory + if (displayType < 1000000) + return false; + IServiceReferenceHolder cache = s_displayTypeFactoryCache.get(displayType); if (cache != null) { IDisplayTypeFactory service = cache.getService(); if (service != null) return service.isLookup(displayType); + else + s_displayTypeFactoryCache.remove(displayType); } - if (! s_displayTypeFactoryCache.containsKey(displayType)) { + + String customTypeKey = displayType + "|isLookup"; + if (! s_customDisplayTypeNegativeCache.containsKey(customTypeKey)) { Optional> found = getDisplayTypeFactories().stream() .filter(e -> e.getService() != null && e.getService().isLookup(displayType)) .findFirst(); if (found.isPresent()) { s_displayTypeFactoryCache.put(displayType, found.get()); - return found.get().getService().isLookup(displayType); + return true; } - s_displayTypeFactoryCache.put(displayType, null); + s_customDisplayTypeNegativeCache.put(customTypeKey, Boolean.TRUE); } return false; @@ -475,21 +529,29 @@ public final class DisplayType || displayType == TextLong) return true; + //not custom type, don't have to check factory + if (displayType < 1000000) + return false; + IServiceReferenceHolder cache = s_displayTypeFactoryCache.get(displayType); if (cache != null) { IDisplayTypeFactory service = cache.getService(); if (service != null) return service.isLOB(displayType); + else + s_displayTypeFactoryCache.remove(displayType); } - if (! s_displayTypeFactoryCache.containsKey(displayType)) { + + String customTypeKey = displayType + "|isLOB"; + if (! s_customDisplayTypeNegativeCache.containsKey(customTypeKey)) { Optional> found = getDisplayTypeFactories().stream() .filter(e -> e.getService() != null && e.getService().isLOB(displayType)) .findFirst(); if (found.isPresent()) { s_displayTypeFactoryCache.put(displayType, found.get()); - return found.get().getService().isLOB(displayType); + return true; } - s_displayTypeFactoryCache.put(displayType, null); + s_customDisplayTypeNegativeCache.put(customTypeKey, Boolean.TRUE); } return false; @@ -576,6 +638,10 @@ public final class DisplayType } else { + //not custom type, don't have to check factory + if (displayType < 1000000) + return format; + IServiceReferenceHolder cache = s_displayTypeFactoryCache.get(displayType); if (cache != null) { IDisplayTypeFactory service = cache.getService(); @@ -583,9 +649,13 @@ public final class DisplayType DecimalFormat f = service.getNumberFormat(displayType, language, pattern); if (f != null) return f; + } else { + s_displayTypeFactoryCache.remove(displayType); } } - if (! s_displayTypeFactoryCache.containsKey(displayType)) { + + String customTypeKey = displayType + "|getNumberFormat"; + if (! s_customDisplayTypeNegativeCache.containsKey(customTypeKey)) { Optional> found = getDisplayTypeFactories().stream() .filter(e -> e.getService() != null && e.getService().getNumberFormat(displayType, language, pattern) != null) .findFirst(); @@ -593,7 +663,7 @@ public final class DisplayType s_displayTypeFactoryCache.put(displayType, found.get()); return found.get().getService().getNumberFormat(displayType, language, pattern); } - s_displayTypeFactoryCache.put(displayType, null); + s_customDisplayTypeNegativeCache.put(customTypeKey, Boolean.TRUE); } format.setMaximumIntegerDigits(MAX_DIGITS); @@ -709,7 +779,7 @@ public final class DisplayType format = myLanguage.getDateTimeFormat(); return setTimeZone(format); } - else { + else if (displayType >= 1000000) { //custom display type IServiceReferenceHolder cache = s_displayTypeFactoryCache.get(displayType); if (cache != null) { IDisplayTypeFactory service = cache.getService(); @@ -717,9 +787,13 @@ public final class DisplayType SimpleDateFormat v = service.getDateFormat(displayType, language, pattern); if (v != null) return v; + } else { + s_displayTypeFactoryCache.remove(displayType); } } - if (! s_displayTypeFactoryCache.containsKey(displayType)) { + + String customTypeKey = displayType + "|getDateFormat"; + if (! s_customDisplayTypeNegativeCache.containsKey(customTypeKey)) { Optional> found = getDisplayTypeFactories().stream() .filter(e -> e.getService() != null && e.getService().getDateFormat(displayType, language, pattern) != null) .findFirst(); @@ -727,7 +801,7 @@ public final class DisplayType s_displayTypeFactoryCache.put(displayType, found.get()); return found.get().getService().getDateFormat(displayType, language, pattern); } - s_displayTypeFactoryCache.put(displayType, null); + s_customDisplayTypeNegativeCache.put(customTypeKey, Boolean.TRUE); } } @@ -798,7 +872,7 @@ public final class DisplayType return String.class; else if (isLOB(displayType)) // CLOB is String return byte[].class; - else + else if (displayType >= 1000000) // custom display type { IServiceReferenceHolder cache = s_displayTypeFactoryCache.get(displayType); if (cache != null) { @@ -807,9 +881,13 @@ public final class DisplayType Class v = service.getClass(displayType, yesNoAsBoolean); if (v != null) return v; + } else { + s_displayTypeFactoryCache.remove(displayType); } } - if (! s_displayTypeFactoryCache.containsKey(displayType)) { + + String customTypeKey = displayType + "|getClass"; + if (! s_customDisplayTypeNegativeCache.containsKey(customTypeKey)) { Optional> found = getDisplayTypeFactories().stream() .filter(e -> e.getService() != null && e.getService().getClass(displayType, yesNoAsBoolean) != null) .findFirst(); @@ -817,7 +895,7 @@ public final class DisplayType s_displayTypeFactoryCache.put(displayType, found.get()); return found.get().getService().getClass(displayType, yesNoAsBoolean); } - s_displayTypeFactoryCache.put(displayType, null); + s_customDisplayTypeNegativeCache.put(customTypeKey, Boolean.TRUE); } } // @@ -901,9 +979,13 @@ public final class DisplayType String v = service.getSQLDataType(displayType, columnName, fieldLength); if (v != null) return v; + } else { + s_displayTypeFactoryCache.remove(displayType); } } - if (! s_displayTypeFactoryCache.containsKey(displayType)) { + + String customTypeKey = displayType + "|getSQLDataType"; + if (! s_customDisplayTypeNegativeCache.containsKey(customTypeKey)) { Optional> found = getDisplayTypeFactories().stream() .filter(e -> e.getService() != null && e.getService().getSQLDataType(displayType, columnName, fieldLength) != null) .findFirst(); @@ -911,7 +993,7 @@ public final class DisplayType s_displayTypeFactoryCache.put(displayType, found.get()); return found.get().getService().getSQLDataType(displayType, columnName, fieldLength); } - s_displayTypeFactoryCache.put(displayType, null); + s_customDisplayTypeNegativeCache.put(customTypeKey, Boolean.TRUE); } if (!DisplayType.isText(displayType)) @@ -1008,9 +1090,13 @@ public final class DisplayType String v = service.getDescription(displayType); if (v != null) return v; + } else { + s_displayTypeFactoryCache.remove(displayType); } } - if (! s_displayTypeFactoryCache.containsKey(displayType)) { + + String customTypeKey = displayType + "|getDescription"; + if (! s_customDisplayTypeNegativeCache.containsKey(customTypeKey)) { Optional> found = getDisplayTypeFactories().stream() .filter(e -> e.getService() != null && e.getService().getDescription(displayType) != null) .findFirst(); @@ -1018,7 +1104,7 @@ public final class DisplayType s_displayTypeFactoryCache.put(displayType, found.get()); return found.get().getService().getDescription(displayType); } - s_displayTypeFactoryCache.put(displayType, null); + s_customDisplayTypeNegativeCache.put(customTypeKey, Boolean.TRUE); } // @@ -1040,7 +1126,11 @@ public final class DisplayType return currencyFormatter; } // getCurrencyFormat - + /** + * Custom DisplayType|Method:Boolean.TRUE (for e.g 1000000|isID:Boolean.TRUE).
+ * Map to cache that a custom display type does not have display type factory register for a Method (isID, isNumeric, getDateFormat, etc). + */ + private final static CCache s_customDisplayTypeNegativeCache = new CCache<>(null, "CustomDisplayTypeNegativeCache", 100, false); private final static CCache> s_displayTypeFactoryCache = new CCache<>(null, "IDisplayTypeFactory", 100, false); private static List> getDisplayTypeFactories() { diff --git a/org.idempiere.test/src/org/idempiere/test/performance/CacheTest.java b/org.idempiere.test/src/org/idempiere/test/performance/CacheTest.java index b2a9b7bb31..4877ba758a 100644 --- a/org.idempiere.test/src/org/idempiere/test/performance/CacheTest.java +++ b/org.idempiere.test/src/org/idempiere/test/performance/CacheTest.java @@ -663,6 +663,8 @@ public class CacheTest extends AbstractTestCase { //IDisplayTypeFactory TestActivator.context.registerService(IDisplayTypeFactory.class, new FakeDisplayTypeFactory(), null); cacheName = "IDisplayTypeFactory"; + boolean isLOB = DisplayType.isLOB(FakeDisplayTypeFactory.DISPLAY_TYPE); + assertFalse(isLOB); boolean isText = DisplayType.isText(FakeDisplayTypeFactory.DISPLAY_TYPE); assertTrue(isText); cache = findByNameAndKey(cacheName, FakeDisplayTypeFactory.DISPLAY_TYPE);