Merge pull request #312 from aguibert/property-type-mismatch

 Apply adapters based on property read/write type
diff --git a/pom.xml b/pom.xml
index f0b2731..fbc29be 100644
--- a/pom.xml
+++ b/pom.xml
@@ -351,6 +351,7 @@
                                 <goal>test</goal>
                             </goals>
                             <configuration>
+                                <trimStackTrace>false</trimStackTrace>
                                 <excludes>
                                     <exclude>**/JavaxNamingExcludedTest.class</exclude>
                                     <exclude>**/AnnotationIntrospectorWithoutOptionalModulesTest.class</exclude>
diff --git a/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java b/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java
index 8041412..c22674e 100644
--- a/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java
+++ b/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java
@@ -172,20 +172,18 @@
      * @param customization customization with component info
      * @return components info if present
      */
-    public Optional<AdapterBinding> getAdapterBinding(Type propertyRuntimeType, ComponentBoundCustomization customization) {
-        if (customization == null || customization.getAdapterBinding() == null) {
+    public Optional<AdapterBinding> getSerializeAdapterBinding(Type propertyRuntimeType, ComponentBoundCustomization customization) {
+        if (customization == null || customization.getSerializeAdapterBinding() == null) {
             return searchComponentBinding(propertyRuntimeType, ComponentBindings::getAdapterInfo);
         }
-        return Optional.of(customization.getAdapterBinding());
+        return Optional.of(customization.getSerializeAdapterBinding());
     }
-
-    private <T extends AbstractComponentBinding> Optional<T> getComponentBinding(Type propertyRuntimeType, T componentBinding) {
-        //need runtime check, ParameterizedType property may have generic components assigned which is not compatible
-        //for given runtime type
-        if (matches(propertyRuntimeType, componentBinding.getBindingType())) {
-            return Optional.of(componentBinding);
+    
+    public Optional<AdapterBinding> getDeserializeAdapterBinding(Type propertyRuntimeType, ComponentBoundCustomization customization) {
+        if (customization == null || customization.getDeserializeAdapterBinding() == null) {
+            return searchComponentBinding(propertyRuntimeType, ComponentBindings::getAdapterInfo);
         }
-        return Optional.empty();
+        return Optional.of(customization.getDeserializeAdapterBinding());
     }
 
     private <T extends AbstractComponentBinding> Optional<T> searchComponentBinding(Type runtimeType, ComponentSupplier<T> supplier) {
diff --git a/src/main/java/org/eclipse/yasson/internal/Unmarshaller.java b/src/main/java/org/eclipse/yasson/internal/Unmarshaller.java
index b0c63ff..9d9f743 100644
--- a/src/main/java/org/eclipse/yasson/internal/Unmarshaller.java
+++ b/src/main/java/org/eclipse/yasson/internal/Unmarshaller.java
@@ -16,13 +16,11 @@
 import org.eclipse.yasson.internal.model.ClassModel;
 import org.eclipse.yasson.internal.properties.MessageKeys;
 import org.eclipse.yasson.internal.properties.Messages;
-import org.eclipse.yasson.internal.serializer.CurrentItem;
 import org.eclipse.yasson.internal.serializer.DefaultSerializers;
 import org.eclipse.yasson.internal.serializer.DeserializerBuilder;
 
 import javax.json.bind.JsonbException;
 import javax.json.bind.serializer.DeserializationContext;
-import javax.json.bind.serializer.JsonbDeserializer;
 import javax.json.stream.JsonParser;
 import java.lang.reflect.Type;
 import java.util.logging.Logger;
diff --git a/src/main/java/org/eclipse/yasson/internal/model/CreatorModel.java b/src/main/java/org/eclipse/yasson/internal/model/CreatorModel.java
index 11bf0df..26e2834 100644
--- a/src/main/java/org/eclipse/yasson/internal/model/CreatorModel.java
+++ b/src/main/java/org/eclipse/yasson/internal/model/CreatorModel.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -51,7 +51,7 @@
         JsonbNumberFormatter constructorNumberFormatter = context.getAnnotationIntrospector().getConstructorNumberFormatter(annotated);
         JsonbDateFormatter constructorDateFormatter = context.getAnnotationIntrospector().getConstructorDateFormatter(annotated);
         final JsonbAnnotatedElement<Class<?>> clsElement = annotationIntrospector.collectAnnotations(parameter.getType());
-        final CustomizationBuilder builder = new ClassCustomizationBuilder();
+        final ClassCustomizationBuilder builder = new ClassCustomizationBuilder();
         builder.setAdapterInfo(annotationIntrospector.getAdapterBinding(clsElement));
         builder.setDeserializerBinding(annotationIntrospector.getDeserializerBinding(clsElement));
         builder.setSerializerBinding(annotationIntrospector.getSerializerBinding(clsElement));
diff --git a/src/main/java/org/eclipse/yasson/internal/model/PropertyModel.java b/src/main/java/org/eclipse/yasson/internal/model/PropertyModel.java
index e00866c..9943e8e 100644
--- a/src/main/java/org/eclipse/yasson/internal/model/PropertyModel.java
+++ b/src/main/java/org/eclipse/yasson/internal/model/PropertyModel.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -113,8 +113,8 @@
         if (!ReflectionUtils.isResolvedType(serializationType)) {
             return null;
         }
-        if (customization.getAdapterBinding() != null) {
-            return new AdaptedObjectSerializer<>(classModel, customization.getAdapterBinding());
+        if (customization.getSerializeAdapterBinding() != null) {
+            return new AdaptedObjectSerializer<>(classModel, customization.getSerializeAdapterBinding());
         }
         if (customization.getSerializerBinding() != null) {
             return new UserSerializerSerializer<>(classModel, customization.getSerializerBinding().getJsonbSerializer());
@@ -147,14 +147,6 @@
         return getterMethodType == null ? propertyType : getterMethodType.getMethodType();
     }
 
-    private AdapterBinding getUserAdapterBinding(Property property, JsonbContext jsonbContext) {
-        final AdapterBinding adapterBinding = jsonbContext.getAnnotationIntrospector().getAdapterBinding(property);
-        if (adapterBinding != null) {
-            return adapterBinding;
-        }
-        return jsonbContext.getComponentMatcher().getAdapterBinding(propertyType, null).orElse(null);
-    }
-
     private SerializerBinding<?> getUserSerializerBinding(Property property, JsonbContext jsonbContext) {
         final SerializerBinding serializerBinding = jsonbContext.getAnnotationIntrospector().getSerializerBinding(property);
         if (serializerBinding != null) {
@@ -202,7 +194,14 @@
             builder.setDeserializerBinding(introspector.getDeserializerBinding(property));
         }
 
-        builder.setAdapterInfo(getUserAdapterBinding(property, jsonbContext));
+        final AdapterBinding adapterBinding = jsonbContext.getAnnotationIntrospector().getAdapterBinding(property);
+        if (adapterBinding != null) {
+            builder.setSerializeAdapter(adapterBinding);
+            builder.setDeserializeAdapter(adapterBinding);
+       } else {
+           builder.setSerializeAdapter(jsonbContext.getComponentMatcher().getSerializeAdapterBinding(getPropertySerializationType(), null).orElse(null));
+           builder.setDeserializeAdapter(jsonbContext.getComponentMatcher().getDeserializeAdapterBinding(getPropertyDeserializationType(), null).orElse(null));
+       }
 
         introspectDateFormatter(property, introspector, builder, jsonbContext);
         introspectNumberFormatter(property, introspector, builder);
@@ -327,15 +326,6 @@
     }
 
     /**
-     * Runtime type of a property. May be a TypeVariable or WildcardType.
-     *
-     * @return type of a property
-     */
-    public Type getPropertyType() {
-        return propertyType;
-    }
-
-    /**
      * Model of declaring class of this property.
      * @return class model
      */
diff --git a/src/main/java/org/eclipse/yasson/internal/model/customization/ComponentBoundCustomization.java b/src/main/java/org/eclipse/yasson/internal/model/customization/ComponentBoundCustomization.java
index 47a7e9d..3b107e8 100644
--- a/src/main/java/org/eclipse/yasson/internal/model/customization/ComponentBoundCustomization.java
+++ b/src/main/java/org/eclipse/yasson/internal/model/customization/ComponentBoundCustomization.java
@@ -1,3 +1,12 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ ******************************************************************************/
 package org.eclipse.yasson.internal.model.customization;
 
 import org.eclipse.yasson.internal.components.AdapterBinding;
@@ -10,11 +19,14 @@
 public interface ComponentBoundCustomization {
 
     /**
-     * Adapter wrapper class with resolved generic information.
-     *
-     * @return components wrapper
+     * @return Adapter wrapper class with resolved generic information.
      */
-    AdapterBinding getAdapterBinding();
+    AdapterBinding getSerializeAdapterBinding();
+    
+    /**
+     * @return Adapter wrapper class with resolved generic information.
+     */
+    AdapterBinding getDeserializeAdapterBinding();
 
     /**
      * Serializer wrapper with resolved generic info.
diff --git a/src/main/java/org/eclipse/yasson/internal/model/customization/CustomizationBase.java b/src/main/java/org/eclipse/yasson/internal/model/customization/CustomizationBase.java
index cad97b0..587e852 100644
--- a/src/main/java/org/eclipse/yasson/internal/model/customization/CustomizationBase.java
+++ b/src/main/java/org/eclipse/yasson/internal/model/customization/CustomizationBase.java
@@ -1,3 +1,12 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ ******************************************************************************/
 package org.eclipse.yasson.internal.model.customization;
 
 import org.eclipse.yasson.internal.components.AdapterBinding;
@@ -36,7 +45,7 @@
      */
     public CustomizationBase(CustomizationBase other) {
         this.nillable = other.isNillable();
-        this.adapterBinding = other.getAdapterBinding();
+        this.adapterBinding = other.getSerializeAdapterBinding();
         this.serializerBinding = other.getSerializerBinding();
         this.deserializerBinding = other.getDeserializerBinding();
     }
@@ -50,12 +59,12 @@
         return nillable;
     }
 
-    /**
-     * Adapter wrapper class with resolved generic information.
-     *
-     * @return components wrapper
-     */
-    public AdapterBinding getAdapterBinding() {
+    public AdapterBinding getSerializeAdapterBinding() {
+        return adapterBinding;
+    }
+    
+    @Override
+    public AdapterBinding getDeserializeAdapterBinding() {
         return adapterBinding;
     }
 
diff --git a/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomization.java b/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomization.java
index ce30100..8c05266 100644
--- a/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomization.java
+++ b/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomization.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -10,9 +10,9 @@
  * Contributors:
  * Roman Grigoriadi
  ******************************************************************************/
-
 package org.eclipse.yasson.internal.model.customization;
 
+import org.eclipse.yasson.internal.components.AdapterBinding;
 import org.eclipse.yasson.internal.serializer.JsonbDateFormatter;
 import org.eclipse.yasson.internal.serializer.JsonbNumberFormatter;
 
@@ -24,22 +24,21 @@
 public class PropertyCustomization extends CustomizationBase {
 
     private final String jsonReadName;
-
     private final String jsonWriteName;
 
     private final JsonbNumberFormatter serializeNumberFormatter;
-
     private final JsonbNumberFormatter deserializeNumberFormatter;
 
     private final JsonbDateFormatter serializeDateFormatter;
-
     private final JsonbDateFormatter deserializeDateFormatter;
+    
+    private final AdapterBinding serializeAdapter;
+    private final AdapterBinding deserializeAdapter;
 
     private boolean readTransient;
-
     private boolean writeTransient;
 
-    private final Class implementationClass;
+    private final Class<?> implementationClass;
 
     /**
      * Copies properties from builder an creates immutable instance.
@@ -48,6 +47,8 @@
      */
     public PropertyCustomization(PropertyCustomizationBuilder builder) {
         super(builder);
+        this.serializeAdapter = builder.getSerializeAdapter();
+        this.deserializeAdapter = builder.getDeserializeAdapter();
         this.jsonReadName = builder.getJsonReadName();
         this.jsonWriteName = builder.getJsonWriteName();
         this.serializeNumberFormatter = builder.getSerializeNumberFormatter();
@@ -121,8 +122,18 @@
      *
      * @return class implementing property interface
      */
-    public Class getImplementationClass() {
+    public Class<?> getImplementationClass() {
         return implementationClass;
     }
+    
+    @Override
+    public AdapterBinding getDeserializeAdapterBinding() {
+        return deserializeAdapter;
+    }
+    
+    @Override
+    public AdapterBinding getSerializeAdapterBinding() {
+        return serializeAdapter;
+    }
 
 }
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomizationBuilder.java b/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomizationBuilder.java
index 98160f4..e36b294 100644
--- a/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomizationBuilder.java
+++ b/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomizationBuilder.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -10,9 +10,9 @@
  * Contributors:
  *      Ehsan Zaery Moghaddam (zaerymoghaddam@gmail.com)
  ******************************************************************************/
-
 package org.eclipse.yasson.internal.model.customization;
 
+import org.eclipse.yasson.internal.components.AdapterBinding;
 import org.eclipse.yasson.internal.serializer.JsonbDateFormatter;
 import org.eclipse.yasson.internal.serializer.JsonbNumberFormatter;
 
@@ -24,20 +24,19 @@
 public class PropertyCustomizationBuilder extends CustomizationBuilder {
 
     private String jsonReadName;
-
     private String jsonWriteName;
 
     private JsonbNumberFormatter serializeNumberFormatter;
-
     private JsonbNumberFormatter deserializeNumberFormatter;
 
     private JsonbDateFormatter serializeDateFormatter;
-
     private JsonbDateFormatter deserializeDateFormatter;
 
     private boolean readTransient;
-
     private boolean writeTransient;
+    
+    private AdapterBinding serializeAdapter;
+    private AdapterBinding deserializeAdapter;
 
     private Class implementationClass;
 
@@ -212,4 +211,30 @@
     public void setImplementationClass(Class implementationClass) {
         this.implementationClass = implementationClass;
     }
+    
+    @Override
+    public void setAdapterInfo(AdapterBinding adapterInfo) {
+        throw new UnsupportedOperationException();
+    }
+    
+    @Override
+    public AdapterBinding getAdapterInfo() {
+        return null;
+    }
+    
+    public AdapterBinding getSerializeAdapter() {
+        return serializeAdapter;
+    }
+    
+    public void setSerializeAdapter(AdapterBinding adapter) {
+        this.serializeAdapter = adapter;
+    }
+    
+    public AdapterBinding getDeserializeAdapter() {
+        return deserializeAdapter;
+    }
+    
+    public void setDeserializeAdapter(AdapterBinding adapter) {
+        this.deserializeAdapter = adapter;
+    }
 }
diff --git a/src/main/java/org/eclipse/yasson/internal/serializer/DeserializerBuilder.java b/src/main/java/org/eclipse/yasson/internal/serializer/DeserializerBuilder.java
index 6e939ce..29607d4 100644
--- a/src/main/java/org/eclipse/yasson/internal/serializer/DeserializerBuilder.java
+++ b/src/main/java/org/eclipse/yasson/internal/serializer/DeserializerBuilder.java
@@ -76,7 +76,6 @@
      *
      * @return built item
      */
-    @SuppressWarnings("unchecked")
     public JsonbDeserializer<?> build() {
         runtimeType = resolveRuntimeType();
         Class<?> rawType = ReflectionUtils.getRawType(getRuntimeType());
@@ -95,7 +94,7 @@
             }
 
             //Second user components is registered.
-            Optional<AdapterBinding> adapterBinding = componentMatcher.getAdapterBinding(getRuntimeType(), componentBoundCustomization);
+            Optional<AdapterBinding> adapterBinding = componentMatcher.getDeserializeAdapterBinding(getRuntimeType(), componentBoundCustomization);
             if (adapterBinding.isPresent()) {
                 adapterInfoOptional = adapterBinding;
                 runtimeType = adapterInfoOptional.get().getToType();
@@ -247,7 +246,7 @@
 
     private Class<?> getInterfaceMappedType(Class<?> interfaceType) {
         if (interfaceType.isInterface()) {
-            Class implementationClass = null;
+            Class<?> implementationClass = null;
             //annotation
             if (customization instanceof PropertyCustomization) {
                  implementationClass = ((PropertyCustomization) customization).getImplementationClass();
diff --git a/src/main/java/org/eclipse/yasson/internal/serializer/ObjectDeserializer.java b/src/main/java/org/eclipse/yasson/internal/serializer/ObjectDeserializer.java
index f1a603e..9ced476 100644
--- a/src/main/java/org/eclipse/yasson/internal/serializer/ObjectDeserializer.java
+++ b/src/main/java/org/eclipse/yasson/internal/serializer/ObjectDeserializer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -28,7 +28,6 @@
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.logging.Logger;
 
 /**
  * Item for handling all types of unknown objects by reflection, parsing their fields, according to json key name.
@@ -59,8 +58,6 @@
         }
     }
 
-    private static final Logger log = Logger.getLogger(ObjectDeserializer.class.getName());
-
     private Map<String, ValueWrapper> values = new LinkedHashMap<>();
 
     private T instance;
@@ -137,7 +134,7 @@
         if (model == null) {
             return;
         }
-        values.put(model.getReadName(), new ValueWrapper(model, convertNullToOptionalEmpty(model.getPropertyType(), result)));
+        values.put(model.getReadName(), new ValueWrapper(model, convertNullToOptionalEmpty(model.getPropertyDeserializationType(), result)));
     }
 
     @Override
diff --git a/src/main/java/org/eclipse/yasson/internal/serializer/ObjectSerializer.java b/src/main/java/org/eclipse/yasson/internal/serializer/ObjectSerializer.java
index 7ab0f6a..c8350aa 100644
--- a/src/main/java/org/eclipse/yasson/internal/serializer/ObjectSerializer.java
+++ b/src/main/java/org/eclipse/yasson/internal/serializer/ObjectSerializer.java
@@ -10,7 +10,6 @@
  * Contributors:
  * Roman Grigoriadi
  ******************************************************************************/
-
 package org.eclipse.yasson.internal.serializer;
 
 import org.eclipse.yasson.internal.Marshaller;
@@ -101,7 +100,7 @@
                 return;
             }
 
-            Optional<Type> runtimeTypeOptional = ReflectionUtils.resolveOptionalType(this, propertyModel.getPropertyType());
+            Optional<Type> runtimeTypeOptional = ReflectionUtils.resolveOptionalType(this, propertyModel.getPropertySerializationType());
             Type genericType = runtimeTypeOptional.orElse(null);
             final JsonbSerializer<?> serializer = new SerializerBuilder(marshaller.getJsonbContext())
                     .withWrapper(this)
diff --git a/src/main/java/org/eclipse/yasson/internal/serializer/SerializerBuilder.java b/src/main/java/org/eclipse/yasson/internal/serializer/SerializerBuilder.java
index 7262cef..5731d79 100644
--- a/src/main/java/org/eclipse/yasson/internal/serializer/SerializerBuilder.java
+++ b/src/main/java/org/eclipse/yasson/internal/serializer/SerializerBuilder.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -10,7 +10,6 @@
  * Contributors:
  * Roman Grigoriadi
  ******************************************************************************/
-
 package org.eclipse.yasson.internal.serializer;
 
 import org.eclipse.yasson.internal.ComponentMatcher;
@@ -76,7 +75,7 @@
             }
 
             //Second user components is registered.
-            Optional<AdapterBinding> adapterInfoOptional = componentMatcher.getAdapterBinding(getRuntimeType(), customization);
+            Optional<AdapterBinding> adapterInfoOptional = componentMatcher.getSerializeAdapterBinding(getRuntimeType(), customization);
             if (adapterInfoOptional.isPresent()) {
                 return new AdaptedObjectSerializer<>(classModel, adapterInfoOptional.get());
             }
diff --git a/src/test/java/org/eclipse/yasson/adapters/AdaptersTest.java b/src/test/java/org/eclipse/yasson/adapters/AdaptersTest.java
index 17676ad..9ae2b66 100644
--- a/src/test/java/org/eclipse/yasson/adapters/AdaptersTest.java
+++ b/src/test/java/org/eclipse/yasson/adapters/AdaptersTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved.
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
  * which accompanies this distribution.
@@ -37,13 +37,16 @@
 import javax.json.bind.adapter.JsonbAdapter;
 import java.lang.reflect.Type;
 import java.math.BigDecimal;
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.UUID;
 
+import static java.util.Collections.unmodifiableMap;
 import static org.junit.Assert.assertEquals;
 
 /**
@@ -482,4 +485,96 @@
         Assert.assertEquals(Integer.valueOf(10), pojo.getNumberInteger());
         Assert.assertEquals(Integer.valueOf(11), pojo.getSerializableInteger());
     }
+    
+    public static class PropertyTypeMismatch {
+        private Throwable error = new RuntimeException("foo");
+        
+        public Optional<Throwable> getError() {
+            return Optional.ofNullable(error);
+        }
+        
+        public void setError(Instant errorTime) {
+            this.error = new RuntimeException("Error at: " + errorTime.toString());
+        }
+    }        
+    
+    public static class ThrowableAdapter implements JsonbAdapter<Throwable, Map<String, Object>> {
+
+        public int callCount = 0;
+
+        @Override
+        public Map<String, Object> adaptToJson(Throwable obj) throws Exception {
+            HashMap<String, Object> output = new HashMap<>();
+            output.put("message", obj.getMessage());
+            output.put("type", obj.getClass().getName());
+            callCount++;
+
+            return unmodifiableMap(output);
+        }
+
+        @Override
+        public Throwable adaptFromJson(Map<String, Object> obj) throws Exception {
+            throw new UnsupportedOperationException("not implemented");
+        }
+    }
+    
+    /**
+     * Serialize a class that has mismatching properties. The field is of type
+     * Throwable but the getter method is of type Optional<Throwable>. The user-defined
+     * adapter for Throwable should still be called.
+     */
+    @Test
+    public void testOptionalAdapter() {
+        ThrowableAdapter adapter = new ThrowableAdapter();
+        jsonb = JsonbBuilder.newBuilder()
+                .withConfig(new JsonbConfig().withAdapters(adapter))
+                .build();
+        
+        PropertyTypeMismatch obj = new PropertyTypeMismatch();
+        String json = jsonb.toJson(obj);
+        assertEquals("{\"error\":{\"message\":\"foo\",\"type\":\"java.lang.RuntimeException\"}}", json);
+        assertEquals("The user-defined ThrowableAdapter should have been called", 1, adapter.callCount);
+    }
+    
+    public static class InstantAdapter implements JsonbAdapter<Instant, String> {
+
+        public int callCount = 0;
+
+        @Override
+        public String adaptToJson(Instant obj) throws Exception {
+            return obj.toString();
+        }
+
+        @Override
+        public Instant adaptFromJson(String obj) throws Exception {
+            callCount++;
+            if (obj.equals("CUSTOM_VALUE"))
+                return Instant.MAX;
+            return Instant.parse(obj);
+        }
+    }
+    
+    /**
+     * Make sure that the same property can use a different adapter for
+     * serialization and deserialization.
+     */
+    @Test
+    public void testDifferentAdapters() {
+        ThrowableAdapter throwableAdapter = new ThrowableAdapter();
+        InstantAdapter instantAdapter = new InstantAdapter();
+        jsonb = JsonbBuilder.newBuilder()
+                .withConfig(new JsonbConfig().withAdapters(throwableAdapter, instantAdapter))
+                .build();
+        
+        String json = "{\"error\":\"CUSTOM_VALUE\"}";
+        PropertyTypeMismatch obj = jsonb.fromJson(json, PropertyTypeMismatch.class);
+        assertEquals("Error at: +1000000000-12-31T23:59:59.999999999Z", obj.getError().get().getMessage());
+        assertEquals(1, instantAdapter.callCount);
+        
+        String afterJson = jsonb.toJson(obj);
+        assertEquals("{\"error\":{\"message\":\"Error at: +1000000000-12-31T23:59:59.999999999Z\",\"type\":\"java.lang.RuntimeException\"}}", 
+                afterJson);
+        assertEquals(1, throwableAdapter.callCount);
+    }
+    
 }
diff --git a/src/test/java/org/eclipse/yasson/defaultmapping/basic/PropertyMismatchTest.java b/src/test/java/org/eclipse/yasson/defaultmapping/basic/PropertyMismatchTest.java
index eccdbaa..4a177c4 100644
--- a/src/test/java/org/eclipse/yasson/defaultmapping/basic/PropertyMismatchTest.java
+++ b/src/test/java/org/eclipse/yasson/defaultmapping/basic/PropertyMismatchTest.java
@@ -1,12 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ ******************************************************************************/
 package org.eclipse.yasson.defaultmapping.basic;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
+import java.time.Instant;
 import java.util.HashMap;
 import java.util.HashSet;
 
+import javax.json.bind.Jsonb;
 import javax.json.bind.JsonbBuilder;
+import javax.json.bind.annotation.JsonbTransient;
 
 import org.jboss.weld.exceptions.IllegalStateException;
 import org.junit.Test;
@@ -101,4 +113,38 @@
         String json = JsonbBuilder.create().toJson(obj);
         assertEquals("{}", json);
     }
+    
+    public static class PropertyTypeMismatch {
+        @JsonbTransient
+        public Instant internalInstantProperty;
+        
+        private String foo;
+        public int getFoo() {
+            return foo.length();
+        }
+        public void setFoo(Instant instant) {
+            this.foo = instant.toString();
+            this.internalInstantProperty = instant;
+        }
+    }
+    
+    /**
+     * Test that properties of the same name with different
+     * field/getter/setter types behave properly and that we don't
+     * assume they are all equal
+     */
+    @Test
+    public void testPropertyTypesMismatch() {
+        PropertyTypeMismatch obj = new PropertyTypeMismatch();
+        Instant now = Instant.now();
+        obj.setFoo(now);
+        
+        Jsonb jsonb = JsonbBuilder.create();
+        String json = jsonb.toJson(obj);
+        assertEquals("{\"foo\":" + now.toString().length() + "}", json);
+        
+        PropertyTypeMismatch after = jsonb.fromJson("{\"foo\":\"" + now.toString() + "\"}", PropertyTypeMismatch.class);
+        assertEquals(obj.getFoo(), after.getFoo());
+        assertEquals(obj.internalInstantProperty, after.internalInstantProperty);
+    }
 }