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 extends Record>) 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());
}
}