Skip to content

Commit

Permalink
Prepared for BeanMapper(-Spring) update (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcus-talbot42 authored Nov 9, 2022
1 parent fe48a25 commit f36407c
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 70 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Fixed
- BeanMapper v4.0.1 adds a new converter, as such, a few tests had to be updated to use the appropriate expected values.

## [4.0.0] - 2022-09-15
### Upgrades
- Upgraded beanmapper(4.0.1), beanmapper-spring(4.0.1).
### Fixed
- BeanMapper v4.0.1 adds a new converter, as such, a few tests had to be updated to use the appropriate expected values.

## [4.0.0] - 2022-09-15
### Upgrades
- Upgraded beanmapper(4.0.0), beanmapper-spring(4.0.0) and spring-boot(2.7.3) dependencies.
Expand Down
5 changes: 2 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,8 @@
<maven.compiler.target>17</maven.compiler.target>

<spring.boot.version>2.7.3</spring.boot.version>
<beanmapper.version>4.0.1</beanmapper.version>
<beanmapper.spring.version>4.0.1</beanmapper.spring.version>

<beanmapper.version>4.1.0</beanmapper.version>
<beanmapper.spring.version>4.1.0</beanmapper.spring.version>
<maven.release.plugin.version>2.5.3</maven.release.plugin.version>
<maven.scm.provider.gitexe.version>1.13.0</maven.scm.provider.gitexe.version>
</properties>
Expand Down
15 changes: 4 additions & 11 deletions src/main/java/io/beanmapper/autoconfigure/ApplicationScanner.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import static io.beanmapper.utils.Classes.forName;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.HashSet;
Expand All @@ -21,8 +20,6 @@
import org.springframework.boot.autoconfigure.domain.EntityScanner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

/**
Expand Down Expand Up @@ -89,14 +86,10 @@ private <T> Set<Class<? extends T>> findClasses(String basePackage, Class<T> loo
}

private TypeFilter createTypeFilterForClass(Class<?> clazz) {
return new TypeFilter() {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
String className = metadataReader.getClassMetadata().getClassName();
Class<?> currentClass = Classes.forName(className);
return clazz.isAssignableFrom(currentClass);
}
return (metadataReader, metadataReaderFactory) -> {
String className = metadataReader.getClassMetadata().getClassName();
Class<?> currentClass = Classes.forName(className);
return clazz.isAssignableFrom(currentClass);
};
}

}
49 changes: 27 additions & 22 deletions src/main/java/io/beanmapper/autoconfigure/BeanMapperAutoConfig.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package io.beanmapper.autoconfigure;

import static java.util.Collections.singletonList;
import static org.springframework.beans.BeanUtils.instantiate;
import static org.springframework.beans.BeanUtils.instantiateClass;

import java.util.List;

import javax.annotation.Nonnull;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;

Expand Down Expand Up @@ -35,18 +35,16 @@
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.ClassUtils;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
* In no BeanMapper bean is found, it will be created with sensible webapplication/spring-data-jpa mapping defaults.
* It's possible to customize the BeanMapperBuilder by adding a bean of type {@link BeanMapperBuilderCustomizer}
* It's possible to customize the BeanMapperBuilder by adding a bean of type {@link BeanMapperBuilderCustomizer}
* to your configuration.
* When a {@link MappingJackson2HttpMessageConverter} bean is found, a {@link MergedFormMethodArgumentResolver}
* When a {@link MappingJackson2HttpMessageConverter} bean is found, a {@link MergedFormMethodArgumentResolver}
* will be added to the Spring MVC context.
*/
@Configuration
Expand All @@ -55,16 +53,19 @@
public class BeanMapperAutoConfig {

private final Logger log = LoggerFactory.getLogger(BeanMapperAutoConfig.class);
@Autowired
private BeanMapperProperties props;
@Autowired
private ApplicationContext applicationContext;
@Autowired(required = false)
private BeanMapperBuilderCustomizer builderCustomizer;
private final BeanMapperProperties props;
private final ApplicationContext applicationContext;
private final BeanMapperBuilderCustomizer builderCustomizer;

private ApplicationScanner collectionHandlerAppScanner;
private ApplicationScanner beanConverterAppScanner;

public BeanMapperAutoConfig(final BeanMapperProperties props, final ApplicationContext applicationContext, @Autowired(required = false) final BeanMapperBuilderCustomizer builderCustomizer) {
this.props = props;
this.applicationContext = applicationContext;
this.builderCustomizer = builderCustomizer;
}

@PostConstruct
private void initApplicationScanner() {
collectionHandlerAppScanner = new ApplicationScanner(applicationContext);
Expand Down Expand Up @@ -162,7 +163,7 @@ private void addCustomBeanPairs(BeanMapperBuilder builder) {

private void addLogicSecuredChecks(BeanMapperBuilder builder, String basePackage) {
collectionHandlerAppScanner.findLogicSecuredCheckClasses(basePackage).forEach(cls -> {
LogicSecuredCheck logicSecuredCheck = instantiateClassAppContextOptional(cls, "logic secured check");
LogicSecuredCheck<?, ?> logicSecuredCheck = instantiateClassAppContextOptional(cls, "logic secured check");
if (logicSecuredCheck != null) {
builder.addLogicSecuredCheck(logicSecuredCheck);
}
Expand All @@ -171,7 +172,7 @@ private void addLogicSecuredChecks(BeanMapperBuilder builder, String basePackage

private void addCollectionHandlers(BeanMapperBuilder builder, String basePackage) {
collectionHandlerAppScanner.findCollectionHandlerClasses(basePackage).forEach(cls -> {
CollectionHandler collectionHandler = instantiateClassAppContextOptional(cls, "collection handler");
CollectionHandler<?> collectionHandler = instantiateClassAppContextOptional(cls, "collection handler");
if (collectionHandler != null) {
builder.addCollectionHandler(collectionHandler);
}
Expand Down Expand Up @@ -234,20 +235,24 @@ private void customize(BeanMapperBuilder builder) {
static class MergedFormConfig implements WebMvcConfigurer {

private final Logger log = LoggerFactory.getLogger(MergedFormConfig.class);
@Autowired(required = false)
private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;
@Autowired
private BeanMapper beanMapper;
@Autowired
private ApplicationContext applicationContext;
@Autowired(required = false)
private EntityManager entityManager;
private final MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;
private final BeanMapper beanMapper;
private final ApplicationContext applicationContext;
private final EntityManager entityManager;

public MergedFormConfig(@Autowired(required = false) final MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter,
final BeanMapper beanMapper, final ApplicationContext applicationContext, @Autowired(required = false) final EntityManager entityManager) {
this.mappingJackson2HttpMessageConverter = mappingJackson2HttpMessageConverter;
this.beanMapper = beanMapper;
this.applicationContext = applicationContext;
this.entityManager = entityManager;
}

/**
* If a {@link MappingJackson2HttpMessageConverter} bean is found, adds a {@link MergedFormMethodArgumentResolver} to the Spring MVC context.
*/
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
public void addArgumentResolvers(@Nonnull List<HandlerMethodArgumentResolver> argumentResolvers) {
if (mappingJackson2HttpMessageConverter != null) {
log.info("Adding MergedFormArgumentResolver to MVC application.");
argumentResolvers.add(new MergedFormMethodArgumentResolver(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ public class BeanMapperProperties {
*/
private boolean useHibernateUnproxy = true;

private Boolean applyStrictMappingConvention = true;
private boolean applyStrictMappingConvention = true;

private Boolean applySecuredProperties = true;
private boolean applySecuredProperties = true;

private String strictSourceSuffix = "Form";

Expand All @@ -45,19 +45,19 @@ public void setPackagePrefix(String basePackageName) {
this.packagePrefix = basePackageName;
}

public Boolean getApplyStrictMappingConvention() {
public boolean getApplyStrictMappingConvention() {
return applyStrictMappingConvention;
}

public void setApplyStrictMappingConvention(Boolean applyStrictMappingConvention) {
public void setApplyStrictMappingConvention(boolean applyStrictMappingConvention) {
this.applyStrictMappingConvention = applyStrictMappingConvention;
}

public Boolean getApplySecuredProperties() {
public boolean getApplySecuredProperties() {
return applySecuredProperties;
}

public void setApplySecuredProperties(Boolean applySecuredProperties) {
public void setApplySecuredProperties(boolean applySecuredProperties) {
this.applySecuredProperties = applySecuredProperties;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.beanmapper.autoconfigure;

import static java.util.stream.Collectors.toList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
Expand Down Expand Up @@ -53,43 +52,43 @@ public void tearDown() {
@Test
public void autoconfig_shouldCreateBeanMapper_ifNotExists() {
loadApplicationContext();
assertBeanMapper(1, 17);
assertBeanMapper(1, 20);
assertMergedFormArgResolver();
}

@Test
public void autoconfig_shouldCreateCustomizedBeanMapper_ifNotExists() {
loadApplicationContext(ConfigWithBeanMapperBuilderCustomizer.class);
assertBeanMapper(1, 18);
assertBeanMapper(1, 21);
assertMergedFormArgResolver();
}

@Test
public void autoconfig_shouldNotCreateBeanMapper_ifAlreadyExists() {
loadApplicationContext(ConfigWithBeanMapper.class);
assertBeanMapper(0, 12, false);
assertBeanMapper(0, 15, false);
assertMergedFormArgResolver();
}

@Test
public void autoconfig_shouldCreateBeanMapper_withDefaultUnproxy_whenEnvIsSet() {
loadApplicationContext(BEANMAPPER_USE_HIBERNATE_UNPROXY_PROP);
assertBeanMapper(1, 17, false);
assertBeanMapper(1, 20, false);
assertMergedFormArgResolver();
}

@Test
public void autoconfig_shouldRegisterCollectionHandler_ifScanned() {
loadApplicationContext(BEANMAPPER_USE_HIBERNATE_UNPROXY_PROP);
BeanMapper mapper = context.getBean(BeanMapper.class);
List<CollectionHandler> customCollectionHandlers = mapper.configuration().getCollectionHandlers()
List<CollectionHandler> customCollectionHandlers = mapper.getConfiguration().getCollectionHandlers()
.stream()
.filter(handler ->
handler.getType().equals(TestEntity.class) ||
handler.getType().equals(TestEntity2.class))
.collect(toList());
.toList();
assertEquals(2, customCollectionHandlers.size());
TestCollectionHandlerWithAppCtx collectionHandler = (TestCollectionHandlerWithAppCtx)mapper.configuration().getCollectionHandlerFor(TestEntity2.class);
TestCollectionHandlerWithAppCtx collectionHandler = (TestCollectionHandlerWithAppCtx)mapper.getConfiguration().getCollectionHandlerFor(TestEntity2.class);
assertNotNull(collectionHandler.getApplicationContext());
}

Expand All @@ -98,7 +97,7 @@ public void autoconfig_shouldSetSecurityChecks() {
loadApplicationContext(ConfigWithSecurity.class);
BeanMapper mapper = context.getBean(BeanMapper.class);

assertTrue(mapper.configuration().getRoleSecuredCheck() instanceof SpringRoleSecuredCheck);
assertTrue(mapper.getConfiguration().getRoleSecuredCheck() instanceof SpringRoleSecuredCheck);
}


Expand All @@ -108,28 +107,28 @@ public void autoconfig_shouldNotSetSecurityChecks_ifSpringSecurityIsMissingFromC
loadApplicationContext(ConfigWithSecurity.class, new NoSpringSecurityClassLoader());
BeanMapper mapper = context.getBean(BeanMapper.class);

assertFalse(mapper.configuration().getRoleSecuredCheck() instanceof SpringRoleSecuredCheck);
assertFalse(mapper.getConfiguration().getRoleSecuredCheck() instanceof SpringRoleSecuredCheck);
}

@Test
public void autoconfig_shouldLoadIdToEntityBeanConverterAndHibernateUnproxy_withSpringDataOnClassPath() {
loadApplicationContext(ConfigWithSpringData.class);
BeanMapper mapper = context.getBean(BeanMapper.class);
List<BeanConverter> beanConverters = mapper.configuration().getBeanConverters();
List<BeanConverter> beanConverters = mapper.getConfiguration().getBeanConverters();
assertTrue(beanConverters.stream().anyMatch(c -> c instanceof IdToEntityBeanConverter));

BeanUnproxy unproxyDelegate = (BeanUnproxy) getField(mapper.configuration().getBeanUnproxy(), "delegate");
BeanUnproxy unproxyDelegate = (BeanUnproxy) getField(mapper.getConfiguration().getBeanUnproxy(), "delegate");
assertTrue(unproxyDelegate instanceof HibernateAwareBeanUnproxy);
}

@Test
public void autoconfig_shouldNotLoadIdToEntityBeanConverterAndHibernateUnproxy_withoutSpringDataOnClassPath() {
loadApplicationContext(ConfigWithSpringData.class, new NoSpringDataClassLoader());
BeanMapper mapper = context.getBean(BeanMapper.class);
List<BeanConverter> beanConverters = mapper.configuration().getBeanConverters();
List<BeanConverter> beanConverters = mapper.getConfiguration().getBeanConverters();
assertFalse(beanConverters.stream().anyMatch(c -> c instanceof IdToEntityBeanConverter));

BeanUnproxy unproxyDelegate = (BeanUnproxy) getField(mapper.configuration().getBeanUnproxy(), "delegate");
BeanUnproxy unproxyDelegate = (BeanUnproxy) getField(mapper.getConfiguration().getBeanUnproxy(), "delegate");
assertFalse(unproxyDelegate instanceof HibernateAwareBeanUnproxy);
assertTrue(unproxyDelegate instanceof DefaultBeanUnproxy);
}
Expand Down Expand Up @@ -169,21 +168,19 @@ static class ConfigWithBeanMapperBuilderCustomizer {

@Bean
public BeanMapperBuilderCustomizer beanMapperCustomizer() {
return builder -> {
builder.addConverter(new BeanConverter() {
return builder -> builder.addConverter(new BeanConverter() {

@Override
public Object convert(BeanMapper beanMapper, Object source, Class<?> targetClass, BeanPropertyMatch beanFieldMatch) {
return null;
}
@Override
public <S, T> T convert(BeanMapper beanMapper, S source, Class<T> targetClass, BeanPropertyMatch beanFieldMatch) {
return null;
}

@Override
public boolean match(Class<?> sourceClass, Class<?> targetClass) {
return false;
}
@Override
public boolean match(Class<?> sourceClass, Class<?> targetClass) {
return false;
}

});
};
});
}

}
Expand All @@ -194,7 +191,7 @@ private void assertBeanMapper(int expectedNumberOfPackagePrefixes, int expectedN

private void assertBeanMapper(int expectedNumberOfPackagePrefixes, int expectedNumberOfConverters, boolean hibernateUnproxy) {
BeanMapper mapper = context.getBean(BeanMapper.class);
io.beanmapper.config.Configuration config = mapper.configuration();
io.beanmapper.config.Configuration config = mapper.getConfiguration();
assertEquals(expectedNumberOfPackagePrefixes, config.getPackagePrefixes().size());
if (expectedNumberOfPackagePrefixes == 1) {
assertEquals("io.beanmapper.autoconfigure", config.getPackagePrefixes().get(0));
Expand All @@ -213,7 +210,7 @@ private void assertMergedFormArgResolver() {
List<HandlerMethodArgumentResolver> argResolvers = requestHandler.getArgumentResolvers()
.stream()
.filter(argResolver -> MergedFormMethodArgumentResolver.class == argResolver.getClass())
.collect(toList());
.toList();
assertEquals(1, argResolvers.size());
}

Expand Down

0 comments on commit f36407c

Please sign in to comment.