Skip to content

Commit

Permalink
[#9631] Use MapStruct instead of ModelMapper
Browse files Browse the repository at this point in the history
  • Loading branch information
intr3p1d committed Sep 1, 2023
1 parent 869b660 commit fd26e1e
Show file tree
Hide file tree
Showing 19 changed files with 344 additions and 642 deletions.
28 changes: 26 additions & 2 deletions exceptiontrace/exceptiontrace-collector/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,32 @@
<artifactId>pinpoint-collector</artifactId>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
<!-- other annotation processors -->
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@
@Configuration
@Import({PinotConfiguration.class, ExceptionMetricKafkaConfiguration.class})
@ComponentScan({
"com.navercorp.pinpoint.exceptiontrace.collector.service",
"com.navercorp.pinpoint.exceptiontrace.collector.dao",
"com.navercorp.pinpoint.exceptiontrace.collector.mapper"
"com.navercorp.pinpoint.exceptiontrace.collector"
})
@PropertySource({ExceptionTraceCollectorConfig.KAFKA_TOPIC_PROPERTIES})
@ConditionalOnProperty(name = "pinpoint.modules.collector.exceptiontrace.enabled", havingValue = "true")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.navercorp.pinpoint.pinot.kafka.util.KafkaCallbacks;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mapstruct.factory.Mappers;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.core.KafkaTemplate;
Expand Down Expand Up @@ -67,7 +68,7 @@ public void insert(List<ExceptionMetaData> exceptionMetaData) {
logger.info("Pinot data insert: {}", exceptionMetaData);

Check warning on line 68 in exceptiontrace/exceptiontrace-collector/src/main/java/com/navercorp/pinpoint/exceptiontrace/collector/dao/PinotExceptionTraceDao.java

View check run for this annotation

Codecov / codecov/patch

exceptiontrace/exceptiontrace-collector/src/main/java/com/navercorp/pinpoint/exceptiontrace/collector/dao/PinotExceptionTraceDao.java#L67-L68

Added lines #L67 - L68 were not covered by tests

for (ExceptionMetaData e : exceptionMetaData) {
ExceptionMetaDataEntity dataEntity = modelToEntityMapper.toEntity(e);
ExceptionMetaDataEntity dataEntity = modelToEntityMapper.modelToExceptionMetaDataEntity(e);
ListenableFuture<SendResult<String, ExceptionMetaDataEntity>> response = this.kafkaExceptionMetaDataTemplate.send(

Check warning on line 72 in exceptiontrace/exceptiontrace-collector/src/main/java/com/navercorp/pinpoint/exceptiontrace/collector/dao/PinotExceptionTraceDao.java

View check run for this annotation

Codecov / codecov/patch

exceptiontrace/exceptiontrace-collector/src/main/java/com/navercorp/pinpoint/exceptiontrace/collector/dao/PinotExceptionTraceDao.java#L71-L72

Added lines #L71 - L72 were not covered by tests
topic, dataEntity
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* Copyright 2023 NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.navercorp.pinpoint.exceptiontrace.collector.mapper;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.navercorp.pinpoint.common.server.util.json.Jackson;
import com.navercorp.pinpoint.exceptiontrace.common.model.StackTraceElementWrapper;
import org.mapstruct.Qualifier;
import org.springframework.stereotype.Component;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author intr3p1d
*/
@Component
public class MapStructUtils {

private final ObjectMapper mapper = Jackson.newMapper();

public MapStructUtils() {
}

@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface StackTraceToClassNames {
}

@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface StackTraceToFileNames {
}

@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface StackTraceToLineNumbers {
}

@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface StackTraceToMethodNames {
}

@StackTraceToClassNames
public String stackTraceToClassNames(List<StackTraceElementWrapper> classNames) {
return objListToString(classNames, StackTraceElementWrapper::getClassName);
}

@StackTraceToFileNames
public String stackTraceToFileNames(List<StackTraceElementWrapper> fileNames) {
return objListToString(fileNames, StackTraceElementWrapper::getFileName);
}

@StackTraceToLineNumbers
public String stackTraceToLineNumber(List<StackTraceElementWrapper> lineNumbers) {
return objListToString(lineNumbers, StackTraceElementWrapper::getLineNumber);
}

@StackTraceToMethodNames
public String stackTraceToMethodNames(List<StackTraceElementWrapper> methodNames) {
return objListToString(methodNames, StackTraceElementWrapper::getMethodName);
}

public <T> String objListToString(List<T> objs, Function<T, ?> getter) {
try {
return mapper.writeValueAsString(objs.stream().map(getter).collect(Collectors.toList()));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);

Check warning on line 93 in exceptiontrace/exceptiontrace-collector/src/main/java/com/navercorp/pinpoint/exceptiontrace/collector/mapper/MapStructUtils.java

View check run for this annotation

Codecov / codecov/patch

exceptiontrace/exceptiontrace-collector/src/main/java/com/navercorp/pinpoint/exceptiontrace/collector/mapper/MapStructUtils.java#L92-L93

Added lines #L92 - L93 were not covered by tests
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,78 +15,28 @@
*/
package com.navercorp.pinpoint.exceptiontrace.collector.mapper;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.navercorp.pinpoint.common.server.util.json.Jackson;
import com.navercorp.pinpoint.exceptiontrace.common.entity.ExceptionMetaDataEntity;
import com.navercorp.pinpoint.exceptiontrace.common.model.ExceptionMetaData;
import com.navercorp.pinpoint.exceptiontrace.common.model.StackTraceElementWrapper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.modelmapper.Converter;
import org.modelmapper.ModelMapper;
import org.modelmapper.TypeMap;
import org.modelmapper.spi.DestinationSetter;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.springframework.beans.factory.annotation.Autowired;

/**
* @author intr3p1d
*/
@Component
public class ModelToEntityMapper {
private static final Logger logger = LogManager.getLogger(ModelToEntityMapper.class);
private static final ObjectMapper objectMapper = Jackson.newMapper();

private ModelMapper modelToEntity = newModelToEntityMapper();

public ModelToEntityMapper() {
}

public ExceptionMetaDataEntity toEntity(ExceptionMetaData model) {
return modelToEntity.map(model, ExceptionMetaDataEntity.class);
}

private ModelMapper newModelToEntityMapper() {
ModelMapper modelMapper = new ModelMapper();

TypeMap<ExceptionMetaData, ExceptionMetaDataEntity> typeMap = modelMapper.createTypeMap(
ExceptionMetaData.class, ExceptionMetaDataEntity.class
);

addMappings(typeMap, StackTraceElementWrapper::getClassName, ExceptionMetaDataEntity::setStackTraceClassName);
addMappings(typeMap, StackTraceElementWrapper::getFileName, ExceptionMetaDataEntity::setStackTraceFileName);
addMappings(typeMap, StackTraceElementWrapper::getLineNumber, ExceptionMetaDataEntity::setStackTraceLineNumber);
addMappings(typeMap, StackTraceElementWrapper::getMethodName, ExceptionMetaDataEntity::setStackTraceMethodName);
@Mapper(componentModel = "spring", uses = MapStructUtils.class)
public abstract class ModelToEntityMapper {

modelMapper.validate();
return modelMapper;
}
@Autowired
private MapStructUtils mapStructUtils;

private <T, V> void addMappings(
TypeMap<ExceptionMetaData, ExceptionMetaDataEntity> typeMap,
Function<StackTraceElementWrapper, T> wrapperGetter,
DestinationSetter<ExceptionMetaDataEntity, V> entitySetter
) {
typeMap.addMappings(
mapper -> mapper.using(
memberVariableFlattener(wrapperGetter)
).map(ExceptionMetaData::getStackTrace, entitySetter)
);
}
@Mappings({
@Mapping(source = "stackTrace", target = "stackTraceClassName", qualifiedBy = MapStructUtils.StackTraceToClassNames.class),
@Mapping(source = "stackTrace", target = "stackTraceFileName", qualifiedBy = MapStructUtils.StackTraceToFileNames.class),
@Mapping(source = "stackTrace", target = "stackTraceLineNumber", qualifiedBy = MapStructUtils.StackTraceToLineNumbers.class),
@Mapping(source = "stackTrace", target = "stackTraceMethodName", qualifiedBy = MapStructUtils.StackTraceToMethodNames.class)
})
public abstract ExceptionMetaDataEntity modelToExceptionMetaDataEntity(ExceptionMetaData model);

private <T> Converter<List<StackTraceElementWrapper>, String> memberVariableFlattener(
Function<StackTraceElementWrapper, T> getter
) {
return ctx -> {
try {
return objectMapper.writeValueAsString(ctx.getSource().stream().map(getter).collect(Collectors.toList()));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
};
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.navercorp.pinpoint.exceptiontrace.collector.mapper;


import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.navercorp.pinpoint.common.server.util.json.Jackson;
Expand All @@ -10,8 +11,12 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;
import org.mockito.InjectMocks;
import org.springframework.boot.json.JsonParseException;
import org.springframework.test.util.ReflectionTestUtils;

import java.io.IOException;
import java.util.Arrays;
Expand All @@ -27,16 +32,26 @@ class ModelToEntityMapperTest {

private static final Logger logger = LogManager.getLogger(ModelToEntityMapperTest.class);
private final Random random = new Random();
private static final ObjectMapper objectMapper = Jackson.newMapper();

ModelToEntityMapper modelToEntityMapper = new ModelToEntityMapper();
private final ObjectMapper objectMapper = Jackson.newMapper();

private final MapStructUtils mapStructUtils = new MapStructUtils();

@InjectMocks
ModelToEntityMapper modelToEntityMapper = Mappers.getMapper(ModelToEntityMapper.class);

@BeforeEach
public void init() {
ReflectionTestUtils.setField(modelToEntityMapper, "mapStructUtils", mapStructUtils);
}


@Test
public void testModelToEntity() {
Throwable throwable = new RuntimeException();

ExceptionMetaData expected = newRandomExceptionMetaData(throwable);
ExceptionMetaDataEntity actual = modelToEntityMapper.toEntity(expected);
ExceptionMetaDataEntity actual = modelToEntityMapper.modelToExceptionMetaDataEntity(expected);

Assertions.assertEquals(expected.getTimestamp(), actual.getTimestamp());
Assertions.assertEquals(expected.getTransactionId(), actual.getTransactionId());
Expand Down Expand Up @@ -107,7 +122,7 @@ private List<StackTraceElementWrapper> wrapperList(Throwable throwable) {
).collect(Collectors.toList());
}

private <T> List<T> convertToList(String s) {
private <T> List<T> convertToList(String s) {
if (StringUtils.isEmpty(s)) {
return Collections.emptyList();
}
Expand Down
5 changes: 5 additions & 0 deletions exceptiontrace/exceptiontrace-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,10 @@
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-commons-server</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
</dependencies>

</project>
12 changes: 6 additions & 6 deletions exceptiontrace/exceptiontrace-web/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-exceptiontrace-common</artifactId>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.5.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

Expand All @@ -50,7 +50,7 @@
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
<version>${mapstruct.version}</version>
</path>
<!-- other annotation processors -->
</annotationProcessorPaths>
Expand Down
Loading

0 comments on commit fd26e1e

Please sign in to comment.