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);
+ }
+
+}