fixes after review
diff --git a/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java b/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
index 2142b74..2d90ee0 100644
--- a/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
+++ b/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
@@ -59,6 +59,7 @@
 import org.apache.sling.models.impl.model.InjectableMethod;
 import org.apache.sling.models.impl.model.ModelClass;
 import org.apache.sling.models.impl.model.ModelClassConstructor;
+import org.apache.sling.models.impl.model.OptionalTypedInjectableElement;
 import org.apache.sling.models.spi.AcceptsNullName;
 import org.apache.sling.models.spi.DisposalCallback;
 import org.apache.sling.models.spi.DisposalCallbackRegistry;
@@ -480,59 +481,22 @@
         }
     }
 
-    @NotNull
-    private InjectableElement getElement(InjectableElement element, Type type) {
-        return new InjectableElement() {
-            @Override
-            public AnnotatedElement getAnnotatedElement() {
-                return element.getAnnotatedElement();
-            }
+    private class OptionalWrappingCallback implements InjectCallback {
 
-            @Override
-            public Type getType() {
-                return type;
-            }
+        private final InjectCallback chainedCallback;
+        private final InjectableElement element;
 
-            @Override
-            public boolean isPrimitive() {
-                return element.isPrimitive();
-            }
+        private OptionalWrappingCallback(InjectCallback chainedCallback, InjectableElement element) {
+            this.chainedCallback = chainedCallback;
+            this.element = element;
+        }
 
-            @Override
-            public String getName() {
-                return element.getName();
-            }
-
-            @Override
-            public String getSource() {
-                return element.getSource();
-            }
-
-            @Override
-            public String getVia() {
-                return element.getVia();
-            }
-
-            @Override
-            public Class<? extends ViaProviderType> getViaProviderType() {
-                return element.getViaProviderType();
-            }
-
-            @Override
-            public boolean hasDefaultValue() {
-                return element.hasDefaultValue();
-            }
-
-            @Override
-            public Object getDefaultValue() {
-                return element.getDefaultValue() == null ? Optional.empty() : element.getDefaultValue();
-            }
-
-            @Override
-            public boolean isOptional(InjectAnnotationProcessor annotationProcessor) {
-                return true;
-            }
-        };
+        @Override
+        public RuntimeException inject(InjectableElement element1, Object value) {
+            return chainedCallback.inject(element, value.equals(Optional.empty())
+                    ? value    // if the value is null it's already represented as Optional.empty(), return as is
+                    : Optional.of(value)); // otherwise wrap in Optional
+        }
     }
 
     private
@@ -548,16 +512,10 @@
                 ParameterizedType pType = (ParameterizedType) genericType;
 
                 if (pType.getRawType().equals(Optional.class)) {
-                    InjectableElement el = getElement(element, pType.getActualTypeArguments()[0]);
+                    InjectableElement el = new OptionalTypedInjectableElement(element, pType.getActualTypeArguments()[0]);
+                    InjectCallback wrappedCallback = new OptionalWrappingCallback(callback, element);
 
-                    return injectElementInternal(el, adaptable, registry, new InjectCallback() {
-                        @Override
-                        public RuntimeException inject(InjectableElement element1, Object value) {
-                            return callback.inject(element, value.equals(Optional.empty())
-                                    ? value
-                                    : Optional.of(value));
-                        }
-                    }, preparedValues, modelContext);
+                    return injectElementInternal(el, adaptable, registry, wrappedCallback, preparedValues, modelContext);
                 }
             }
         }
diff --git a/src/main/java/org/apache/sling/models/impl/model/OptionalTypedInjectableElement.java b/src/main/java/org/apache/sling/models/impl/model/OptionalTypedInjectableElement.java
new file mode 100644
index 0000000..ba4f160
--- /dev/null
+++ b/src/main/java/org/apache/sling/models/impl/model/OptionalTypedInjectableElement.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sling.models.impl.model;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Type;
+import java.util.Optional;
+
+import org.apache.sling.models.annotations.ViaProviderType;
+import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor;
+
+public class OptionalTypedInjectableElement implements InjectableElement {
+
+    private final InjectableElement element;
+    private final Type type;
+
+    public OptionalTypedInjectableElement(InjectableElement element, Type type) {
+        this.element = element;
+        this.type = type;
+    }
+
+    @Override
+    public AnnotatedElement getAnnotatedElement() {
+        return element.getAnnotatedElement();
+    }
+
+    @Override
+    public Type getType() {
+        return type;
+    }
+
+    @Override
+    public boolean isPrimitive() {
+        return element.isPrimitive();
+    }
+
+    @Override
+    public String getName() {
+        return element.getName();
+    }
+
+    @Override
+    public String getSource() {
+        return element.getSource();
+    }
+
+    @Override
+    public String getVia() {
+        return element.getVia();
+    }
+
+    @Override
+    public Class<? extends ViaProviderType> getViaProviderType() {
+        return element.getViaProviderType();
+    }
+
+    @Override
+    public boolean hasDefaultValue() {
+        return element.hasDefaultValue();
+    }
+
+    @Override
+    public Object getDefaultValue() {
+        // Default value injector will be evaluated last, make sure we return a value here so the injection is successful
+        return element.getDefaultValue() == null ? Optional.empty() : element.getDefaultValue();
+    }
+
+    @Override
+    public boolean isOptional(InjectAnnotationProcessor annotationProcessor) {
+        return true;
+    }
+}