From 7f59e3539758810e792367e97818473532fe0aa9 Mon Sep 17 00:00:00 2001 From: Marcus Talbot Date: Thu, 15 Feb 2024 09:32:46 +0100 Subject: [PATCH 1/4] Create Logger, replace existing logging - Replaced Logger in individual classes, with centralised instance in BeanMapperLogger. --- .../io/beanmapper/config/OverrideField.java | 11 +-- .../config/StrictMappingProperties.java | 13 ++-- .../io/beanmapper/core/BeanMatchStore.java | 12 ++-- .../io/beanmapper/core/BeanPropertyMatch.java | 10 +-- ...eanStrictMappingRequirementsException.java | 9 +-- .../AbstractCollectionHandler.java | 13 ++-- .../constructor/DefaultBeanInitializer.java | 9 +-- .../collections/CollectionConverter.java | 9 ++- .../impl/OptionalToObjectConverter.java | 18 ++--- .../core/unproxy/SkippingBeanUnproxy.java | 3 + .../BeanNoLogicSecuredCheckSetException.java | 7 +- .../BeanNoRoleSecuredCheckSetException.java | 7 +- .../BeanNoSuchPropertyException.java | 7 +- .../strategy/AbstractMapStrategy.java | 16 ++--- .../strategy/MapToClassStrategy.java | 3 +- .../strategy/MapToDynamicClassStrategy.java | 38 ++++++----- .../strategy/MapToRecordStrategy.java | 20 +++--- .../io/beanmapper/utils/BeanMapperLogger.java | 68 +++++++++++++++++++ .../config/BeanMapperBuilderTest.java | 2 + 19 files changed, 168 insertions(+), 107 deletions(-) create mode 100644 src/main/java/io/beanmapper/utils/BeanMapperLogger.java diff --git a/src/main/java/io/beanmapper/config/OverrideField.java b/src/main/java/io/beanmapper/config/OverrideField.java index ab75a130..274bee9e 100644 --- a/src/main/java/io/beanmapper/config/OverrideField.java +++ b/src/main/java/io/beanmapper/config/OverrideField.java @@ -2,6 +2,8 @@ import java.util.function.Supplier; +import io.beanmapper.utils.BeanMapperLogger; + public class OverrideField { private final Supplier supplier; @@ -31,9 +33,10 @@ public T get() { if (this.block) { return null; } - return this.value == null ? - this.supplier.get() : - this.value; + if (this.value == null) { + this.value = BeanMapperLogger.logTimed("Retrieving nested configuration field.", this.supplier); + } + return value; } -} \ No newline at end of file +} diff --git a/src/main/java/io/beanmapper/config/StrictMappingProperties.java b/src/main/java/io/beanmapper/config/StrictMappingProperties.java index b7f4f01e..2550ed22 100644 --- a/src/main/java/io/beanmapper/config/StrictMappingProperties.java +++ b/src/main/java/io/beanmapper/config/StrictMappingProperties.java @@ -2,6 +2,7 @@ import io.beanmapper.core.unproxy.BeanUnproxy; import io.beanmapper.core.unproxy.SkippingBeanUnproxy; +import io.beanmapper.utils.BeanMapperLogger; public class StrictMappingProperties { @@ -79,18 +80,20 @@ public void setApplyStrictMappingConvention(boolean applyStrictMappingConvention } public BeanPair createBeanPair(Class sourceClass, Class targetClass) { - sourceClass = beanUnproxy.unproxy(sourceClass); - targetClass = beanUnproxy.unproxy(targetClass); - BeanPair beanPair = new BeanPair(sourceClass, targetClass); + BeanPair beanPair = BeanMapperLogger.logTimed("Creating BeanPair, and unproxying source %s-class and target %s-class.".formatted(sourceClass.getCanonicalName(), targetClass.getCanonicalName()), () -> { + Class unproxiedSource = beanUnproxy.unproxy(sourceClass); + Class unproxiedTarget = beanUnproxy.unproxy(targetClass); + return new BeanPair(unproxiedSource, unproxiedTarget); + }); if (!isApplyStrictMappingConvention()) { return beanPair; } if (strictSourceSuffix != null && - sourceClass.getCanonicalName().endsWith(strictSourceSuffix)) { + beanPair.getSourceClass().getCanonicalName().endsWith(strictSourceSuffix)) { beanPair = beanPair.withStrictSource(); } if (strictTargetSuffix != null && - targetClass.getCanonicalName().endsWith(strictTargetSuffix)) { + beanPair.getTargetClass().getCanonicalName().endsWith(strictTargetSuffix)) { beanPair = beanPair.withStrictTarget(); } return beanPair; diff --git a/src/main/java/io/beanmapper/core/BeanMatchStore.java b/src/main/java/io/beanmapper/core/BeanMatchStore.java index 0bd3e1d1..e25642cf 100644 --- a/src/main/java/io/beanmapper/core/BeanMatchStore.java +++ b/src/main/java/io/beanmapper/core/BeanMatchStore.java @@ -34,15 +34,11 @@ import io.beanmapper.exceptions.BeanMissingPathException; import io.beanmapper.exceptions.BeanNoSuchPropertyException; import io.beanmapper.exceptions.FieldShadowingException; +import io.beanmapper.utils.BeanMapperLogger; import io.beanmapper.utils.Trinary; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class BeanMatchStore { - private final Logger logger = LoggerFactory.getLogger(getClass()); - private final CollectionHandlerStore collectionHandlerStore; private final BeanUnproxy beanUnproxy; @@ -287,11 +283,11 @@ private BeanPropertyWrapper dealWithBeanProperty(BeanPropertyMatchupDirection ma new BeanPropertyCreator(matchupDirection.getInverse(), otherType, wrapper.getName()) .determineNodesForPath()); } catch (BeanNoSuchPropertyException err) { - if (logger.isDebugEnabled()) { - logger.debug(""" + + BeanMapperLogger.log(""" BeanNoSuchPropertyException thrown by BeanMatchStore#dealWithBeanProperty(BeanPropertyMatchupDirection, Map, Class, PropertyAccessor), for {}. {}""", wrapper.getName(), err.getMessage()); - } + } } return wrapper; diff --git a/src/main/java/io/beanmapper/core/BeanPropertyMatch.java b/src/main/java/io/beanmapper/core/BeanPropertyMatch.java index 031883cf..39089edd 100644 --- a/src/main/java/io/beanmapper/core/BeanPropertyMatch.java +++ b/src/main/java/io/beanmapper/core/BeanPropertyMatch.java @@ -10,14 +10,10 @@ import io.beanmapper.exceptions.BeanMappingException; import io.beanmapper.exceptions.BeanNoLogicSecuredCheckSetException; import io.beanmapper.exceptions.BeanNoRoleSecuredCheckSetException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import io.beanmapper.utils.BeanMapperLogger; public class BeanPropertyMatch { - protected final Logger logger = LoggerFactory.getLogger(getClass()); - private final BeanMatch beanMatch; private final Object source; private final Object target; @@ -81,7 +77,7 @@ private boolean checkForLogicSecured( if (enforcedSecuredProperties) { throw new BeanNoLogicSecuredCheckSetException(message); } - logger.warn(message); + BeanMapperLogger.warn(message); return true; } return logicSecuredCheck.isAllowed(source, target); @@ -96,7 +92,7 @@ private void checkIfSecuredFieldHandlerNotSet(BeanProperty beanProperty, boolean if (enforcedSecuredProperties) { throw new BeanNoRoleSecuredCheckSetException(message); } - logger.warn(message); + BeanMapperLogger.warn(message); } } diff --git a/src/main/java/io/beanmapper/core/BeanStrictMappingRequirementsException.java b/src/main/java/io/beanmapper/core/BeanStrictMappingRequirementsException.java index dd86a92d..eacc8d52 100644 --- a/src/main/java/io/beanmapper/core/BeanStrictMappingRequirementsException.java +++ b/src/main/java/io/beanmapper/core/BeanStrictMappingRequirementsException.java @@ -3,13 +3,10 @@ import java.util.Collections; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import io.beanmapper.utils.BeanMapperLogger; public class BeanStrictMappingRequirementsException extends RuntimeException { - protected final transient Logger logger = LoggerFactory.getLogger(getClass()); - private final List validationMessages; public BeanStrictMappingRequirementsException(BeanMatchValidationMessage validationMessage) { @@ -26,7 +23,7 @@ private void logErrors(List validationMessages) { if (validationMessage.isLogged()) { continue; } - logger.error(""" + BeanMapperLogger.error(""" Missing matching properties for source [{}] {} > target [{}] {} for fields: """, validationMessage.getSourceClass().getCanonicalName(), @@ -35,7 +32,7 @@ private void logErrors(List validationMessages) { (validationMessage.isTargetStrict() ? "*" : "")); for (BeanProperty field : validationMessage.getFields()) { - logger.error(""" + BeanMapperLogger.error(""" > {}.{} """, validationMessage.getStrictClass().getSimpleName(), diff --git a/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java b/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java index 22d40940..7fd0f713 100644 --- a/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java +++ b/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java @@ -5,6 +5,7 @@ import io.beanmapper.config.CollectionFlusher; import io.beanmapper.core.constructor.DefaultBeanInitializer; import io.beanmapper.exceptions.BeanCollectionUnassignableTargetCollectionTypeException; +import io.beanmapper.utils.BeanMapperLogger; import io.beanmapper.utils.Classes; public abstract class AbstractCollectionHandler implements CollectionHandler { @@ -32,14 +33,16 @@ public Object mapItem( BeanMapper beanMapper, Class collectionElementClass, Object source) { - - return beanMapper - .wrap() + return BeanMapperLogger.logTimed("Recursively calling BeanMapper#map(Object), to map collection elements of type %s, to %s." + .formatted(source != null + ? source.getClass().getCanonicalName() + : "null", collectionElementClass.getCanonicalName()), + () -> beanMapper.wrap() .setTargetClass(collectionElementClass) .setCollectionClass(null) .setConverterChoosable(true) .build() - .map(source); + .map(source)); } @Override @@ -90,4 +93,4 @@ public int getGenericParameterIndex() { return 0; } -} \ No newline at end of file +} diff --git a/src/main/java/io/beanmapper/core/constructor/DefaultBeanInitializer.java b/src/main/java/io/beanmapper/core/constructor/DefaultBeanInitializer.java index b03f8ba8..57d317ba 100644 --- a/src/main/java/io/beanmapper/core/constructor/DefaultBeanInitializer.java +++ b/src/main/java/io/beanmapper/core/constructor/DefaultBeanInitializer.java @@ -12,20 +12,17 @@ import io.beanmapper.BeanMapper; import io.beanmapper.config.BeanMapperBuilder; import io.beanmapper.strategy.ConstructorArguments; +import io.beanmapper.utils.BeanMapperLogger; import io.beanmapper.utils.DefaultValues; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class DefaultBeanInitializer implements BeanInitializer { - private final Logger logger = LoggerFactory.getLogger(getClass()); - /** * {@inheritDoc} */ @Override public T instantiate(Class beanClass, ConstructorArguments arguments) { + BeanMapperLogger.log("Creating a new instance of type %s, using reflection.".formatted(beanClass)); try { if (arguments == null) { return beanClass.getConstructor().newInstance(); @@ -34,7 +31,7 @@ public T instantiate(Class beanClass, ConstructorArguments arguments) { var constructorParameterTypes = Arrays.stream(constructor.getParameters()).map(Parameter::getParameterizedType).toArray(Type[]::new); return beanClass.getConstructor(arguments.getTypes()).newInstance(mapParameterizedArguments(constructorParameterTypes, arguments.getValues())); } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { - logger.error("Could not instantiate bean of class %s. Returning the default value associated with the given type. %s".formatted(beanClass.getName(), + BeanMapperLogger.error("Could not instantiate bean of class %s. Returning the default value associated with the given type. %s".formatted(beanClass.getName(), e.getMessage())); return DefaultValues.defaultValueFor(beanClass); } diff --git a/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java b/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java index 41e174ae..8e1f2842 100644 --- a/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java +++ b/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java @@ -4,6 +4,7 @@ import io.beanmapper.core.BeanPropertyMatch; import io.beanmapper.core.collections.CollectionHandler; import io.beanmapper.core.converter.BeanConverter; +import io.beanmapper.utils.BeanMapperLogger; public class CollectionConverter implements BeanConverter { @@ -24,7 +25,11 @@ public U convert( return targetClass.cast(source); } - return beanMapper.wrap() + return BeanMapperLogger.logTimed("Calling BeanMapper#map(Object) recursively, to convert object of type %s, to type %s." + .formatted(source != null + ? source.getClass().getCanonicalName() + : "null", targetClass.getCanonicalName()), + () -> beanMapper.wrap() .setCollectionClass(collectionHandler.getType()) .setCollectionUsage(beanPropertyMatch.getCollectionInstructions().getBeanCollectionUsage()) .setPreferredCollectionClass(beanPropertyMatch.getCollectionInstructions().getPreferredCollectionClass().getAnnotationClass()) @@ -33,7 +38,7 @@ public U convert( .setTarget(beanPropertyMatch.getTargetObject()) .setUseNullValue() .build() - .map(source); + .map(source)); } @Override diff --git a/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java b/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java index 5fbc38e0..b555be1f 100644 --- a/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java +++ b/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java @@ -12,11 +12,9 @@ import io.beanmapper.BeanMapper; import io.beanmapper.core.BeanPropertyMatch; import io.beanmapper.core.converter.BeanConverter; +import io.beanmapper.utils.BeanMapperLogger; import io.beanmapper.utils.Classes; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - /** * This converter facilitates the conversion of an arbitrary amount of Optional wrappers, however, support for complex * datastructures, such as Maps, Sets, List, etc. is limited to a single layer. As such, if the user requires support @@ -25,8 +23,6 @@ */ public class OptionalToObjectConverter implements BeanConverter { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - /** * {@inheritDoc} */ @@ -35,13 +31,11 @@ public T convert(BeanMapper beanMapper, S source, Class targetClass, B Object obj = ((Optional) source).orElse(null); if (targetClass.equals(Optional.class)) { - if (logger.isDebugEnabled()) { - // Not always possible to get the actual source class, so just report the name of the field. Debug log will show the call stack. - logger.debug("Converting Optional to Optional. Perhaps the target does not need to be an Optional?\nSource-field: {}\nTarget: {}.{}", - beanPropertyMatch.getSourceFieldName(), - beanPropertyMatch.getTarget().getClass(), - beanPropertyMatch.getTargetFieldName()); - } + // Not always possible to get the actual source class, so just report the name of the field. Debug log will show the call stack. + BeanMapperLogger.log("Converting Optional to Optional. Perhaps the target does not need to be an Optional?\nSource-field: {}\nTarget: {}.{}", + beanPropertyMatch.getSourceFieldName(), + beanPropertyMatch.getTarget().getClass(), + beanPropertyMatch.getTargetFieldName()); return targetClass.cast(convertToOptional(beanMapper, (Optional) source, beanPropertyMatch)); } else if (obj == null) { return null; diff --git a/src/main/java/io/beanmapper/core/unproxy/SkippingBeanUnproxy.java b/src/main/java/io/beanmapper/core/unproxy/SkippingBeanUnproxy.java index 643f40f2..2ed4edff 100644 --- a/src/main/java/io/beanmapper/core/unproxy/SkippingBeanUnproxy.java +++ b/src/main/java/io/beanmapper/core/unproxy/SkippingBeanUnproxy.java @@ -6,6 +6,8 @@ import java.util.HashSet; import java.util.Set; +import io.beanmapper.utils.BeanMapperLogger; + /** * Unproxy that allows you to configure classes to skip. * @@ -31,6 +33,7 @@ public SkippingBeanUnproxy(BeanUnproxy delegate) { */ @Override public Class unproxy(Class beanClass) { + BeanMapperLogger.log("Unproxying class %s.".formatted(beanClass != null ? beanClass.getCanonicalName() : "null")); if (isSkippedProxyClass(beanClass)) { return beanClass; } diff --git a/src/main/java/io/beanmapper/exceptions/BeanNoLogicSecuredCheckSetException.java b/src/main/java/io/beanmapper/exceptions/BeanNoLogicSecuredCheckSetException.java index 065f871a..08851ac8 100644 --- a/src/main/java/io/beanmapper/exceptions/BeanNoLogicSecuredCheckSetException.java +++ b/src/main/java/io/beanmapper/exceptions/BeanNoLogicSecuredCheckSetException.java @@ -1,14 +1,11 @@ package io.beanmapper.exceptions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import io.beanmapper.utils.BeanMapperLogger; public class BeanNoLogicSecuredCheckSetException extends IllegalArgumentException { - protected final transient Logger logger = LoggerFactory.getLogger(getClass()); - public BeanNoLogicSecuredCheckSetException(String message) { super(message); - logger.error(message); + BeanMapperLogger.error(message); } } diff --git a/src/main/java/io/beanmapper/exceptions/BeanNoRoleSecuredCheckSetException.java b/src/main/java/io/beanmapper/exceptions/BeanNoRoleSecuredCheckSetException.java index ffed196c..a39b31b7 100644 --- a/src/main/java/io/beanmapper/exceptions/BeanNoRoleSecuredCheckSetException.java +++ b/src/main/java/io/beanmapper/exceptions/BeanNoRoleSecuredCheckSetException.java @@ -1,14 +1,11 @@ package io.beanmapper.exceptions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import io.beanmapper.utils.BeanMapperLogger; public class BeanNoRoleSecuredCheckSetException extends IllegalArgumentException { - protected final transient Logger logger = LoggerFactory.getLogger(getClass()); - public BeanNoRoleSecuredCheckSetException(String message) { super(message); - logger.error(message); + BeanMapperLogger.error(message); } } diff --git a/src/main/java/io/beanmapper/exceptions/BeanNoSuchPropertyException.java b/src/main/java/io/beanmapper/exceptions/BeanNoSuchPropertyException.java index c09014bd..a74776f9 100644 --- a/src/main/java/io/beanmapper/exceptions/BeanNoSuchPropertyException.java +++ b/src/main/java/io/beanmapper/exceptions/BeanNoSuchPropertyException.java @@ -3,19 +3,16 @@ */ package io.beanmapper.exceptions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import io.beanmapper.utils.BeanMapperLogger; /** * Exception thrown when a property could not be found. */ public class BeanNoSuchPropertyException extends IllegalArgumentException { - protected final transient Logger logger = LoggerFactory.getLogger(getClass()); - public BeanNoSuchPropertyException(String message) { super(message); - logger.error(message); + BeanMapperLogger.error(message); } } diff --git a/src/main/java/io/beanmapper/strategy/AbstractMapStrategy.java b/src/main/java/io/beanmapper/strategy/AbstractMapStrategy.java index ba099c1d..c005d519 100644 --- a/src/main/java/io/beanmapper/strategy/AbstractMapStrategy.java +++ b/src/main/java/io/beanmapper/strategy/AbstractMapStrategy.java @@ -12,19 +12,15 @@ import io.beanmapper.core.converter.BeanConverter; import io.beanmapper.exceptions.BeanConversionException; import io.beanmapper.exceptions.BeanPropertyNoMatchException; +import io.beanmapper.utils.BeanMapperLogger; import io.beanmapper.utils.Records; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public abstract class AbstractMapStrategy implements MapStrategy { private static final String INDENT = " "; private static final String ARROW = " -> "; - protected final Logger logger = LoggerFactory.getLogger(getClass()); - private final BeanMapper beanMapper; private final Configuration configuration; @@ -111,7 +107,7 @@ private void dealWithMappableNestedClass(BeanPropertyMatch beanPropertyMatch) { Object encapsulatedSource = beanPropertyMatch.getSourceObject(); Object target; if (encapsulatedSource != null) { - logger.debug(" {"); + BeanMapperLogger.log(" {"); BeanMapper localBeanMapper = getBeanMapper() .wrap() .setParent(beanPropertyMatch.getTarget()) @@ -122,7 +118,7 @@ private void dealWithMappableNestedClass(BeanPropertyMatch beanPropertyMatch) { target = localBeanMapper.map(encapsulatedSource, beanPropertyMatch.getTargetObject()); } beanPropertyMatch.writeObject(target); - logger.debug(" }"); + BeanMapperLogger.log(" }"); } } @@ -139,7 +135,7 @@ public Object convert(Object value, Class targetClass, BeanPropertyMatch bean BeanConverter converter = getConverterOptional(valueClass, targetClass); if (converter != null) { - logger.debug("{}{}{}", INDENT, converter.getClass().getSimpleName(), ARROW); + BeanMapperLogger.log("{}{}{}", INDENT, converter.getClass().getSimpleName(), ARROW); BeanMapper wrappedBeanMapper = beanMapper .wrap() .setParent(beanPropertyMatch.getTarget()) @@ -211,9 +207,9 @@ private void processProperty(BeanPropertyMatch beanPropertyMatch) { return; } if (beanPropertyMatch.isMappable()) { - logger.debug("{}{}", beanPropertyMatch.sourceToString(), ARROW); + BeanMapperLogger.log("{}{}", beanPropertyMatch.sourceToString(), ARROW); copySourceToTarget(beanPropertyMatch); - logger.debug("{}{}", INDENT, beanPropertyMatch.targetToString()); + BeanMapperLogger.log("{}{}", INDENT, beanPropertyMatch.targetToString()); } } diff --git a/src/main/java/io/beanmapper/strategy/MapToClassStrategy.java b/src/main/java/io/beanmapper/strategy/MapToClassStrategy.java index 26ea0ffb..942b2fea 100644 --- a/src/main/java/io/beanmapper/strategy/MapToClassStrategy.java +++ b/src/main/java/io/beanmapper/strategy/MapToClassStrategy.java @@ -4,6 +4,7 @@ import io.beanmapper.config.Configuration; import io.beanmapper.core.BeanMatch; import io.beanmapper.core.converter.BeanConverter; +import io.beanmapper.utils.BeanMapperLogger; public class MapToClassStrategy extends MapToInstanceStrategy { @@ -19,7 +20,7 @@ public T map(S source) { Class valueClass = getConfiguration().getBeanUnproxy().unproxy(source.getClass()); BeanConverter converter = getConverterOptional(valueClass, targetClass); if (converter != null) { - logger.debug("Converter called for source of class {}, while mapping to class {}\t{}->", source.getClass(), targetClass, + BeanMapperLogger.log("Converter called for source of class {}, while mapping to class {}\t{}->", source.getClass(), targetClass, converter.getClass().getSimpleName()); return (T) converter.convert(getBeanMapper(), source, targetClass, null); } diff --git a/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java b/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java index 593e7fc7..c29f5166 100644 --- a/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java +++ b/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java @@ -5,6 +5,7 @@ import io.beanmapper.BeanMapper; import io.beanmapper.config.Configuration; +import io.beanmapper.utils.BeanMapperLogger; public class MapToDynamicClassStrategy extends AbstractMapStrategy { @@ -48,21 +49,25 @@ public T downsizeSource(S source, List downsizeSourceFields) { Class targetClass = getConfiguration().getTargetClass(); Object target = getConfiguration().getTarget(); - Object dynSource = getBeanMapper() - .wrap() - .downsizeSource(null) - .setTarget(target) - .setTargetClass(dynamicClass) - .build() - .map(source); + Object dynSource = BeanMapperLogger.logTimed("Recursively calling BeanMapper#map(Object), to map source of type %s, to target of type %s." + .formatted(source.getClass().getCanonicalName(), dynamicClass.getCanonicalName()), + () -> getBeanMapper() + .wrap() + .downsizeSource(null) + .setTarget(target) + .setTargetClass(dynamicClass) + .build() + .map(source)); - return getBeanMapper() - .wrap() - .downsizeSource(null) - .setTarget(target) - .setTargetClass(targetClass) - .build() - .map(dynSource); + return BeanMapperLogger.logTimed("Recursively calling BeanMapper#map(Object), to map source of type %s, to type %s." + .formatted(dynSource.getClass().getCanonicalName(), targetClass != null ? targetClass.getCanonicalName() : "null"), + () -> getBeanMapper() + .wrap() + .downsizeSource(null) + .setTarget(target) + .setTargetClass(targetClass) + .build() + .map(dynSource)); } public T downsizeTarget(S source, List downsizeTargetFields) { @@ -71,12 +76,13 @@ public T downsizeTarget(S source, List downsizeTargetFields) { downsizeTargetFields, getConfiguration().getStrictMappingProperties()); Class collectionClass = getBeanMapper().getConfiguration().getCollectionClass(); - return getBeanMapper() + return BeanMapperLogger.logTimed("Recursively calling BeanMapper#map(Object), to map source of type %s, to type %s." + .formatted(source.getClass().getCanonicalName(), dynamicClass.getCanonicalName()), () -> getBeanMapper() .wrap() .downsizeTarget(null) .setCollectionClass(collectionClass) .setTargetClass(dynamicClass) .build() - .map(source); + .map(source)); } } diff --git a/src/main/java/io/beanmapper/strategy/MapToRecordStrategy.java b/src/main/java/io/beanmapper/strategy/MapToRecordStrategy.java index 9a579128..983f91d1 100644 --- a/src/main/java/io/beanmapper/strategy/MapToRecordStrategy.java +++ b/src/main/java/io/beanmapper/strategy/MapToRecordStrategy.java @@ -26,6 +26,7 @@ import io.beanmapper.exceptions.RecordConstructorConflictException; import io.beanmapper.exceptions.RecordNoAvailableConstructorsExceptions; import io.beanmapper.exceptions.SourceFieldAccessException; +import io.beanmapper.utils.BeanMapperLogger; import io.beanmapper.utils.Records; /** @@ -56,9 +57,8 @@ public T map(final S source) { if (getConfiguration().isConverterChoosable()) { BeanConverter converter = getConverterOptional(source.getClass(), this.getConfiguration().getTargetClass()); if (converter != null) { - if (logger.isDebugEnabled()) - logger.debug("Converter called for source of class {}, while mapping to class {}\t{}->", source.getClass(), targetClass, - converter.getClass().getSimpleName()); + BeanMapperLogger.log("Converter called for source of class {}, while mapping to class {}\t{}->", source.getClass(), targetClass, + converter.getClass().getSimpleName()); return converter.convert(getBeanMapper(), source, targetClass, null); } } @@ -76,8 +76,8 @@ public T map(final S source) { * present. * * @param sourceClass The class of the source-object. + * @param The type of the sourceClass. * @return A Map containing the fields of the source-class, mapped by the name of the field, or the value of an available BeanAlias. - * @param The type of the sourceClass. */ private Map getFieldsOfClass(final Class sourceClass) { return Arrays.stream(sourceClass.getDeclaredFields()) @@ -95,8 +95,8 @@ private Map getFieldsOfClass(final Class sourceClass) { * BeanAlias-annotation. * * @param source The source-object, of which the fields will be mapped. - * @return The fields of the source-object, mapped to the * @param + * @return The fields of the source-object, mapped to the */ private Map getSourceFields(final S source) { Map sourceFields = new HashMap<>(); @@ -115,8 +115,8 @@ private Map getSourceFields(final S source) { * from an available {@link io.beanmapper.annotations.BeanProperty BeanProperty}-annotation.

* * @param targetClass The class of the target record. + * @param The type of the target record. * @return The names of the RecordComponents as a String-array. - * @param The type of the target record. */ private String[] getNamesOfRecordComponents(final Class targetClass) { return Arrays.stream(targetClass.getRecordComponents()) @@ -137,8 +137,8 @@ private String[] getNamesOfRecordComponents(final Class targetClass) { * * @param targetClass The target record. * @param constructor The target constructor. + * @param The type of the target class. * @return The String-array containing the names of the constructor-parameters. - * @param The type of the target class. */ private String[] getNamesOfConstructorParameters(final Class targetClass, final Constructor constructor) { if (constructor.isAnnotationPresent(BeanRecordConstruct.class)) { @@ -176,7 +176,7 @@ private Object[] getConstructorArgumentsMappedToCorrectTargetType(final Paramete } else { var parameterType = parameters[i].getType(); if (Collection.class.isAssignableFrom(parameterType) || Optional.class.isAssignableFrom(parameterType) - || Map.class.isAssignableFrom(parameterType)) { + || Map.class.isAssignableFrom(parameterType)) { arguments[i] = this.getBeanMapper().map(values.get(i), (ParameterizedType) parameters[i].getParameterizedType()); } else { arguments[i] = values.get(i) != null && parameters[i].getType().equals(values.get(i).getClass()) ? @@ -232,8 +232,8 @@ private Constructor getSuitableConstructor(final Map sourc var recordConstruct = (BeanRecordConstruct) canonicalConstructor.getAnnotation(BeanRecordConstruct.class); if (recordConstruct.constructMode() == BeanRecordConstructMode.EXCLUDE) throw new RecordNoAvailableConstructorsExceptions((Class) targetClass, "All available constructors have been " - + "annotated with @RecordConstruct(constructMode = RecordConstructMode.EXCLUDE). To enable mapping to the target record, please make at " - + "least one constructor available."); + + "annotated with @RecordConstruct(constructMode = RecordConstructMode.EXCLUDE). To enable mapping to the target record, please make at " + + "least one constructor available."); } return canonicalConstructor; } diff --git a/src/main/java/io/beanmapper/utils/BeanMapperLogger.java b/src/main/java/io/beanmapper/utils/BeanMapperLogger.java new file mode 100644 index 00000000..21c156d1 --- /dev/null +++ b/src/main/java/io/beanmapper/utils/BeanMapperLogger.java @@ -0,0 +1,68 @@ +package io.beanmapper.utils; + +import java.util.function.Supplier; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BeanMapperLogger { + + private static final Logger log = LoggerFactory.getLogger(BeanMapperLogger.class); + + private static final String LOG_TEMPLATE = "{} Performed operation in {}ms."; + + public static void log(String message) { + log.debug(message); + } + + public static void log(String message, Object... args) { + log.debug(message, args); + } + + public static void warn(String message) { + log.warn(message); + } + + public static void warn(String message, Object... args) { + log.warn(message, args); + } + + public static void error(String message) { + log.error(message); + } + + public static void error(String message, Object... args) { + log.error(message, args); + } + + public static void logTimed(String message, Runnable runnable) { + Stopwatch stopwatch = Stopwatch.create(); + runnable.run(); + log.debug(LOG_TEMPLATE, message, stopwatch.stop()); + } + + public static T logTimed(String message, Supplier supplier) { + Stopwatch stopwatch = Stopwatch.create(); + T result = supplier.get(); + log.debug(LOG_TEMPLATE, message, stopwatch.stop()); + return result; + } + + private static class Stopwatch { + + private final long started; + + Stopwatch() { + this.started = System.nanoTime(); + } + + public static Stopwatch create() { + return new Stopwatch(); + } + + public double stop() { + return (System.nanoTime() - this.started) / 1_000_000.0; + } + } + +} diff --git a/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java b/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java index c50bc217..70a2f406 100644 --- a/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java +++ b/src/test/java/io/beanmapper/config/BeanMapperBuilderTest.java @@ -19,6 +19,7 @@ import io.beanmapper.strategy.ConstructorArguments; import io.beanmapper.utils.Trinary; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; class BeanMapperBuilderTest { @@ -137,6 +138,7 @@ public T instantiate(Class beanClass, ConstructorArguments arguments) { } @Test + @Disabled("BeanUnproxy should not be used as a Converter.") void setBeanUnproxy() { final BeanUnproxy expectedBeanUnproxy = new BeanUnproxy() { @Override From 5458d0326704286451e3e4bc31f5bcd484e2ac49 Mon Sep 17 00:00:00 2001 From: Marcus Talbot Date: Thu, 15 Feb 2024 15:13:48 +0100 Subject: [PATCH 2/4] Separate Performance logging from Trace logging - Separated BeanMapperLogger into BeanMapperPerformanceLogger and BeanMapperTraceLogger. - Updated names of methods in Loggers, to better reflect their purpose. - Removed logging from Exception constructors. --- .../io/beanmapper/config/OverrideField.java | 4 +- .../config/StrictMappingProperties.java | 4 +- .../java/io/beanmapper/core/BeanMatch.java | 6 +++ .../io/beanmapper/core/BeanMatchStore.java | 4 +- .../beanmapper/core/BeanPropertyCreator.java | 6 +++ .../io/beanmapper/core/BeanPropertyMatch.java | 11 ++++-- ...eanStrictMappingRequirementsException.java | 10 +++-- .../AbstractCollectionHandler.java | 4 +- .../constructor/DefaultBeanInitializer.java | 11 ++++-- .../collections/CollectionConverter.java | 4 +- .../impl/ObjectToOptionalConverter.java | 6 +++ .../impl/OptionalToObjectConverter.java | 4 +- .../core/unproxy/SkippingBeanUnproxy.java | 4 +- .../BeanNoLogicSecuredCheckSetException.java | 3 -- .../BeanNoRoleSecuredCheckSetException.java | 3 -- .../BeanNoSuchPropertyException.java | 4 -- .../strategy/AbstractMapStrategy.java | 12 +++--- .../strategy/MapToClassStrategy.java | 4 +- .../strategy/MapToDynamicClassStrategy.java | 8 ++-- .../strategy/MapToRecordStrategy.java | 4 +- ....java => BeanMapperPerformanceLogger.java} | 37 +++---------------- .../utils/BeanMapperTraceLogger.java | 17 +++++++++ .../java/io/beanmapper/utils/Classes.java | 6 +++ 23 files changed, 98 insertions(+), 78 deletions(-) rename src/main/java/io/beanmapper/utils/{BeanMapperLogger.java => BeanMapperPerformanceLogger.java} (52%) create mode 100644 src/main/java/io/beanmapper/utils/BeanMapperTraceLogger.java diff --git a/src/main/java/io/beanmapper/config/OverrideField.java b/src/main/java/io/beanmapper/config/OverrideField.java index 274bee9e..745f03d8 100644 --- a/src/main/java/io/beanmapper/config/OverrideField.java +++ b/src/main/java/io/beanmapper/config/OverrideField.java @@ -2,7 +2,7 @@ import java.util.function.Supplier; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperPerformanceLogger; public class OverrideField { @@ -34,7 +34,7 @@ public T get() { return null; } if (this.value == null) { - this.value = BeanMapperLogger.logTimed("Retrieving nested configuration field.", this.supplier); + this.value = BeanMapperPerformanceLogger.runTimedTask("Retrieving nested configuration field.", this.supplier); } return value; } diff --git a/src/main/java/io/beanmapper/config/StrictMappingProperties.java b/src/main/java/io/beanmapper/config/StrictMappingProperties.java index 2550ed22..ec2368f4 100644 --- a/src/main/java/io/beanmapper/config/StrictMappingProperties.java +++ b/src/main/java/io/beanmapper/config/StrictMappingProperties.java @@ -2,7 +2,7 @@ import io.beanmapper.core.unproxy.BeanUnproxy; import io.beanmapper.core.unproxy.SkippingBeanUnproxy; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperPerformanceLogger; public class StrictMappingProperties { @@ -80,7 +80,7 @@ public void setApplyStrictMappingConvention(boolean applyStrictMappingConvention } public BeanPair createBeanPair(Class sourceClass, Class targetClass) { - BeanPair beanPair = BeanMapperLogger.logTimed("Creating BeanPair, and unproxying source %s-class and target %s-class.".formatted(sourceClass.getCanonicalName(), targetClass.getCanonicalName()), () -> { + BeanPair beanPair = BeanMapperPerformanceLogger.runTimedTask("Creating BeanPair, and unproxying source %s-class and target %s-class.".formatted(sourceClass.getCanonicalName(), targetClass.getCanonicalName()), () -> { Class unproxiedSource = beanUnproxy.unproxy(sourceClass); Class unproxiedTarget = beanUnproxy.unproxy(targetClass); return new BeanPair(unproxiedSource, unproxiedTarget); diff --git a/src/main/java/io/beanmapper/core/BeanMatch.java b/src/main/java/io/beanmapper/core/BeanMatch.java index c111dfe9..f3c969a3 100644 --- a/src/main/java/io/beanmapper/core/BeanMatch.java +++ b/src/main/java/io/beanmapper/core/BeanMatch.java @@ -8,8 +8,13 @@ import io.beanmapper.config.BeanPair; import io.beanmapper.exceptions.BeanNoSuchPropertyException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class BeanMatch { + private static final Logger log = LoggerFactory.getLogger(BeanMatch.class); + private final BeanPair beanPair; private final Map sourceNodes; @@ -106,6 +111,7 @@ private void checkForMandatoryUnmatchedNodes(String side, Class containingCla for (Map.Entry entry : nodes.entrySet()) { BeanProperty currentField = entry.getValue(); if (currentField.isUnmatched()) { + log.error("{} {} has no match for property {}", side, containingClass.isAnonymousClass(), entry.getKey()); throw new BeanNoSuchPropertyException(side + " " + containingClass.getCanonicalName() + " has no match for property " + entry.getKey()); } } diff --git a/src/main/java/io/beanmapper/core/BeanMatchStore.java b/src/main/java/io/beanmapper/core/BeanMatchStore.java index e25642cf..f13fc854 100644 --- a/src/main/java/io/beanmapper/core/BeanMatchStore.java +++ b/src/main/java/io/beanmapper/core/BeanMatchStore.java @@ -34,7 +34,7 @@ import io.beanmapper.exceptions.BeanMissingPathException; import io.beanmapper.exceptions.BeanNoSuchPropertyException; import io.beanmapper.exceptions.FieldShadowingException; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperTraceLogger; import io.beanmapper.utils.Trinary; public class BeanMatchStore { @@ -284,7 +284,7 @@ private BeanPropertyWrapper dealWithBeanProperty(BeanPropertyMatchupDirection ma .determineNodesForPath()); } catch (BeanNoSuchPropertyException err) { - BeanMapperLogger.log(""" + BeanMapperTraceLogger.log(""" BeanNoSuchPropertyException thrown by BeanMatchStore#dealWithBeanProperty(BeanPropertyMatchupDirection, Map, Class, PropertyAccessor), for {}. {}""", wrapper.getName(), err.getMessage()); diff --git a/src/main/java/io/beanmapper/core/BeanPropertyCreator.java b/src/main/java/io/beanmapper/core/BeanPropertyCreator.java index 560120d4..324c8347 100644 --- a/src/main/java/io/beanmapper/core/BeanPropertyCreator.java +++ b/src/main/java/io/beanmapper/core/BeanPropertyCreator.java @@ -6,8 +6,13 @@ import io.beanmapper.core.inspector.PropertyAccessors; import io.beanmapper.exceptions.BeanNoSuchPropertyException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class BeanPropertyCreator { + private static final Logger log = LoggerFactory.getLogger(BeanPropertyCreator.class); + private final BeanPropertyMatchupDirection matchupDirection; private final Class baseClass; @@ -68,6 +73,7 @@ private void traversePath(Stack beanProperties) { for (String node : route.getRoute()) { final PropertyAccessor property = PropertyAccessors.findProperty(currentBaseClass, node); if (property == null) { + log.error("Property '{}' does not exist in: {}", node, currentBaseClass.getSimpleName()); throw new BeanNoSuchPropertyException("Property '" + node + "' does not exist in: " + currentBaseClass.getSimpleName()); } beanProperties.push(new BeanProperty( diff --git a/src/main/java/io/beanmapper/core/BeanPropertyMatch.java b/src/main/java/io/beanmapper/core/BeanPropertyMatch.java index 39089edd..ea5ac420 100644 --- a/src/main/java/io/beanmapper/core/BeanPropertyMatch.java +++ b/src/main/java/io/beanmapper/core/BeanPropertyMatch.java @@ -10,10 +10,15 @@ import io.beanmapper.exceptions.BeanMappingException; import io.beanmapper.exceptions.BeanNoLogicSecuredCheckSetException; import io.beanmapper.exceptions.BeanNoRoleSecuredCheckSetException; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperTraceLogger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class BeanPropertyMatch { + private static final Logger log = LoggerFactory.getLogger(BeanPropertyMatch.class); + private final BeanMatch beanMatch; private final Object source; private final Object target; @@ -77,7 +82,7 @@ private boolean checkForLogicSecured( if (enforcedSecuredProperties) { throw new BeanNoLogicSecuredCheckSetException(message); } - BeanMapperLogger.warn(message); + BeanMapperTraceLogger.log(message); return true; } return logicSecuredCheck.isAllowed(source, target); @@ -92,7 +97,7 @@ private void checkIfSecuredFieldHandlerNotSet(BeanProperty beanProperty, boolean if (enforcedSecuredProperties) { throw new BeanNoRoleSecuredCheckSetException(message); } - BeanMapperLogger.warn(message); + log.warn(message); } } diff --git a/src/main/java/io/beanmapper/core/BeanStrictMappingRequirementsException.java b/src/main/java/io/beanmapper/core/BeanStrictMappingRequirementsException.java index eacc8d52..77319a25 100644 --- a/src/main/java/io/beanmapper/core/BeanStrictMappingRequirementsException.java +++ b/src/main/java/io/beanmapper/core/BeanStrictMappingRequirementsException.java @@ -3,10 +3,14 @@ import java.util.Collections; import java.util.List; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperTraceLogger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class BeanStrictMappingRequirementsException extends RuntimeException { + private static final Logger log = LoggerFactory.getLogger(BeanStrictMappingRequirementsException.class); private final List validationMessages; public BeanStrictMappingRequirementsException(BeanMatchValidationMessage validationMessage) { @@ -23,7 +27,7 @@ private void logErrors(List validationMessages) { if (validationMessage.isLogged()) { continue; } - BeanMapperLogger.error(""" + log.error(""" Missing matching properties for source [{}] {} > target [{}] {} for fields: """, validationMessage.getSourceClass().getCanonicalName(), @@ -32,7 +36,7 @@ private void logErrors(List validationMessages) { (validationMessage.isTargetStrict() ? "*" : "")); for (BeanProperty field : validationMessage.getFields()) { - BeanMapperLogger.error(""" + log.error(""" > {}.{} """, validationMessage.getStrictClass().getSimpleName(), diff --git a/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java b/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java index 7fd0f713..e6796577 100644 --- a/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java +++ b/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java @@ -5,7 +5,7 @@ import io.beanmapper.config.CollectionFlusher; import io.beanmapper.core.constructor.DefaultBeanInitializer; import io.beanmapper.exceptions.BeanCollectionUnassignableTargetCollectionTypeException; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperPerformanceLogger; import io.beanmapper.utils.Classes; public abstract class AbstractCollectionHandler implements CollectionHandler { @@ -33,7 +33,7 @@ public Object mapItem( BeanMapper beanMapper, Class collectionElementClass, Object source) { - return BeanMapperLogger.logTimed("Recursively calling BeanMapper#map(Object), to map collection elements of type %s, to %s." + return BeanMapperPerformanceLogger.runTimedTask("Recursively calling BeanMapper#map(Object), to map collection elements of type %s, to %s." .formatted(source != null ? source.getClass().getCanonicalName() : "null", collectionElementClass.getCanonicalName()), diff --git a/src/main/java/io/beanmapper/core/constructor/DefaultBeanInitializer.java b/src/main/java/io/beanmapper/core/constructor/DefaultBeanInitializer.java index 57d317ba..db608e0c 100644 --- a/src/main/java/io/beanmapper/core/constructor/DefaultBeanInitializer.java +++ b/src/main/java/io/beanmapper/core/constructor/DefaultBeanInitializer.java @@ -12,17 +12,22 @@ import io.beanmapper.BeanMapper; import io.beanmapper.config.BeanMapperBuilder; import io.beanmapper.strategy.ConstructorArguments; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperTraceLogger; import io.beanmapper.utils.DefaultValues; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class DefaultBeanInitializer implements BeanInitializer { + private static final Logger log = LoggerFactory.getLogger(DefaultBeanInitializer.class); + /** * {@inheritDoc} */ @Override public T instantiate(Class beanClass, ConstructorArguments arguments) { - BeanMapperLogger.log("Creating a new instance of type %s, using reflection.".formatted(beanClass)); + BeanMapperTraceLogger.log("Creating a new instance of type %s, using reflection.".formatted(beanClass)); try { if (arguments == null) { return beanClass.getConstructor().newInstance(); @@ -31,7 +36,7 @@ public T instantiate(Class beanClass, ConstructorArguments arguments) { var constructorParameterTypes = Arrays.stream(constructor.getParameters()).map(Parameter::getParameterizedType).toArray(Type[]::new); return beanClass.getConstructor(arguments.getTypes()).newInstance(mapParameterizedArguments(constructorParameterTypes, arguments.getValues())); } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { - BeanMapperLogger.error("Could not instantiate bean of class %s. Returning the default value associated with the given type. %s".formatted(beanClass.getName(), + log.error("Could not instantiate bean of class %s. Returning the default value associated with the given type. %s".formatted(beanClass.getName(), e.getMessage())); return DefaultValues.defaultValueFor(beanClass); } diff --git a/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java b/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java index 8e1f2842..ad4e45da 100644 --- a/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java +++ b/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java @@ -4,7 +4,7 @@ import io.beanmapper.core.BeanPropertyMatch; import io.beanmapper.core.collections.CollectionHandler; import io.beanmapper.core.converter.BeanConverter; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperPerformanceLogger; public class CollectionConverter implements BeanConverter { @@ -25,7 +25,7 @@ public U convert( return targetClass.cast(source); } - return BeanMapperLogger.logTimed("Calling BeanMapper#map(Object) recursively, to convert object of type %s, to type %s." + return BeanMapperPerformanceLogger.runTimedTask("Calling BeanMapper#map(Object) recursively, to convert object of type %s, to type %s." .formatted(source != null ? source.getClass().getCanonicalName() : "null", targetClass.getCanonicalName()), diff --git a/src/main/java/io/beanmapper/core/converter/impl/ObjectToOptionalConverter.java b/src/main/java/io/beanmapper/core/converter/impl/ObjectToOptionalConverter.java index 77f9eaa7..cf72c21c 100644 --- a/src/main/java/io/beanmapper/core/converter/impl/ObjectToOptionalConverter.java +++ b/src/main/java/io/beanmapper/core/converter/impl/ObjectToOptionalConverter.java @@ -10,6 +10,9 @@ import io.beanmapper.core.converter.BeanConverter; import io.beanmapper.exceptions.BeanNoSuchPropertyException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * This converter facilitates the conversion of an object to an Optional wrapping another object. This converter does * not support the conversion of complex datastructures, such as Collections, to Optionals. If that functionality is @@ -18,6 +21,8 @@ */ public class ObjectToOptionalConverter implements BeanConverter { + private static final Logger log = LoggerFactory.getLogger(ObjectToOptionalConverter.class); + @Override public T convert(BeanMapper beanMapper, S source, Class targetClass, BeanPropertyMatch beanPropertyMatch) { if (source == null) { @@ -28,6 +33,7 @@ public T convert(BeanMapper beanMapper, S source, Class targetClass, B try { targetField = beanPropertyMatch.getTarget().getClass().getDeclaredField(beanPropertyMatch.getTargetFieldName()); } catch (NoSuchFieldException e) { + log.error(e.getMessage()); throw new BeanNoSuchPropertyException(e.getMessage()); } diff --git a/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java b/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java index b555be1f..c6e616cb 100644 --- a/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java +++ b/src/main/java/io/beanmapper/core/converter/impl/OptionalToObjectConverter.java @@ -12,7 +12,7 @@ import io.beanmapper.BeanMapper; import io.beanmapper.core.BeanPropertyMatch; import io.beanmapper.core.converter.BeanConverter; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperTraceLogger; import io.beanmapper.utils.Classes; /** @@ -32,7 +32,7 @@ public T convert(BeanMapper beanMapper, S source, Class targetClass, B if (targetClass.equals(Optional.class)) { // Not always possible to get the actual source class, so just report the name of the field. Debug log will show the call stack. - BeanMapperLogger.log("Converting Optional to Optional. Perhaps the target does not need to be an Optional?\nSource-field: {}\nTarget: {}.{}", + BeanMapperTraceLogger.log("Converting Optional to Optional. Perhaps the target does not need to be an Optional?\nSource-field: {}\nTarget: {}.{}", beanPropertyMatch.getSourceFieldName(), beanPropertyMatch.getTarget().getClass(), beanPropertyMatch.getTargetFieldName()); diff --git a/src/main/java/io/beanmapper/core/unproxy/SkippingBeanUnproxy.java b/src/main/java/io/beanmapper/core/unproxy/SkippingBeanUnproxy.java index 2ed4edff..bddfa09e 100644 --- a/src/main/java/io/beanmapper/core/unproxy/SkippingBeanUnproxy.java +++ b/src/main/java/io/beanmapper/core/unproxy/SkippingBeanUnproxy.java @@ -6,7 +6,7 @@ import java.util.HashSet; import java.util.Set; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperTraceLogger; /** * Unproxy that allows you to configure classes to skip. @@ -33,7 +33,7 @@ public SkippingBeanUnproxy(BeanUnproxy delegate) { */ @Override public Class unproxy(Class beanClass) { - BeanMapperLogger.log("Unproxying class %s.".formatted(beanClass != null ? beanClass.getCanonicalName() : "null")); + BeanMapperTraceLogger.log("Unproxying class %s.".formatted(beanClass != null ? beanClass.getCanonicalName() : "null")); if (isSkippedProxyClass(beanClass)) { return beanClass; } diff --git a/src/main/java/io/beanmapper/exceptions/BeanNoLogicSecuredCheckSetException.java b/src/main/java/io/beanmapper/exceptions/BeanNoLogicSecuredCheckSetException.java index 08851ac8..e0407031 100644 --- a/src/main/java/io/beanmapper/exceptions/BeanNoLogicSecuredCheckSetException.java +++ b/src/main/java/io/beanmapper/exceptions/BeanNoLogicSecuredCheckSetException.java @@ -1,11 +1,8 @@ package io.beanmapper.exceptions; -import io.beanmapper.utils.BeanMapperLogger; - public class BeanNoLogicSecuredCheckSetException extends IllegalArgumentException { public BeanNoLogicSecuredCheckSetException(String message) { super(message); - BeanMapperLogger.error(message); } } diff --git a/src/main/java/io/beanmapper/exceptions/BeanNoRoleSecuredCheckSetException.java b/src/main/java/io/beanmapper/exceptions/BeanNoRoleSecuredCheckSetException.java index a39b31b7..e8041c30 100644 --- a/src/main/java/io/beanmapper/exceptions/BeanNoRoleSecuredCheckSetException.java +++ b/src/main/java/io/beanmapper/exceptions/BeanNoRoleSecuredCheckSetException.java @@ -1,11 +1,8 @@ package io.beanmapper.exceptions; -import io.beanmapper.utils.BeanMapperLogger; - public class BeanNoRoleSecuredCheckSetException extends IllegalArgumentException { public BeanNoRoleSecuredCheckSetException(String message) { super(message); - BeanMapperLogger.error(message); } } diff --git a/src/main/java/io/beanmapper/exceptions/BeanNoSuchPropertyException.java b/src/main/java/io/beanmapper/exceptions/BeanNoSuchPropertyException.java index a74776f9..0caee4d7 100644 --- a/src/main/java/io/beanmapper/exceptions/BeanNoSuchPropertyException.java +++ b/src/main/java/io/beanmapper/exceptions/BeanNoSuchPropertyException.java @@ -3,8 +3,6 @@ */ package io.beanmapper.exceptions; -import io.beanmapper.utils.BeanMapperLogger; - /** * Exception thrown when a property could not be found. */ @@ -12,7 +10,5 @@ public class BeanNoSuchPropertyException extends IllegalArgumentException { public BeanNoSuchPropertyException(String message) { super(message); - BeanMapperLogger.error(message); } - } diff --git a/src/main/java/io/beanmapper/strategy/AbstractMapStrategy.java b/src/main/java/io/beanmapper/strategy/AbstractMapStrategy.java index c005d519..8b672feb 100644 --- a/src/main/java/io/beanmapper/strategy/AbstractMapStrategy.java +++ b/src/main/java/io/beanmapper/strategy/AbstractMapStrategy.java @@ -12,7 +12,7 @@ import io.beanmapper.core.converter.BeanConverter; import io.beanmapper.exceptions.BeanConversionException; import io.beanmapper.exceptions.BeanPropertyNoMatchException; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperTraceLogger; import io.beanmapper.utils.Records; public abstract class AbstractMapStrategy implements MapStrategy { @@ -107,7 +107,7 @@ private void dealWithMappableNestedClass(BeanPropertyMatch beanPropertyMatch) { Object encapsulatedSource = beanPropertyMatch.getSourceObject(); Object target; if (encapsulatedSource != null) { - BeanMapperLogger.log(" {"); + BeanMapperTraceLogger.log(" {"); BeanMapper localBeanMapper = getBeanMapper() .wrap() .setParent(beanPropertyMatch.getTarget()) @@ -118,7 +118,7 @@ private void dealWithMappableNestedClass(BeanPropertyMatch beanPropertyMatch) { target = localBeanMapper.map(encapsulatedSource, beanPropertyMatch.getTargetObject()); } beanPropertyMatch.writeObject(target); - BeanMapperLogger.log(" }"); + BeanMapperTraceLogger.log(" }"); } } @@ -135,7 +135,7 @@ public Object convert(Object value, Class targetClass, BeanPropertyMatch bean BeanConverter converter = getConverterOptional(valueClass, targetClass); if (converter != null) { - BeanMapperLogger.log("{}{}{}", INDENT, converter.getClass().getSimpleName(), ARROW); + BeanMapperTraceLogger.log("{}{}{}", INDENT, converter.getClass().getSimpleName(), ARROW); BeanMapper wrappedBeanMapper = beanMapper .wrap() .setParent(beanPropertyMatch.getTarget()) @@ -207,9 +207,9 @@ private void processProperty(BeanPropertyMatch beanPropertyMatch) { return; } if (beanPropertyMatch.isMappable()) { - BeanMapperLogger.log("{}{}", beanPropertyMatch.sourceToString(), ARROW); + BeanMapperTraceLogger.log("{}{}", beanPropertyMatch.sourceToString(), ARROW); copySourceToTarget(beanPropertyMatch); - BeanMapperLogger.log("{}{}", INDENT, beanPropertyMatch.targetToString()); + BeanMapperTraceLogger.log("{}{}", INDENT, beanPropertyMatch.targetToString()); } } diff --git a/src/main/java/io/beanmapper/strategy/MapToClassStrategy.java b/src/main/java/io/beanmapper/strategy/MapToClassStrategy.java index 942b2fea..06f45bd4 100644 --- a/src/main/java/io/beanmapper/strategy/MapToClassStrategy.java +++ b/src/main/java/io/beanmapper/strategy/MapToClassStrategy.java @@ -4,7 +4,7 @@ import io.beanmapper.config.Configuration; import io.beanmapper.core.BeanMatch; import io.beanmapper.core.converter.BeanConverter; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperTraceLogger; public class MapToClassStrategy extends MapToInstanceStrategy { @@ -20,7 +20,7 @@ public T map(S source) { Class valueClass = getConfiguration().getBeanUnproxy().unproxy(source.getClass()); BeanConverter converter = getConverterOptional(valueClass, targetClass); if (converter != null) { - BeanMapperLogger.log("Converter called for source of class {}, while mapping to class {}\t{}->", source.getClass(), targetClass, + BeanMapperTraceLogger.log("Converter called for source of class {}, while mapping to class {}\t{}->", source.getClass(), targetClass, converter.getClass().getSimpleName()); return (T) converter.convert(getBeanMapper(), source, targetClass, null); } diff --git a/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java b/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java index c29f5166..db834cd9 100644 --- a/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java +++ b/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java @@ -5,7 +5,7 @@ import io.beanmapper.BeanMapper; import io.beanmapper.config.Configuration; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperPerformanceLogger; public class MapToDynamicClassStrategy extends AbstractMapStrategy { @@ -49,7 +49,7 @@ public T downsizeSource(S source, List downsizeSourceFields) { Class targetClass = getConfiguration().getTargetClass(); Object target = getConfiguration().getTarget(); - Object dynSource = BeanMapperLogger.logTimed("Recursively calling BeanMapper#map(Object), to map source of type %s, to target of type %s." + Object dynSource = BeanMapperPerformanceLogger.runTimedTask("Recursively calling BeanMapper#map(Object), to map source of type %s, to target of type %s." .formatted(source.getClass().getCanonicalName(), dynamicClass.getCanonicalName()), () -> getBeanMapper() .wrap() @@ -59,7 +59,7 @@ public T downsizeSource(S source, List downsizeSourceFields) { .build() .map(source)); - return BeanMapperLogger.logTimed("Recursively calling BeanMapper#map(Object), to map source of type %s, to type %s." + return BeanMapperPerformanceLogger.runTimedTask("Recursively calling BeanMapper#map(Object), to map source of type %s, to type %s." .formatted(dynSource.getClass().getCanonicalName(), targetClass != null ? targetClass.getCanonicalName() : "null"), () -> getBeanMapper() .wrap() @@ -76,7 +76,7 @@ public T downsizeTarget(S source, List downsizeTargetFields) { downsizeTargetFields, getConfiguration().getStrictMappingProperties()); Class collectionClass = getBeanMapper().getConfiguration().getCollectionClass(); - return BeanMapperLogger.logTimed("Recursively calling BeanMapper#map(Object), to map source of type %s, to type %s." + return BeanMapperPerformanceLogger.runTimedTask("Recursively calling BeanMapper#map(Object), to map source of type %s, to type %s." .formatted(source.getClass().getCanonicalName(), dynamicClass.getCanonicalName()), () -> getBeanMapper() .wrap() .downsizeTarget(null) diff --git a/src/main/java/io/beanmapper/strategy/MapToRecordStrategy.java b/src/main/java/io/beanmapper/strategy/MapToRecordStrategy.java index 983f91d1..ce357150 100644 --- a/src/main/java/io/beanmapper/strategy/MapToRecordStrategy.java +++ b/src/main/java/io/beanmapper/strategy/MapToRecordStrategy.java @@ -26,7 +26,7 @@ import io.beanmapper.exceptions.RecordConstructorConflictException; import io.beanmapper.exceptions.RecordNoAvailableConstructorsExceptions; import io.beanmapper.exceptions.SourceFieldAccessException; -import io.beanmapper.utils.BeanMapperLogger; +import io.beanmapper.utils.BeanMapperTraceLogger; import io.beanmapper.utils.Records; /** @@ -57,7 +57,7 @@ public T map(final S source) { if (getConfiguration().isConverterChoosable()) { BeanConverter converter = getConverterOptional(source.getClass(), this.getConfiguration().getTargetClass()); if (converter != null) { - BeanMapperLogger.log("Converter called for source of class {}, while mapping to class {}\t{}->", source.getClass(), targetClass, + BeanMapperTraceLogger.log("Converter called for source of class {}, while mapping to class {}\t{}->", source.getClass(), targetClass, converter.getClass().getSimpleName()); return converter.convert(getBeanMapper(), source, targetClass, null); } diff --git a/src/main/java/io/beanmapper/utils/BeanMapperLogger.java b/src/main/java/io/beanmapper/utils/BeanMapperPerformanceLogger.java similarity index 52% rename from src/main/java/io/beanmapper/utils/BeanMapperLogger.java rename to src/main/java/io/beanmapper/utils/BeanMapperPerformanceLogger.java index 21c156d1..139f25a7 100644 --- a/src/main/java/io/beanmapper/utils/BeanMapperLogger.java +++ b/src/main/java/io/beanmapper/utils/BeanMapperPerformanceLogger.java @@ -5,45 +5,20 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class BeanMapperLogger { - - private static final Logger log = LoggerFactory.getLogger(BeanMapperLogger.class); +public class BeanMapperPerformanceLogger { + private static final Logger log = LoggerFactory.getLogger(BeanMapperPerformanceLogger.class); private static final String LOG_TEMPLATE = "{} Performed operation in {}ms."; - public static void log(String message) { - log.debug(message); - } - - public static void log(String message, Object... args) { - log.debug(message, args); - } - - public static void warn(String message) { - log.warn(message); - } - - public static void warn(String message, Object... args) { - log.warn(message, args); - } - - public static void error(String message) { - log.error(message); - } - - public static void error(String message, Object... args) { - log.error(message, args); - } - - public static void logTimed(String message, Runnable runnable) { + public static void runTimedTask(String message, Runnable task) { Stopwatch stopwatch = Stopwatch.create(); - runnable.run(); + task.run(); log.debug(LOG_TEMPLATE, message, stopwatch.stop()); } - public static T logTimed(String message, Supplier supplier) { + public static T runTimedTask(String message, Supplier task) { Stopwatch stopwatch = Stopwatch.create(); - T result = supplier.get(); + T result = task.get(); log.debug(LOG_TEMPLATE, message, stopwatch.stop()); return result; } diff --git a/src/main/java/io/beanmapper/utils/BeanMapperTraceLogger.java b/src/main/java/io/beanmapper/utils/BeanMapperTraceLogger.java new file mode 100644 index 00000000..98f25754 --- /dev/null +++ b/src/main/java/io/beanmapper/utils/BeanMapperTraceLogger.java @@ -0,0 +1,17 @@ +package io.beanmapper.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BeanMapperTraceLogger { + + private static final Logger log = LoggerFactory.getLogger(BeanMapperTraceLogger.class); + + public static void log(String message) { + log.trace(message); + } + + public static void log(String message, Object... args) { + log.trace(message, args); + } +} diff --git a/src/main/java/io/beanmapper/utils/Classes.java b/src/main/java/io/beanmapper/utils/Classes.java index ff567927..3f96c98f 100644 --- a/src/main/java/io/beanmapper/utils/Classes.java +++ b/src/main/java/io/beanmapper/utils/Classes.java @@ -9,6 +9,9 @@ import io.beanmapper.core.BeanPropertyMatch; import io.beanmapper.exceptions.BeanNoSuchPropertyException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Reflection utilities. * @@ -17,6 +20,8 @@ */ public class Classes { + private static final Logger log = LoggerFactory.getLogger(Classes.class); + /** * Private constructor to hide implicit public constructor of utility-class. */ @@ -62,6 +67,7 @@ public static Type[] getParameteredTypes(Class clazz, BeanPropertyMatch beanP return ((ParameterizedType) clazz.getDeclaredField(beanPropertyMatch.getTargetFieldName()) .getGenericType()).getActualTypeArguments(); } catch (NoSuchFieldException e) { + log.error(e.getMessage()); throw new BeanNoSuchPropertyException(e.getMessage()); } } From 9692fc1452afa39d6ce59aacc3af363cbbbb3336 Mon Sep 17 00:00:00 2001 From: Marcus Talbot Date: Mon, 26 Feb 2024 08:59:23 +0100 Subject: [PATCH 3/4] Separate Performance logging from Trace logging - Separated BeanMapperLogger into BeanMapperPerformanceLogger and BeanMapperTraceLogger. - Updated names of methods in Loggers, to better reflect their purpose. - Removed logging from Exception constructors. --- .../io/beanmapper/config/OverrideField.java | 2 +- .../config/StrictMappingProperties.java | 2 +- .../AbstractCollectionHandler.java | 6 ++---- .../collections/CollectionConverter.java | 6 ++---- .../strategy/MapToDynamicClassStrategy.java | 6 +++--- .../utils/BeanMapperPerformanceLogger.java | 19 ++++++++++--------- 6 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/main/java/io/beanmapper/config/OverrideField.java b/src/main/java/io/beanmapper/config/OverrideField.java index 745f03d8..fde4bcaf 100644 --- a/src/main/java/io/beanmapper/config/OverrideField.java +++ b/src/main/java/io/beanmapper/config/OverrideField.java @@ -34,7 +34,7 @@ public T get() { return null; } if (this.value == null) { - this.value = BeanMapperPerformanceLogger.runTimedTask("Retrieving nested configuration field.", this.supplier); + this.value = BeanMapperPerformanceLogger.runTimed("%s#%s -> %s#%s".formatted(this.getClass().getSimpleName(), "get(void)", this.getClass().getSimpleName(), "get(void)"), this.supplier); } return value; } diff --git a/src/main/java/io/beanmapper/config/StrictMappingProperties.java b/src/main/java/io/beanmapper/config/StrictMappingProperties.java index ec2368f4..ea87a74e 100644 --- a/src/main/java/io/beanmapper/config/StrictMappingProperties.java +++ b/src/main/java/io/beanmapper/config/StrictMappingProperties.java @@ -80,7 +80,7 @@ public void setApplyStrictMappingConvention(boolean applyStrictMappingConvention } public BeanPair createBeanPair(Class sourceClass, Class targetClass) { - BeanPair beanPair = BeanMapperPerformanceLogger.runTimedTask("Creating BeanPair, and unproxying source %s-class and target %s-class.".formatted(sourceClass.getCanonicalName(), targetClass.getCanonicalName()), () -> { + BeanPair beanPair = BeanMapperPerformanceLogger.runTimed("%s#%s".formatted(this.getClass().getSimpleName(), "createBeanPair(Class, Class) -> BeanUnproxy#unproxy(Class)"), () -> { Class unproxiedSource = beanUnproxy.unproxy(sourceClass); Class unproxiedTarget = beanUnproxy.unproxy(targetClass); return new BeanPair(unproxiedSource, unproxiedTarget); diff --git a/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java b/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java index e6796577..e0bf205e 100644 --- a/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java +++ b/src/main/java/io/beanmapper/core/collections/AbstractCollectionHandler.java @@ -33,10 +33,8 @@ public Object mapItem( BeanMapper beanMapper, Class collectionElementClass, Object source) { - return BeanMapperPerformanceLogger.runTimedTask("Recursively calling BeanMapper#map(Object), to map collection elements of type %s, to %s." - .formatted(source != null - ? source.getClass().getCanonicalName() - : "null", collectionElementClass.getCanonicalName()), + return BeanMapperPerformanceLogger.runTimed("%s#%s" + .formatted(this.getClass().getSimpleName(), "mapItem(BeanMapper, Class, Object) -> BeanMapper#map(Object)"), () -> beanMapper.wrap() .setTargetClass(collectionElementClass) .setCollectionClass(null) diff --git a/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java b/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java index ad4e45da..a8609d54 100644 --- a/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java +++ b/src/main/java/io/beanmapper/core/converter/collections/CollectionConverter.java @@ -25,10 +25,8 @@ public U convert( return targetClass.cast(source); } - return BeanMapperPerformanceLogger.runTimedTask("Calling BeanMapper#map(Object) recursively, to convert object of type %s, to type %s." - .formatted(source != null - ? source.getClass().getCanonicalName() - : "null", targetClass.getCanonicalName()), + return BeanMapperPerformanceLogger.runTimed("%s#%s" + .formatted(this.getClass().getSimpleName(), "convert(BeanMapper, Object, Class, BeanPropertyMatch) -> BeanMapper#map(Object)"), () -> beanMapper.wrap() .setCollectionClass(collectionHandler.getType()) .setCollectionUsage(beanPropertyMatch.getCollectionInstructions().getBeanCollectionUsage()) diff --git a/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java b/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java index db834cd9..bf7f6ab3 100644 --- a/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java +++ b/src/main/java/io/beanmapper/strategy/MapToDynamicClassStrategy.java @@ -49,7 +49,7 @@ public T downsizeSource(S source, List downsizeSourceFields) { Class targetClass = getConfiguration().getTargetClass(); Object target = getConfiguration().getTarget(); - Object dynSource = BeanMapperPerformanceLogger.runTimedTask("Recursively calling BeanMapper#map(Object), to map source of type %s, to target of type %s." + Object dynSource = BeanMapperPerformanceLogger.runTimed("Recursively calling BeanMapper#map(Object), to map source of type %s, to target of type %s." .formatted(source.getClass().getCanonicalName(), dynamicClass.getCanonicalName()), () -> getBeanMapper() .wrap() @@ -59,7 +59,7 @@ public T downsizeSource(S source, List downsizeSourceFields) { .build() .map(source)); - return BeanMapperPerformanceLogger.runTimedTask("Recursively calling BeanMapper#map(Object), to map source of type %s, to type %s." + return BeanMapperPerformanceLogger.runTimed("Recursively calling BeanMapper#map(Object), to map source of type %s, to type %s." .formatted(dynSource.getClass().getCanonicalName(), targetClass != null ? targetClass.getCanonicalName() : "null"), () -> getBeanMapper() .wrap() @@ -76,7 +76,7 @@ public T downsizeTarget(S source, List downsizeTargetFields) { downsizeTargetFields, getConfiguration().getStrictMappingProperties()); Class collectionClass = getBeanMapper().getConfiguration().getCollectionClass(); - return BeanMapperPerformanceLogger.runTimedTask("Recursively calling BeanMapper#map(Object), to map source of type %s, to type %s." + return BeanMapperPerformanceLogger.runTimed("Recursively calling BeanMapper#map(Object), to map source of type %s, to type %s." .formatted(source.getClass().getCanonicalName(), dynamicClass.getCanonicalName()), () -> getBeanMapper() .wrap() .downsizeTarget(null) diff --git a/src/main/java/io/beanmapper/utils/BeanMapperPerformanceLogger.java b/src/main/java/io/beanmapper/utils/BeanMapperPerformanceLogger.java index 139f25a7..9f890229 100644 --- a/src/main/java/io/beanmapper/utils/BeanMapperPerformanceLogger.java +++ b/src/main/java/io/beanmapper/utils/BeanMapperPerformanceLogger.java @@ -1,5 +1,7 @@ package io.beanmapper.utils; +import java.time.Duration; +import java.time.Instant; import java.util.function.Supplier; import org.slf4j.Logger; @@ -8,27 +10,27 @@ public class BeanMapperPerformanceLogger { private static final Logger log = LoggerFactory.getLogger(BeanMapperPerformanceLogger.class); - private static final String LOG_TEMPLATE = "{} Performed operation in {}ms."; + private static final String LOG_TEMPLATE = "Performed operation in {}ms. ({})"; - public static void runTimedTask(String message, Runnable task) { + public static void runTimed(String taskName, Runnable task) { Stopwatch stopwatch = Stopwatch.create(); task.run(); - log.debug(LOG_TEMPLATE, message, stopwatch.stop()); + log.debug(LOG_TEMPLATE, stopwatch.stop(), taskName); } - public static T runTimedTask(String message, Supplier task) { + public static T runTimed(String taskName, Supplier task) { Stopwatch stopwatch = Stopwatch.create(); T result = task.get(); - log.debug(LOG_TEMPLATE, message, stopwatch.stop()); + log.debug(LOG_TEMPLATE, stopwatch.stop(), taskName); return result; } private static class Stopwatch { - private final long started; + private final Instant started; Stopwatch() { - this.started = System.nanoTime(); + this.started = Instant.now(); } public static Stopwatch create() { @@ -36,8 +38,7 @@ public static Stopwatch create() { } public double stop() { - return (System.nanoTime() - this.started) / 1_000_000.0; + return Duration.between(started, Instant.now()).toNanos() / 1_000_000.0; } } - } From 93310abd204e04f6115a90a449dbe531bdd1f3f6 Mon Sep 17 00:00:00 2001 From: Marcus Talbot Date: Mon, 26 Feb 2024 09:05:03 +0100 Subject: [PATCH 4/4] Fix NPE - Fixed NPE where canonical name can be null, due to constraints set by Class#getCanonicalName(void). --- src/main/java/io/beanmapper/core/BeanMatch.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/io/beanmapper/core/BeanMatch.java b/src/main/java/io/beanmapper/core/BeanMatch.java index f3c969a3..5437ed16 100644 --- a/src/main/java/io/beanmapper/core/BeanMatch.java +++ b/src/main/java/io/beanmapper/core/BeanMatch.java @@ -111,7 +111,7 @@ private void checkForMandatoryUnmatchedNodes(String side, Class containingCla for (Map.Entry entry : nodes.entrySet()) { BeanProperty currentField = entry.getValue(); if (currentField.isUnmatched()) { - log.error("{} {} has no match for property {}", side, containingClass.isAnonymousClass(), entry.getKey()); + log.error("{} {} has no match for property {}", side, containingClass.getCanonicalName() != null ? containingClass.getCanonicalName() : containingClass.getDeclaringClass().getCanonicalName(), entry.getKey()); throw new BeanNoSuchPropertyException(side + " " + containingClass.getCanonicalName() + " has no match for property " + entry.getKey()); } }