diff --git a/core/src/main/java/io/micronaut/core/beans/BeanIntrospection.java b/core/src/main/java/io/micronaut/core/beans/BeanIntrospection.java index ac2ef548d5b..416dbf38259 100644 --- a/core/src/main/java/io/micronaut/core/beans/BeanIntrospection.java +++ b/core/src/main/java/io/micronaut/core/beans/BeanIntrospection.java @@ -20,6 +20,7 @@ import io.micronaut.core.beans.exceptions.IntrospectionException; import io.micronaut.core.convert.ArgumentConversionContext; import io.micronaut.core.convert.ConversionService; +import io.micronaut.core.reflect.ReflectionUtils; import io.micronaut.core.reflect.exception.InstantiationException; import io.micronaut.core.type.Argument; import io.micronaut.core.util.ArgumentUtils; @@ -304,7 +305,7 @@ default

BeanWriteProperty getRequiredWriteProperty(@NonNull String nam ArgumentUtils.requireNonNull("type", type); final BeanProperty prop = getProperty(name).orElse(null); - if (prop != null && type.isAssignableFrom(prop.getType())) { + if (prop != null && type.isAssignableFrom(ReflectionUtils.getWrapperType(prop.getType()))) { //noinspection unchecked return Optional.of((BeanProperty) prop); } @@ -324,7 +325,7 @@ default

BeanWriteProperty getRequiredWriteProperty(@NonNull String nam ArgumentUtils.requireNonNull("type", type); final BeanReadProperty prop = getReadProperty(name).orElse(null); - if (prop != null && type.isAssignableFrom(prop.getType())) { + if (prop != null && type.isAssignableFrom(ReflectionUtils.getWrapperType(prop.getType()))) { //noinspection unchecked return Optional.of((BeanReadProperty) prop); } @@ -345,7 +346,7 @@ default

BeanWriteProperty getRequiredWriteProperty(@NonNull String nam ArgumentUtils.requireNonNull("type", type); final BeanWriteProperty prop = getWriteProperty(name).orElse(null); - if (prop != null && type.isAssignableFrom(prop.getType())) { + if (prop != null && type.isAssignableFrom(ReflectionUtils.getWrapperType(prop.getType()))) { //noinspection unchecked return Optional.of((BeanProperty) prop); } diff --git a/test-suite/src/test/groovy/io/micronaut/docs/ioc/mappers/PrimitiveMapperSpec.groovy b/test-suite/src/test/groovy/io/micronaut/docs/ioc/mappers/PrimitiveMapperSpec.groovy new file mode 100644 index 00000000000..14c554aa42d --- /dev/null +++ b/test-suite/src/test/groovy/io/micronaut/docs/ioc/mappers/PrimitiveMapperSpec.groovy @@ -0,0 +1,62 @@ +package io.micronaut.docs.ioc.mappers + +import io.micronaut.context.ApplicationContext +import io.micronaut.docs.ioc.mappers.PrimitiveTypes.PrimitiveMapper +import io.micronaut.docs.ioc.mappers.PrimitiveTypes.SourceWithPrimitive +import io.micronaut.docs.ioc.mappers.PrimitiveTypes.SourceWithWrapper +import io.micronaut.docs.ioc.mappers.PrimitiveTypes.TargetWithPrimitive +import io.micronaut.docs.ioc.mappers.PrimitiveTypes.TargetWithWrapper +import spock.lang.AutoCleanup +import spock.lang.Shared +import spock.lang.Specification + +class PrimitiveMapperSpec extends Specification { + + @Shared @AutoCleanup ApplicationContext context = ApplicationContext.run(["spec.name": "PrimitiveMapperSpec"]) + + void 'test primitive to wrapper mapping'() { + given: + PrimitiveMapper mapper = context.getBean(PrimitiveMapper.class) + + when: + SourceWithPrimitive source = new SourceWithPrimitive() + source.setId(42L) + source.setCount(100) + source.setActive(true) + source.setScore(95.5f) + source.setValue(3.14159) + + TargetWithWrapper target = mapper.convert(source) + + then: + target != null + target.getId() == Long.valueOf(42L) + target.getCount() == Integer.valueOf(100) + target.getActive() == Boolean.valueOf(true) + target.getScore() == Float.valueOf(95.5f) + target.getValue() == Double.valueOf(3.14159) + } + + void 'test wrapper to primitive mapping'() { + given: + PrimitiveMapper mapper = context.getBean(PrimitiveMapper.class) + + when: + SourceWithWrapper source = new SourceWithWrapper() + source.setId(Long.valueOf(123L)) + source.setCount(Integer.valueOf(200)) + source.setActive(Boolean.valueOf(false)) + source.setScore(Float.valueOf(88.5f)) + source.setValue(Double.valueOf(2.71828)) + + TargetWithPrimitive target = mapper.convertToPrimitive(source) + + then: + target != null + target.getId() == 123L + target.getCount() == 200 + target.getActive() == false + target.getScore() == 88.5f + target.getValue() == 2.71828 + } +} \ No newline at end of file diff --git a/test-suite/src/test/java/io/micronaut/docs/ioc/mappers/PrimitiveTypes.java b/test-suite/src/test/java/io/micronaut/docs/ioc/mappers/PrimitiveTypes.java new file mode 100644 index 00000000000..df5c860d4f9 --- /dev/null +++ b/test-suite/src/test/java/io/micronaut/docs/ioc/mappers/PrimitiveTypes.java @@ -0,0 +1,104 @@ +package io.micronaut.docs.ioc.mappers; + +import io.micronaut.context.annotation.Mapper; +import io.micronaut.core.annotation.Introspected; + +public interface PrimitiveTypes { + + @Introspected + public static class SourceWithPrimitive { + private long id; + private int count; + private boolean active; + private float score; + private double value; + + public long getId() { return id; } + public void setId(long id) { this.id = id; } + public int getCount() { return count; } + public void setCount(int count) { this.count = count; } + public boolean getActive() { return active; } + public void setActive(boolean active) { this.active = active; } + public float getScore() { return score; } + public void setScore(float score) { this.score = score; } + public double getValue() { return value; } + public void setValue(double value) { this.value = value; } + } + + @Introspected + public static class TargetWithWrapper { + private Long id; + private Integer count; + private Boolean active; + private Float score; + private Double value; + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public Integer getCount() { return count; } + public void setCount(Integer count) { this.count = count; } + public Boolean getActive() { return active; } + public void setActive(Boolean active) { this.active = active; } + public Float getScore() { return score; } + public void setScore(Float score) { this.score = score; } + public Double getValue() { return value; } + public void setValue(Double value) { this.value = value; } + } + + @Introspected + public static class SourceWithWrapper { + private Long id; + private Integer count; + private Boolean active; + private Float score; + private Double value; + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + public Integer getCount() { return count; } + public void setCount(Integer count) { this.count = count; } + public Boolean getActive() { return active; } + public void setActive(Boolean active) { this.active = active; } + public Float getScore() { return score; } + public void setScore(Float score) { this.score = score; } + public Double getValue() { return value; } + public void setValue(Double value) { this.value = value; } + } + + @Introspected + public static class TargetWithPrimitive { + private long id; + private int count; + private boolean active; + private float score; + private double value; + + public long getId() { return id; } + public void setId(long id) { this.id = id; } + public int getCount() { return count; } + public void setCount(int count) { this.count = count; } + public boolean getActive() { return active; } + public void setActive(boolean active) { this.active = active; } + public float getScore() { return score; } + public void setScore(float score) { this.score = score; } + public double getValue() { return value; } + public void setValue(double value) { this.value = value; } + } + + public interface PrimitiveMapper { + @Mapper.Mapping(from = "id", to = "id") + @Mapper.Mapping(from = "count", to = "count") + @Mapper.Mapping(from = "active", to = "active") + @Mapper.Mapping(from = "score", to = "score") + @Mapper.Mapping(from = "value", to = "value") + TargetWithWrapper convert(SourceWithPrimitive source); + + @Mapper.Mapping(from = "id", to = "id") + @Mapper.Mapping(from = "count", to = "count") + @Mapper.Mapping(from = "active", to = "active") + @Mapper.Mapping(from = "score", to = "score") + @Mapper.Mapping(from = "value", to = "value") + TargetWithPrimitive convertToPrimitive(SourceWithWrapper source); + } + +}