Merge branch '2.9' into 2.10
diff --git a/.travis.yml b/.travis.yml
index 15025d8..221255f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,21 +1,31 @@
 language: java
 
-# JDK 7 no longer works, just use JDK 8
+git:
+  quiet: true
+  submodules: false
+
+# Since Jackson 2.7, build requires jdk7, although module itself works on jdk6 still (for now)
+# and since 2.10, will require jdk8 for build
 jdk:
   - openjdk8
+  - oraclejdk11
+
+# 2019-11-26, tatu: Let's try caching Maven dependencies
+cache:
+  directories:
+    - $HOME/.m2
 
 # Below this line is configuration for deploying to the Sonatype OSS repo
-# http://blog.xeiam.com/2013/05/configure-travis-ci-to-deploy-snapshots.html
+# https://knowm.org/configure-travis-ci-to-deploy-snapshots/
 before_install: "git clone -b travis `git config --get remote.origin.url` target/travis"
 after_success:
-  - "mvn source:jar javadoc:jar deploy --settings target/travis/settings.xml"
-  - "mvn -B cobertura:cobertura coveralls:report"
+  - "mvn -B source:jar javadoc:jar deploy --settings target/travis/settings.xml"
 
 # whitelist
 branches:
   only:
     - master
-    - "2.9"
+    - "2.10"
 
 env:
   global:
diff --git a/LICENSE b/LICENSE
new file mode 120000
index 0000000..6fce517
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1 @@
+src/main/resources/META-INF/LICENSE
\ No newline at end of file
diff --git a/README.md b/README.md
index 7076dd2..b8b11f9 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@
 <properties>
   ...
   <!-- Use the latest version whenever possible. -->
-  <jackson.version>2.9.0</jackson.version>
+  <jackson.version>2.10.0</jackson.version>
   ...
 </properties>
 
@@ -404,12 +404,29 @@
 One additional limitation exists for so-called core components (streaming api, jackson-annotations and jackson-databind): no additional dependendies are allowed beyond:
 
 * Core components may rely on any methods included in the supported JDK
-    * Minimum JDK version is 1.6 as of Jackson 2.4 and above (1.5 was baseline with 2.3 and earlier)
+    * Minimum JDK version was 1.5 until (and including) version 2.3
+    * Minimum JDK version was 1.6 for Jackson 2.4 - 2.7 (inclusive) for all core components
+        * Minimum is still 1.6 for `jackson-annotations` and `jackson-core`, for all remaining Jackson 2.x versions
+    * Minimum JDK version is 1.7 for Jackson 2.7 - 2.10 of `jackson-databind` and most non-core components
 * Jackson-databind (this package) depends on the other two (annotations, streaming).
 
 This means that anything that has to rely on additional APIs or libraries needs to be built as an extension,
 usually a Jackson module.
 
+
+## Branches
+
+`master` branch is for developing the next major Jackson version -- 3.0 -- but there
+are active maintenance branches in which much of development happens:
+
+* `2.10` is the current stable minor 2.x version
+* `2.9` is for selected backported fixes 
+
+Older branches are usually not maintained after being declared as closed
+on [Jackson Releases](https://github.com/FasterXML/jackson/wiki/Jackson-Releases) page,
+but exist just in case a rare emergency patch is needed.
+All released versions have matching git tags (`jackson-dataformats-binary-2.9.10`).
+
 -----
 
 # Differences from Jackson 1.x
@@ -433,4 +450,3 @@
 
 * [Core annotations](https://github.com/FasterXML/jackson-annotations) package defines annotations commonly used for configuring databinding details
 * [Core parser/generator](https://github.com/FasterXML/jackson-core) package defines low-level incremental/streaming parsers, generators
-* [Jackson Project Home](http://wiki.fasterxml.com/JacksonHome) has additional documentation (although much of it for Jackson 1.x)
diff --git a/pom.xml b/pom.xml
index e6faeea..8ff3b14 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,12 +5,12 @@
   <parent>
     <groupId>com.fasterxml.jackson</groupId>
     <artifactId>jackson-base</artifactId>
-    <version>2.9.10.20200103</version>
+    <version>2.10.3-SNAPSHOT</version>
   </parent>
 
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
-  <version>2.9.10.3-SNAPSHOT</version>
+  <version>2.10.3-SNAPSHOT</version>
   <name>jackson-databind</name>
   <packaging>bundle</packaging>
   <description>General data-binding functionality for Jackson: works on core streaming API</description>
@@ -25,7 +25,7 @@
   </scm>
 
   <properties>
-    <!-- With Jackson 2.9 we will require JDK 7 (except for annotations/streaming),
+    <!-- With Jackson 2.10 baseline is JDK 7 (except for annotations/streaming),
          and new language features (diamond pattern) may be used.
          JDK classes are still loaded dynamically since there isn't much downside
          (small number of types); this allows use on JDK 6 platforms still (including
@@ -36,7 +36,8 @@
 
     <!-- Can not use default, since group id != Java package name here -->
     <osgi.export>com.fasterxml.jackson.databind.*;version=${project.version}</osgi.export>
-    <osgi.import> <!-- fix for databind#2299: using jackson-databind in an OSGi environment under Android --> 
+    <!-- fix for databind#2299: using jackson-databind in an OSGi environment under Android --> 
+    <osgi.import>
         org.w3c.dom.bootstrap;resolution:=optional,
         *
     </osgi.import>
@@ -45,8 +46,7 @@
     <packageVersion.dir>com/fasterxml/jackson/databind/cfg</packageVersion.dir>
     <packageVersion.package>com.fasterxml.jackson.databind.cfg</packageVersion.package>
 
-    <!-- since 2.9.1: NOTE! can not use packageVersion.package as is -->
-    <jdk.module.name>com.fasterxml.jackson.databind</jdk.module.name>
+    <version.powermock>2.0.0</version.powermock>
   </properties>
 
   <dependencies>
@@ -72,14 +72,20 @@
 
     <dependency>
       <groupId>org.powermock</groupId>
-      <artifactId>powermock-module-junit4</artifactId>
-      <version>1.7.4</version>
+      <artifactId>powermock-core</artifactId>
+      <version>${version.powermock}</version>
       <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.powermock</groupId>
-      <artifactId>powermock-api-mockito</artifactId>
-      <version>1.7.4</version>
+      <artifactId>powermock-module-junit4</artifactId>
+      <version>${version.powermock}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-mockito2</artifactId>
+      <version>${version.powermock}</version>
       <scope>test</scope>
     </dependency>
     <!-- For testing TestNoClassDefFoundDeserializer -->
@@ -105,6 +111,28 @@
 
   <build>
      <plugins>
+
+    <plugin>
+      <groupId>org.jacoco</groupId>
+      <artifactId>jacoco-maven-plugin</artifactId>
+      <version>0.8.4</version>
+      <executions>
+	<execution>
+	  <goals>
+	    <goal>prepare-agent</goal>
+	    </goals>
+	  </execution>
+	<!-- attached to Maven test phase -->
+	<execution>
+	  <id>report</id>
+	  <phase>test</phase>
+	  <goals>
+	    <goal>report</goal>
+	    </goals>
+	  </execution>
+	</executions>
+      </plugin>
+
       <!-- Important: enable enforcer plug-in: -->
       <plugin>
         <artifactId>maven-enforcer-plugin</artifactId>
@@ -128,6 +156,11 @@
           <excludes>
             <exclude>com/fasterxml/jackson/failing/*.java</exclude>
           </excludes>
+          <!-- 26-Nov-2019, tatu: moar parallelism! Per-class basis, safe, efficient enough
+                  ... although not 100% sure this makes much difference TBH
+            -->
+          <threadCount>4</threadCount>
+          <parallel>classes</parallel>
         </configuration>
       </plugin>
 
@@ -137,8 +170,8 @@
         <artifactId>maven-javadoc-plugin</artifactId>
         <configuration>
           <links combine.children="append">
-            <link>http://fasterxml.github.com/jackson-annotations/javadoc/2.9</link>
-            <link>http://fasterxml.github.com/jackson-core/javadoc/2.9</link>
+            <link>http://fasterxml.github.com/jackson-annotations/javadoc/2.10</link>
+            <link>http://fasterxml.github.com/jackson-core/javadoc/2.10</link>
           </links>
         </configuration>
       </plugin>
@@ -149,24 +182,16 @@
         <artifactId>replacer</artifactId>
       </plugin>
 
-      <!-- 18-Oct-2016, tatu: Try to make coveralls work -->
+      <!--  04-Mar-2019, tatu: Add rudimentary JDK9+ module info. To build with JDK 8
+             will have to use `moduleInfoFile` as anything else requires JDK 9+
+        -->
       <plugin>
-        <groupId>org.eluder.coveralls</groupId>
-        <artifactId>coveralls-maven-plugin</artifactId>
-        <version>4.3.0</version>
+        <groupId>org.moditect</groupId>
+        <artifactId>moditect-maven-plugin</artifactId>
       </plugin>
     </plugins>
   </build>
 
-  <reporting>
-    <plugins>
-      <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>cobertura-maven-plugin</artifactId>
-      </plugin>
-    </plugins>
-  </reporting>
-
   <profiles>
     <profile>
       <id>release</id>
diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x
index 5e92884..ef8be7c 100644
--- a/release-notes/CREDITS-2.x
+++ b/release-notes/CREDITS-2.x
@@ -341,6 +341,9 @@
   * Reported #941: Deserialization from "{}" to ObjectNode field causes
     "out of END_OBJECT token" error
    (2.6.3)
+  * Reported #2077: `JsonTypeInfo` with a subtype having `JsonFormat.Shape.ARRAY`
+    and no fields generates `{}` not `[]`
+   (2.10.0)
 
 David Haraburda (dharaburda@github)
   * Contributed #918: Add `MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING`
@@ -608,6 +611,9 @@
   * Contributed #1585: Invoke ServiceLoader.load() inside of a privileged block
     when loading modules using `ObjectMapper.findModules()`
    (2.8.9)
+  * Contributed fix for #2482: `JSONMappingException` `Location` column number
+    is one line Behind the actual location
+   (2.10.3)
 
 Javy Luo (AnywnYu@github)
   * Reported #1595: `JsonIgnoreProperties.allowSetters` is not working in Jackson 2.8
@@ -760,7 +766,9 @@
 Deblock Thomas (deblockt@github)
   * Reported, contributed fix for #1912: `BeanDeserializerModifier.updateBuilder()` does not
     work to set custom  deserializer on a property (since 2.9.0)
- (contributed by Deblock T)
+   (2.9.5)
+  * Reported, suggested fix for #2280: JsonMerge not work with constructor args
+   (2.10.0)
 
 lilei@venusgroup.com.cn:
   * Reported #1931: Two more `c3p0` gadgets to exploit default typing issue
@@ -815,9 +823,25 @@
   * Reported #2064: Cannot set custom format for `SqlDateSerializer` globally
    (2.9.7)
 
+Thibaut Robert (trobert@github)
+  * Requested #2059: Remove `final` modifier for `TypeFactory`
+   (2.10.0)
+
+Christopher Smith (chrylis@github)
+  * Suggested #2115: Support naive deserialization of `Serializable` values as "untyped",
+    same as `java.lang.Object`		     
+   (2.10.0)
+
+Édouard Mercier (edouardmercier@github)
+  * Requested #2116: Make NumberSerializers.Base public and its inherited classes not final
+   (2.9.6)
+
 Semyon Levin (remal@github)
   * Contributed #2120: `NioPathDeserializer` improvement
    (2.9.7)
+  * Contributed #2133: Improve `DeserializationProblemHandler.handleUnexpectedToken()`
+    to allow handling of Collection problems
+   (2.10.0)
 
 Pavel Nikitin (morj@github)
   * Requested #2181: Don't re-use dynamic serializers for property-updating copy constructors
@@ -838,7 +862,7 @@
     Collections$UnmodifiableRandomAccessList
    (2.9.9)
 
-Christoph (cfiehe@github.com)
+Christoph Fiehe (cfiehe@github.com)
   * Contributed #2299: Fix for using jackson-databind in an OSGi environment under Android
    (2.9.9)
 
@@ -872,3 +896,152 @@
 Jon Anderson (Jon901@github)
   * Reported #2544: java.lang.NoClassDefFoundError Thrown for compact profile1
    (2.9.10.2)
+
+Zihui Ren (renzihui@github)
+  * Suggested #2129: Add `SerializationFeature.WRITE_ENUM_KEYS_USING_INDEX`, separate from value setting
+   (2.10.0)
+
+Yiqiu Huang (huangyq23@github
+  * Reported #2164: `FactoryBasedEnumDeserializer` does not respect
+   `DeserializationFeature.WRAP_EXCEPTIONS`
+   (2.10.0)
+   
+Alexander Saites (saites@github)
+  * Reported #2189: `TreeTraversingParser` does not check int bounds
+   (2.10.0)
+
+Christoph Breitkopf (bokesan@github)
+  * Reported #2217: Suboptimal memory allocation in `TextNode.getBinaryValue()`
+   (2.10.0)
+
+Pavel Chervakov (pacher@github)
+  * Reported #2230: `WRITE_BIGDECIMAL_AS_PLAIN` is ignored if `@JsonFormat` is used
+   (2.10.0)
+
+Ben Anderson (andersonbd1@github)
+  * Reported, suggested fix for #2309: READ_ENUMS_USING_TO_STRING doesn't support null values
+   (2.10.0)
+
+Manuel Hegner (manuel-hegner@github)
+  * Suggested #2311: Unnecessary MultiView creation for property writers
+   (2.10.0)
+
+Chris Mercer (cmercer@github)
+  * Reported #2331: `JsonMappingException` through nested getter with generic wildcard return type
+   (2.10.0)
+
+Robert Greig (rgreig@github)
+  * Reported #2336: `MapDeserializer` can not merge `Map`s with polymorphic values
+   (2.10.0)
+
+Victor Noël (victornoel@github)
+  * Reported #2338: Suboptimal return type for `JsonNode.withArray()`
+   (2.10.0)
+  * Reported #2339: Suboptimal return type for `ObjectNode.set()`
+   (2.10.0)
+
+David Harris (toadzky@github)
+  * Reported #2378: `@JsonAlias` doesn't work with AutoValue
+   (2.10.0)
+
+Sam Smith (Oracle Security Researcher)
+  * Suggested #2398: Replace recursion in `TokenBuffer.copyCurrentStructure()` with iteration
+
+Vladimir Tsanev (tsachev@github)
+  * Contributed #2415: Builder-based POJO deserializer should pass builder instance, not type,
+    to `handleUnknownVanilla()` to fix earlier #822
+   (2.10.0)
+
+Marcos Passos (marcospassos@github(
+  * Contributed #2432: Add support for module bundles
+   (2.10.0)
+
+David Becker (dsbecker@github)
+  * Suggested #2433: Improve `NullNode.equals()`
+   (2.10.0)
+
+Hesham Massoud (heshamMassoud@github)
+  * Reported, contributed fix for #2442: `ArrayNode.addAll()` adds raw `null` values
+    which cause NPE on `deepCopy()`
+   (2.10.0)
+
+David Connelly (dconnelly@github)
+  * Reported #2446: Java 11: Unable to load JDK7 types (annotations, java.nio.file.Path):
+    no Java7 support added
+   (2.10.0)
+
+Wahey (KevynBct@github)
+  * Reported #2466: Didn't find class "java.nio.file.Path" below Android api 26
+  (2.10.0)
+
+Martín Coll (colltoaction@github)
+  * Contributed #2467: Accept `JsonTypeInfo.As.WRAPPER_ARRAY` with no second argument to
+   deserialize as "null value"
+  (2.10.0)
+
+Andrey Kulikov (ankulikov@github)
+  * Reported #2457: Extended enum values are not handled as enums when used as Map keys
+  (2.10.1)
+
+João Guerra (joca-bt@github)
+  * Reported #2473: Array index missing in path of `JsonMappingException` for `Collection<String>`,
+    with custom deserializer
+  (2.10.1)
+  * Reported #2567: Incorrect target type for arrays when providing nulls and nulls are disabled
+  (2.10.2)
+
+Ryan Bohn (bohnman@github)
+  * Reported #2475: `StringCollectionSerializer` calls `JsonGenerator.setCurrentValue(value)`,
+    which messes up current value for sibling properties
+  (2.10.1)
+
+Johan Haleby (johanhaleby@github)
+  * Reported #2513: BigDecimalAsStringSerializer in NumberSerializer throws IllegalStateException
+    in 2.10
+  (2.10.1)
+
+Richard Wise (Woodz@github)
+  * Reported #2519: Serializing `BigDecimal` values inside containers ignores shape override	
+  (2.10.1)
+
+Mark Schäfer (mark--@github)
+  * Reported #2520: Sub-optimal exception message when failing to deserialize non-static inner classes
+  (2.10.1)
+
+Ruud Welling (WellingR@github)
+  * Contributed fix for #2102: `FAIL_ON_NULL_FOR_PRIMITIVES` failure does not indicate
+    field name in exception message
+  (2.10.2)
+
+Fabian Lange (CodingFabian@github)
+  * Reported #2556: Contention in `TypeNameIdResolver.idFromClass()`
+  (2.10.2)
+
+Stefan Wendt (stewe@github)
+  * Reported #2560: Check `WRAP_EXCEPTIONS` in `CollectionDeserializer.handleNonArray()`
+  (2.10.2)
+
+Greg Arakelian (arakelian@github)
+  * Reported #2566: `MissingNode.toString()` returns `null` (4 character token) instead
+    of empty string
+  (2.10.2)
+
+Kamal Aslam (aslamkam@github)
+  * Reported #2482: `JSONMappingException` `Location` column number is one line
+    Behind the actual location
+  (2.10.3)
+
+Tobias Preuss (johnjohndoe@github)
+  * Reported #2599: NoClassDefFoundError at DeserializationContext.<init> on Android 4.1.2
+    and Jackson 2.10.0
+  (2.10.3)
+
+Eduard Tudenhöfner (nastra@github)
+  * Reported #2602, contributed fix for: ByteBufferSerializer produces unexpected results with
+    a duplicated ByteBuffer and a position > 0
+  (2.10.3)
+
+Alexander Shilov (ashlanderr@github)
+  * Reported, suggested fix for #2610: `EXTERNAL_PROPERTY` doesn't work with `@JsonIgnoreProperties`
+  (2.10.3)
+
diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x
index 6f1d5ba..cdcc162 100644
--- a/release-notes/VERSION-2.x
+++ b/release-notes/VERSION-2.x
@@ -4,6 +4,182 @@
 === Releases === 
 ------------------------------------------------------------------------
 
+2.10.3 (not yet released)
+
+#2482: `JSONMappingException` `Location` column number is one line Behind the actual
+  location
+ (reported by Kamal A, fixed by Ivo S)
+#2599: NoClassDefFoundError at DeserializationContext.<init> on Android 4.1.2
+  and Jackson 2.10.0
+ (reported by Tobias P)
+#2602: ByteBufferSerializer produces unexpected results with a duplicated ByteBuffer
+  and a position > 0
+ (reported by Eduard T)
+#2610: `EXTERNAL_PROPERTY` doesn't work with `@JsonIgnoreProperties`
+ (reported, fix suggested by Alexander S)
+
+2.10.2 (05-Jan-2020)
+
+#2101: `FAIL_ON_NULL_FOR_PRIMITIVES` failure does not indicate field name in exception message
+ (reported by raderio@github)
+#2544: java.lang.NoClassDefFoundError Thrown for compact profile1
+  (reported by Jon A)
+#2553: JsonDeserialize(contentAs=...) broken with raw collections
+ (reported by cpopp@github)
+#2556: Contention in `TypeNameIdResolver.idFromClass()`
+ (reported by Fabian L)
+#2560: Check `WRAP_EXCEPTIONS` in `CollectionDeserializer.handleNonArray()`
+ (reported by Stefan W)
+#2564: Fix `IllegalArgumentException` on empty input collection for `ArrayBlockingQueue`
+ (reported, fix suggested by yamert89@github)
+#2566: `MissingNode.toString()` returns `null` (4 character token) instead of empty string
+ (reported by Greg A)
+#2567: Incorrect target type for arrays when providing nulls and nulls are disabled
+ (reported by João G)
+#2573: Problem with `JsonInclude` config overrides for `java.util.Map`
+ (reported by SukruthKS@github)
+#2576: Fail to serialize `Enum` instance which includes a method override
+  as POJO (shape = Shape.OBJECT)
+ (reported by ylhuang-veeva@github)
+- Fix an issue with `ObjectReader.with(JsonParser.Feature)` (and related) not working
+
+2.10.1 (09-Nov-2019)
+
+#2457: Extended enum values are not handled as enums when used as Map keys
+ (reported by Andrey K)
+#2473: Array index missing in path of `JsonMappingException` for `Collection<String>`,
+  with custom deserializer
+ (reported by João G)
+#2475: `StringCollectionSerializer` calls `JsonGenerator.setCurrentValue(value)`,
+  which messes up current value for sibling properties
+ (reported by Ryan B)
+#2485: Add `uses` for `Module` in module-info
+ (contributed by Marc M)
+#2513: BigDecimalAsStringSerializer in NumberSerializer throws IllegalStateException in 2.10
+ (reported by Johan H)
+#2519: Serializing `BigDecimal` values inside containers ignores shape override
+ (reported by Richard W)
+#2520: Sub-optimal exception message when failing to deserialize non-static inner classes
+ (reported by Mark S)
+#2529: Add tests to ensure `EnumSet` and `EnumMap` work correctly with "null-as-empty"
+#2534: Add `BasicPolymorphicTypeValidator.Builder.allowIfSubTypeIsArray()`
+#2535: Allow String-to-byte[] coercion for String-value collections
+
+2.10.0 (26-Sep-2019)
+
+#18: Make `JsonNode` serializable
+#1093: Default typing does not work with `writerFor(Object.class)`
+ (reported by hoomanv@github)
+#1675: Remove "impossible" `IOException` in `readTree()` and `readValue()` `ObjectMapper`
+  methods which accept Strings
+ (requested by matthew-pwnieexpress@github)
+#1954: Add Builder pattern for creating configured `ObjectMapper` instances
+#1995: Limit size of `DeserializerCache`, auto-flush on exceeding
+#2059: Remove `final` modifier for `TypeFactory`
+ (requested by Thibaut R)
+#2077: `JsonTypeInfo` with a subtype having `JsonFormat.Shape.ARRAY` and
+  no fields generates `{}` not `[]`
+ (reported by Sadayuki F)
+#2115: Support naive deserialization of `Serializable` values as "untyped", same
+  as `java.lang.Object`
+ (requested by Christopher S)
+#2116: Make NumberSerializers.Base public and its inherited classes not final
+ (requested by Édouard M)
+#2126: `DeserializationContext.instantiationException()` throws `InvalidDefinitionException`
+#2129: Add `SerializationFeature.WRITE_ENUM_KEYS_USING_INDEX`, separate from value setting
+ (suggested by renzihui@github)
+#2133: Improve `DeserializationProblemHandler.handleUnexpectedToken()` to allow handling of
+  Collection problems
+ (contributed by Semyon L)
+#2149: Add `MapperFeature.ACCEPT_CASE_INSENSITIVE_VALUES`
+ (suggested by Craig P)
+#2153: Add `JsonMapper` to replace generic `ObjectMapper` usage
+#2164: `FactoryBasedEnumDeserializer` does not respect
+  `DeserializationFeature.WRAP_EXCEPTIONS`
+ (reported by Yiqiu H)
+#2187: Make `JsonNode.toString()` use shared `ObjectMapper` to produce valid json
+#2189: `TreeTraversingParser` does not check int bounds
+ (reported by Alexander S)
+#2195: Add abstraction `PolymorphicTypeValidator`, for limiting subtypes allowed by
+  default typing, `@JsonTypeInfo`
+#2196: Type safety for `readValue()` with `TypeReference`
+ (suggested by nguyenfilip@github)
+#2204: Add `JsonNode.isEmpty()` as convenience alias
+#2211: Change of behavior (2.8 -> 2.9) with `ObjectMapper.readTree(input)` with no content
+#2217: Suboptimal memory allocation in `TextNode.getBinaryValue()`
+ (reported by Christoph B)
+#2220: Force serialization always for `convertValue()`; avoid short-cuts
+#2223: Add `missingNode()` method in `JsonNodeFactory`
+#2227: Minor cleanup of exception message for `Enum` binding failure
+ (reported by RightHandedMonkey@github)
+#2230: `WRITE_BIGDECIMAL_AS_PLAIN` is ignored if `@JsonFormat` is used
+ (reported by Pavel C)
+#2236: Type id not provided on `Double.NaN`, `Infinity` with `@JsonTypeInfo`
+ (reported by C-B-B@github)
+#2237: Add "required" methods in `JsonNode`: `required(String | int)`,
+  `requiredAt(JsonPointer)`
+#2241: Add `PropertyNamingStrategy.LOWER_DOT_CASE` for dot-delimited names
+ (contributed by zenglian@github.com)
+#2251: Getter that returns an abstract collection breaks a delegating `@JsonCreator`
+#2265: Inconsistent handling of Collections$UnmodifiableList vs Collections$UnmodifiableRandomAccessListq
+#2273: Add basic Java 9+ module info
+#2280: JsonMerge not work with constructor args
+ (reported by Deblock T)
+#2309: READ_ENUMS_USING_TO_STRING doesn't support null values
+ (reported, fix suggested by Ben A)
+#2311: Unnecessary MultiView creation for property writers
+ (suggested by Manuel H)
+#2331: `JsonMappingException` through nested getter with generic wildcard return type
+ (reported by sunchezz89@github)
+#2336: `MapDeserializer` can not merge `Map`s with polymorphic values
+ (reported by Robert G)
+#2338: Suboptimal return type for `JsonNode.withArray()`
+ (reported by Victor N)
+#2339: Suboptimal return type for `ObjectNode.set()`
+ (reported by Victor N)
+#2348: Add sanity checks for `ObjectMapper.readXXX()` methods
+ (requested by ebundy@github)
+#2349: Add option `DefaultTyping.EVERYTHING` to support Kotlin data classes
+#2357: Lack of path on MismatchedInputException
+ (suggested by TheEin@github)
+#2378: `@JsonAlias` doesn't work with AutoValue
+ (reported by David H)
+#2390: `Iterable` serialization breaks when adding `@JsonFilter` annotation
+ (reported by Chris M)
+#2392: `BeanDeserializerModifier.modifyDeserializer()` not applied to custom bean deserializers
+ (reported by andreasbaus@github)
+#2393: `TreeTraversingParser.getLongValue()` incorrectly checks `canConvertToInt()`
+ (reported by RabbidDog@github)
+#2398: Replace recursion in `TokenBuffer.copyCurrentStructure()` with iteration
+ (reported by Sam S)
+#2415: Builder-based POJO deserializer should pass builder instance, not type,
+  to `handleUnknownVanilla()`
+ (proposed by Vladimir T, follow up to #822)
+#2416: Optimize `ValueInstantiator` construction for default `Collection`, `Map` types
+#2422: `scala.collection.immutable.ListMap` fails to serialize since 2.9.3
+ (reported by dejanlokar1@github)
+#2424: Add global config override setting for `@JsonFormat.lenient()`
+#2428: Use "activateDefaultTyping" over "enableDefaultTyping" in 2.10 with new methods
+#2430: Change `ObjectMapper.valueToTree()` to convert `null` to `NullNode`
+#2432: Add support for module bundles
+ (contributed by Marcos P)
+#2433: Improve `NullNode.equals()`
+ (suggested by David B)
+#2442: `ArrayNode.addAll()` adds raw `null` values which cause NPE on `deepCopy()`
+  and `toString()`
+ (reported, fix contributed by Hesham M)
+#2446: Java 11: Unable to load JDK7 types (annotations, java.nio.file.Path): no Java7 support added
+ (reported by David C)
+#2451: Add new `JsonValueFormat` value, `UUID`
+#2453: Add `DeserializationContext.readTree(JsonParser)` convenience method
+#2458: `Nulls` property metadata ignored for creators
+ (reported  by XakepSDK@github)
+#2466: Didn't find class "java.nio.file.Path" below Android api 26
+ (reported by KevynBct@github)
+#2467: Accept `JsonTypeInfo.As.WRAPPER_ARRAY` with no second argument to
+  deserialize as "null value"
+ (contributed by Martin C)
+
 2.9.10.3 (not released yet)
 
 #2620: Block one more gadget type (xbean-reflect/JNDI - CVE-2020-8840)
@@ -13,8 +189,6 @@
 
 #2526: Block two more gadget types (ehcache/JNDI - CVE-2019-20330)
   (repoerted by UltramanGaia)
-#2544: java.lang.NoClassDefFoundError Thrown for compact profile1
-  (reported by Jon A)
 
 2.9.10.1 (20-Oct-2019)
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/AbstractTypeResolver.java b/src/main/java/com/fasterxml/jackson/databind/AbstractTypeResolver.java
index 587c29f..27175e0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/AbstractTypeResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/AbstractTypeResolver.java
@@ -24,7 +24,7 @@
      * resolvers, until a concrete type is located.
      * 
      * @param config Configuration in use; should always be of type
-     *    <code>DeserializationConfig</code>
+     *    {@code DeserializationConfig}
      */
     public JavaType findTypeMapping(DeserializationConfig config, JavaType type) {
         return null;
diff --git a/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java b/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java
index bd83f0e..50a0d4a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java
@@ -630,21 +630,19 @@
 
     /**
      * Method for getting a serializer definition on specified method
-     * or field. Type of definition is either instance (of type
-     * {@link JsonSerializer}) or Class (of type
-     * <code>Class&lt;JsonSerializer></code>); if value of different
-     * type is returned, a runtime exception may be thrown by caller.
+     * or field. Type of definition is either instance (of type {@link JsonSerializer})
+     * or Class (of {@code Class&lt;JsonSerializer} implementation subtype);
+     * if value of different type is returned, a runtime exception may be thrown by caller.
      */
     public Object findSerializer(Annotated am) {
         return null;
     }
 
     /**
-     * Method for getting a serializer definition for keys of associated <code>Map</code> property.
-     * Type of definition is either instance (of type
-     * {@link JsonSerializer}) or Class (of type
-     * <code>Class&lt;JsonSerializer></code>); if value of different
-     * type is returned, a runtime exception may be thrown by caller.
+     * Method for getting a serializer definition for keys of associated {@code java.util.Map} property.
+     * Type of definition is either instance (of type {@link JsonSerializer})
+     * or Class (of type  {@code Class&lt;JsonSerializer>});
+     * if value of different type is returned, a runtime exception may be thrown by caller.
      */
     public Object findKeySerializer(Annotated am) {
         return null;
@@ -652,10 +650,10 @@
 
     /**
      * Method for getting a serializer definition for content (values) of
-     * associated <code>Collection</code>, <code>array</code> or <code>Map</code> property.
-     * Type of definition is either instance (of type
-     * {@link JsonSerializer}) or Class (of type
-     * <code>Class&lt;JsonSerializer></code>); if value of different
+     * associated <code>Collection</code>, <code>array</code> or {@code Map} property.
+     * Type of definition is either instance (of type {@link JsonSerializer})
+     * or Class (of type  {@code Class&lt;JsonSerializer>});
+     * if value of different
      * type is returned, a runtime exception may be thrown by caller.
      */
     public Object findContentSerializer(Annotated am) {
@@ -993,9 +991,8 @@
     /**
      * Method for getting a deserializer definition on specified method
      * or field.
-     * Type of definition is either instance (of type
-     * {@link JsonDeserializer}) or Class (of type
-     * <code>Class&lt;JsonDeserializer></code>); if value of different
+     * Type of definition is either instance (of type {@link JsonDeserializer})
+     * or Class (of type  {@code Class&lt;JsonDeserializer>});
      * type is returned, a runtime exception may be thrown by caller.
      */
     public Object findDeserializer(Annotated am) {
@@ -1005,9 +1002,9 @@
     /**
      * Method for getting a deserializer definition for keys of
      * associated <code>Map</code> property.
-     * Type of definition is either instance (of type
-     * {@link JsonDeserializer}) or Class (of type
-     * <code>Class&lt;JsonDeserializer></code>); if value of different
+     * Type of definition is either instance (of type {@link JsonDeserializer})
+     * or Class (of type  {@code Class&lt;JsonDeserializer>});
+     * if value of different
      * type is returned, a runtime exception may be thrown by caller.
      */
     public Object findKeyDeserializer(Annotated am) {
@@ -1018,9 +1015,9 @@
      * Method for getting a deserializer definition for content (values) of
      * associated <code>Collection</code>, <code>array</code> or
      * <code>Map</code> property.
-     * Type of definition is either instance (of type
-     * {@link JsonDeserializer}) or Class (of type
-     * <code>Class&lt;JsonDeserializer></code>); if value of different
+     * Type of definition is either instance (of type {@link JsonDeserializer})
+     * or Class (of type  {@code Class&lt;JsonDeserializer>});
+     * if value of different
      * type is returned, a runtime exception may be thrown by caller.
      */
     public Object findContentDeserializer(Annotated am) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/DatabindContext.java b/src/main/java/com/fasterxml/jackson/databind/DatabindContext.java
index 1111038..584e668 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DatabindContext.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DatabindContext.java
@@ -10,6 +10,8 @@
 import com.fasterxml.jackson.databind.cfg.MapperConfig;
 import com.fasterxml.jackson.databind.introspect.Annotated;
 import com.fasterxml.jackson.databind.introspect.ObjectIdInfo;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator.Validity;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 import com.fasterxml.jackson.databind.util.Converter;
@@ -163,33 +165,36 @@
 
     /**
      * Lookup method called when code needs to resolve class name from input;
-     * usually simple lookup
+     * usually simple lookup.
+     * Note that unlike {@link #resolveAndValidateSubType} this method DOES NOT
+     * validate subtype against configured {@link PolymorphicTypeValidator}: usually
+     * because such check has already been made.
      *
      * @since 2.9
      */
-    public JavaType resolveSubType(JavaType baseType, String subClass)
+    public JavaType resolveSubType(JavaType baseType, String subClassName)
         throws JsonMappingException
     {
         // 30-Jan-2010, tatu: Most ids are basic class names; so let's first
         //    check if any generics info is added; and only then ask factory
         //    to do translation when necessary
-        if (subClass.indexOf('<') > 0) {
+        if (subClassName.indexOf('<') > 0) {
             // note: may want to try combining with specialization (esp for EnumMap)?
             // 17-Aug-2017, tatu: As per [databind#1735] need to ensure assignment
             //    compatibility -- needed later anyway, and not doing so may open
             //    security issues.
-            JavaType t = getTypeFactory().constructFromCanonical(subClass);
+            JavaType t = getTypeFactory().constructFromCanonical(subClassName);
             if (t.isTypeOrSubTypeOf(baseType.getRawClass())) {
                 return t;
             }
         } else {
             Class<?> cls;
             try {
-                cls =  getTypeFactory().findClass(subClass);
+                cls =  getTypeFactory().findClass(subClassName);
             } catch (ClassNotFoundException e) { // let caller handle this problem
                 return null;
             } catch (Exception e) {
-                throw invalidTypeIdException(baseType, subClass, String.format(
+                throw invalidTypeIdException(baseType, subClassName, String.format(
                         "problem: (%s) %s",
                         e.getClass().getName(),
                         ClassUtil.exceptionMessage(e)));
@@ -198,7 +203,93 @@
                 return getTypeFactory().constructSpecializedType(baseType, cls);
             }
         }
-        throw invalidTypeIdException(baseType, subClass, "Not a subtype");
+        throw invalidTypeIdException(baseType, subClassName, "Not a subtype");
+    }
+
+    /**
+     * Lookup method similar to {@link #resolveSubType} but one that also validates
+     * that resulting subtype is valid according to given {@link PolymorphicTypeValidator}.
+     *
+     * @since 2.10
+     */
+    public JavaType resolveAndValidateSubType(JavaType baseType, String subClass,
+            PolymorphicTypeValidator ptv)
+        throws JsonMappingException
+    {
+        // Off-line the special case of generic (parameterized) type:
+        final int ltIndex = subClass.indexOf('<');
+        if (ltIndex > 0) {
+            return _resolveAndValidateGeneric(baseType, subClass, ptv, ltIndex);
+        }
+        final MapperConfig<?> config = getConfig();
+        PolymorphicTypeValidator.Validity vld = ptv.validateSubClassName(config, baseType, subClass);
+        if (vld == Validity.DENIED) {
+            return _throwSubtypeNameNotAllowed(baseType, subClass, ptv);
+        }
+        final Class<?> cls;
+        try {
+            cls =  getTypeFactory().findClass(subClass);
+        } catch (ClassNotFoundException e) { // let caller handle this problem
+            return null;
+        } catch (Exception e) {
+            throw invalidTypeIdException(baseType, subClass, String.format(
+                    "problem: (%s) %s",
+                    e.getClass().getName(),
+                    ClassUtil.exceptionMessage(e)));
+        }
+        if (!baseType.isTypeOrSuperTypeOf(cls)) {
+            return _throwNotASubtype(baseType, subClass);
+        }
+        final JavaType subType = config.getTypeFactory().constructSpecializedType(baseType, cls);
+        // May skip check if type was allowed by subclass name already
+        if (vld == Validity.INDETERMINATE) {
+            vld = ptv.validateSubType(config, baseType, subType);
+            if (vld != Validity.ALLOWED) {
+                return _throwSubtypeClassNotAllowed(baseType, subClass, ptv);
+            }
+        }
+        return subType;
+    }
+
+    private JavaType _resolveAndValidateGeneric(JavaType baseType, String subClass,
+            PolymorphicTypeValidator ptv, int ltIndex)
+        throws JsonMappingException
+    {
+        final MapperConfig<?> config = getConfig();
+        // 24-Apr-2019, tatu: Not 100% sure if we should pass name with type parameters
+        //    or not, but guessing it's more convenient not to have to worry about it so
+        //    strip out
+        PolymorphicTypeValidator.Validity vld = ptv.validateSubClassName(config, baseType, subClass.substring(0, ltIndex));
+        if (vld == Validity.DENIED) {
+            return _throwSubtypeNameNotAllowed(baseType, subClass, ptv);
+        }
+        JavaType subType = getTypeFactory().constructFromCanonical(subClass);
+        if (!subType.isTypeOrSubTypeOf(baseType.getRawClass())) {
+            return _throwNotASubtype(baseType, subClass);
+        }
+        // Unless we were approved already by name, check that actual sub-class acceptable:
+        if (vld != Validity.ALLOWED) {
+            if (ptv.validateSubType(config, baseType, subType) != Validity.ALLOWED) {
+                return _throwSubtypeClassNotAllowed(baseType, subClass, ptv);
+            }
+        }
+        return subType;
+    }
+
+    protected <T> T _throwNotASubtype(JavaType baseType, String subType) throws JsonMappingException {
+        throw invalidTypeIdException(baseType, subType, "Not a subtype");
+    }
+
+    protected <T> T _throwSubtypeNameNotAllowed(JavaType baseType, String subType,
+            PolymorphicTypeValidator ptv) throws JsonMappingException {
+        throw invalidTypeIdException(baseType, subType,
+                "Configured `PolymorphicTypeValidator` (of type "+ClassUtil.classNameOf(ptv)+") denied resolution");
+    }
+
+    protected <T> T _throwSubtypeClassNotAllowed(JavaType baseType, String subType,
+            PolymorphicTypeValidator ptv) throws JsonMappingException {
+        throw invalidTypeIdException(baseType, subType,
+                "Configured `PolymorphicTypeValidator` (of type "+ClassUtil.classNameOf(ptv)+") denied resolution");
     }
 
     /**
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
index 8867935..0744700 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationConfig.java
@@ -3,7 +3,7 @@
 import java.util.*;
 
 import com.fasterxml.jackson.core.*;
-
+import com.fasterxml.jackson.core.json.JsonReadFeature;
 import com.fasterxml.jackson.databind.cfg.*;
 import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
 import com.fasterxml.jackson.databind.introspect.*;
@@ -28,6 +28,9 @@
     // since 2.9
     private static final long serialVersionUID = 2;
 
+    // since 2.10.1
+    private final static int DESER_FEATURE_DEFAULTS = collectFeatureDefaults(DeserializationFeature.class);
+
     /*
     /**********************************************************
     /* Configured helper objects
@@ -101,7 +104,7 @@
             ConfigOverrides configOverrides)
     {
         super(base, str, mixins, rootNames, configOverrides);
-        _deserFeatures = collectFeatureDefaults(DeserializationFeature.class);
+        _deserFeatures = DESER_FEATURE_DEFAULTS;
         _nodeFactory = JsonNodeFactory.instance;
         _problemHandlers = null;
         _parserFeatures = 0;
@@ -498,6 +501,10 @@
      */
     public DeserializationConfig with(FormatFeature feature)
     {
+        // 08-Oct-2018, tatu: Alas, complexity due to newly (2.10) refactored json-features:
+        if (feature instanceof JsonReadFeature) {
+            return _withJsonReadFeatures(feature);
+        }
         int newSet = _formatReadFeatures | feature.getMask();
         int newMask = _formatReadFeaturesToChange | feature.getMask();
         return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)) ? this :
@@ -514,6 +521,10 @@
      */
     public DeserializationConfig withFeatures(FormatFeature... features)
     {
+        // 08-Oct-2018, tatu: Alas, complexity due to newly (2.10) refactored json-features:
+        if (features.length > 0 && (features[0] instanceof JsonReadFeature)) {
+            return _withJsonReadFeatures(features);
+        }
         int newSet = _formatReadFeatures;
         int newMask = _formatReadFeaturesToChange;
         for (FormatFeature f : features) {
@@ -535,6 +546,10 @@
      */
     public DeserializationConfig without(FormatFeature feature)
     {
+        // 08-Oct-2018, tatu: Alas, complexity due to newly (2.10) refactored json-features:
+        if (feature instanceof JsonReadFeature) {
+            return _withoutJsonReadFeatures(feature);
+        }
         int newSet = _formatReadFeatures & ~feature.getMask();
         int newMask = _formatReadFeaturesToChange | feature.getMask();
         return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)) ? this :
@@ -551,6 +566,10 @@
      */
     public DeserializationConfig withoutFeatures(FormatFeature... features)
     {
+        // 08-Oct-2018, tatu: Alas, complexity due to newly (2.10) refactored json-features:
+        if (features.length > 0 && (features[0] instanceof JsonReadFeature)) {
+            return _withoutJsonReadFeatures(features);
+        }
         int newSet = _formatReadFeatures;
         int newMask = _formatReadFeaturesToChange;
         for (FormatFeature f : features) {
@@ -562,7 +581,61 @@
             new DeserializationConfig(this,  _mapperFeatures, _deserFeatures,
                     _parserFeatures, _parserFeaturesToChange,
                     newSet, newMask);
-    }    
+    }
+
+    // temporary for 2.10
+    private DeserializationConfig _withJsonReadFeatures(FormatFeature... features) {
+        int parserSet = _parserFeatures;
+        int parserMask = _parserFeaturesToChange;
+        int newSet = _formatReadFeatures;
+        int newMask = _formatReadFeaturesToChange;
+        for (FormatFeature f : features) {
+            final int mask = f.getMask();
+            newSet |= mask;
+            newMask |= mask;
+
+            if (f instanceof JsonReadFeature) {
+                JsonParser.Feature oldF = ((JsonReadFeature) f).mappedFeature();
+                if (oldF != null) {
+                    final int pmask = oldF.getMask();
+                    parserSet |= pmask;
+                    parserMask |= pmask;
+                }
+            }
+        }
+        return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)
+                && (_parserFeatures == parserSet) && (_parserFeaturesToChange == parserMask)
+                ) ? this :
+            new DeserializationConfig(this,  _mapperFeatures, _deserFeatures,
+                    parserSet, parserMask, newSet, newMask);
+    }
+
+    // temporary for 2.10
+    private DeserializationConfig _withoutJsonReadFeatures(FormatFeature... features) {
+        int parserSet = _parserFeatures;
+        int parserMask = _parserFeaturesToChange;
+        int newSet = _formatReadFeatures;
+        int newMask = _formatReadFeaturesToChange;
+        for (FormatFeature f : features) {
+            final int mask = f.getMask();
+            newSet &= ~mask;
+            newMask |= mask;
+
+            if (f instanceof JsonReadFeature) {
+                JsonParser.Feature oldF = ((JsonReadFeature) f).mappedFeature();
+                if (oldF != null) {
+                    final int pmask = oldF.getMask();
+                    parserSet &= ~pmask;
+                    parserMask |= pmask;
+                }
+            }
+        }
+        return ((_formatReadFeatures == newSet) && (_formatReadFeaturesToChange == newMask)
+                && (_parserFeatures == parserSet) && (_parserFeaturesToChange == parserMask)
+                ) ? this :
+            new DeserializationConfig(this,  _mapperFeatures, _deserFeatures,
+                    parserSet, parserMask, newSet, newMask);
+    }
 
     /*
     /**********************************************************
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
index e2ff054..8931a96 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationContext.java
@@ -22,7 +22,9 @@
 import com.fasterxml.jackson.databind.exc.InvalidFormatException;
 import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
 import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
+import com.fasterxml.jackson.databind.exc.ValueInstantiationException;
 import com.fasterxml.jackson.databind.introspect.Annotated;
+import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
 import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
 import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
@@ -154,7 +156,7 @@
             DeserializerCache cache)
     {
         if (df == null) {
-            throw new IllegalArgumentException("Cannot pass null DeserializerFactory");
+            throw new NullPointerException("Cannot pass null DeserializerFactory");
         }
         _factory = df;
         if (cache == null) {
@@ -755,7 +757,7 @@
         JsonDeserializer<Object> deser = findRootValueDeserializer(type);
         if (deser == null) {
             reportBadDefinition(type,
-                    "Could not find JsonDeserializer for type "+type);
+                    "Could not find JsonDeserializer for type "+ClassUtil.getTypeDescription(type));
         }
         return (T) deser.deserialize(p, this);
     }
@@ -781,11 +783,29 @@
         if (deser == null) {
             return reportBadDefinition(type, String.format(
                     "Could not find JsonDeserializer for type %s (via property %s)",
-                    type, ClassUtil.nameOf(prop)));
+                    ClassUtil.getTypeDescription(type), ClassUtil.nameOf(prop)));
         }
         return (T) deser.deserialize(p, this);
     }
 
+    /**
+     * @since 2.10
+     */
+    public JsonNode readTree(JsonParser p) throws IOException {
+        JsonToken t = p.currentToken();
+        if (t == null) {
+            t = p.nextToken();
+            if (t == null) {
+                return getNodeFactory().missingNode();
+            }
+        }
+        if (t == JsonToken.VALUE_NULL) {
+            return getNodeFactory().nullNode();
+        }
+        return (JsonNode) findRootValueDeserializer(_config.constructType(JsonNode.class))
+                .deserialize(p, this);
+    }
+
     /*
     /**********************************************************
     /* Methods for problem handling
@@ -860,7 +880,9 @@
                 }
                 throw weirdStringException(keyValue, keyClass, String.format(
                         "DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s",
-                        keyClass, key.getClass()));
+                        ClassUtil.getClassDescription(keyClass),
+                        ClassUtil.getClassDescription(key)
+                ));
             }
             h = h.next();
         }
@@ -904,7 +926,9 @@
                 }
                 throw weirdStringException(value, targetClass, String.format(
                         "DeserializationProblemHandler.handleWeirdStringValue() for type %s returned value of type %s",
-                        targetClass, instance.getClass()));
+                        ClassUtil.getClassDescription(targetClass),
+                        ClassUtil.getClassDescription(instance)
+                ));
             }
             h = h.next();
         }
@@ -947,7 +971,9 @@
                 }
                 throw weirdNumberException(value, targetClass, _format(
                         "DeserializationProblemHandler.handleWeirdNumberValue() for type %s returned value of type %s",
-                        targetClass, key.getClass()));
+                        ClassUtil.getClassDescription(targetClass),
+                        ClassUtil.getClassDescription(key)
+                ));
             }
             h = h.next();
         }
@@ -970,7 +996,9 @@
                 }
                 throw JsonMappingException.from(p, _format(
 "DeserializationProblemHandler.handleWeirdNativeValue() for type %s returned value of type %s",
-targetType, goodValue.getClass()));
+                    ClassUtil.getClassDescription(targetType),
+                    ClassUtil.getClassDescription(goodValue)
+                ));
             }
         }
         throw weirdNativeValueException(badValue, raw);
@@ -1014,7 +1042,9 @@
                 }
                 reportBadDefinition(constructType(instClass), String.format(
 "DeserializationProblemHandler.handleMissingInstantiator() for type %s returned value of type %s",
-                        instClass, ClassUtil.classNameOf(instance)));
+                    ClassUtil.getClassDescription(instClass),
+                    ClassUtil.getClassDescription((instance)
+                )));
             }
             h = h.next();
         }
@@ -1064,12 +1094,18 @@
                 }
                 reportBadDefinition(constructType(instClass), String.format(
 "DeserializationProblemHandler.handleInstantiationProblem() for type %s returned value of type %s",
-                        instClass, ClassUtil.classNameOf(instance)));
+                    ClassUtil.getClassDescription(instClass),
+                    ClassUtil.classNameOf(instance)
+                ));
             }
             h = h.next();
         }
         // 18-May-2016, tatu: Only wrap if not already a valid type to throw
         ClassUtil.throwIfIOE(t);
+        // [databind#2164]: but see if wrapping is desired
+        if (!isEnabled(DeserializationFeature.WRAP_EXCEPTIONS)) {
+            ClassUtil.throwIfRTE(t);
+        }
         throw instantiationException(instClass, t);
     }
 
@@ -1090,7 +1126,7 @@
     public Object handleUnexpectedToken(Class<?> instClass, JsonParser p)
         throws IOException
     {
-        return handleUnexpectedToken(instClass, p.getCurrentToken(), p, null);
+        return handleUnexpectedToken(constructType(instClass), p.getCurrentToken(), p, null);
     }
 
     /**
@@ -1112,31 +1148,75 @@
             JsonParser p, String msg, Object... msgArgs)
         throws IOException
     {
+        return handleUnexpectedToken(constructType(instClass), t, p, msg, msgArgs);
+    }
+
+    /**
+     * Method that deserializers should call if the first token of the value to
+     * deserialize is of unexpected type (that is, type of token that deserializer
+     * cannot handle). This could occur, for example, if a Number deserializer
+     * encounter {@link JsonToken#START_ARRAY} instead of
+     * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
+     *
+     * @param targetType Type that was to be instantiated
+     * @param p Parser that points to the JSON value to decode
+     *
+     * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
+     *
+     * @since 2.10
+     */
+    public Object handleUnexpectedToken(JavaType targetType, JsonParser p)
+        throws IOException
+    {
+        return handleUnexpectedToken(targetType, p.getCurrentToken(), p, null);
+    }
+
+    /**
+     * Method that deserializers should call if the first token of the value to
+     * deserialize is of unexpected type (that is, type of token that deserializer
+     * cannot handle). This could occur, for example, if a Number deserializer
+     * encounter {@link JsonToken#START_ARRAY} instead of
+     * {@link JsonToken#VALUE_NUMBER_INT} or {@link JsonToken#VALUE_NUMBER_FLOAT}.
+     *
+     * @param targetType Type that was to be instantiated
+     * @param t Token encountered that does match expected
+     * @param p Parser that points to the JSON value to decode
+     *
+     * @return Object that should be constructed, if any; has to be of type <code>instClass</code>
+     *
+     * @since 2.10
+     */
+    public Object handleUnexpectedToken(JavaType targetType, JsonToken t,
+            JsonParser p, String msg, Object... msgArgs)
+        throws IOException
+    {
         msg = _format(msg, msgArgs);
         LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers();
         while (h != null) {
             Object instance = h.value().handleUnexpectedToken(this,
-                    instClass, t, p, msg);
+                    targetType, t, p, msg);
             if (instance != DeserializationProblemHandler.NOT_HANDLED) {
-                if (_isCompatible(instClass, instance)) {
+                if (_isCompatible(targetType.getRawClass(), instance)) {
                     return instance;
                 }
-                reportBadDefinition(constructType(instClass), String.format(
+                reportBadDefinition(targetType, String.format(
                         "DeserializationProblemHandler.handleUnexpectedToken() for type %s returned value of type %s",
-                        ClassUtil.nameOf(instClass), ClassUtil.classNameOf(instance)));
+                        ClassUtil.getClassDescription(targetType),
+                        ClassUtil.classNameOf(instance)
+                ));
             }
             h = h.next();
         }
         if (msg == null) {
             if (t == null) {
                 msg = String.format("Unexpected end-of-input when binding data into %s",
-                        ClassUtil.nameOf(instClass));
+                        ClassUtil.getTypeDescription(targetType));
             } else {
                 msg = String.format("Cannot deserialize instance of %s out of %s token",
-                        ClassUtil.nameOf(instClass), t);
+                        ClassUtil.getTypeDescription(targetType), t);
             }
         }
-        reportInputMismatch(instClass, msg);
+        reportInputMismatch(targetType, msg);
         return null; // never gets here
     }
 
@@ -1176,7 +1256,8 @@
                     return type;
                 }
                 throw invalidTypeIdException(baseType, id,
-                        "problem handler tried to resolve into non-subtype: "+type);
+                        "problem handler tried to resolve into non-subtype: "+
+                                ClassUtil.getTypeDescription(type));
             }
             h = h.next();
         }
@@ -1206,7 +1287,8 @@
                     return type;
                 }
                 throw invalidTypeIdException(baseType, null,
-                        "problem handler tried to resolve into non-subtype: "+type);
+                        "problem handler tried to resolve into non-subtype: "+
+                                ClassUtil.getTypeDescription(type));
             }
             h = h.next();
         }
@@ -1219,6 +1301,27 @@
     }
 
     /**
+     * Method that deserializer may call if it is called to do an update ("merge")
+     * but deserializer operates on a non-mergeable type. Although this should
+     * usually be caught earlier, sometimes it may only be caught during operation
+     * and if so this is the method to call.
+     * Note that if {@link MapperFeature#IGNORE_MERGE_FOR_UNMERGEABLE} is enabled,
+     * this method will simply return null; otherwise {@link InvalidDefinitionException}
+     * will be thrown.
+     *
+     * @since 2.10
+     */
+    public void handleBadMerge(JsonDeserializer<?> deser) throws JsonMappingException
+    {
+        if (!isEnabled(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)) {
+            JavaType type = constructType(deser.handledType());
+            String msg = String.format("Invalid configuration: values of type %s cannot be merged",
+                    ClassUtil.getTypeDescription(type));
+            throw InvalidDefinitionException.from(getParser(), msg, type);
+        }
+    }
+
+    /**
      * @since 2.9.2
      */
     protected boolean _isCompatible(Class<?> target, Object value)
@@ -1309,20 +1412,6 @@
      *
      * @since 2.9
      */
-    public <T> T reportInputMismatch(BeanProperty prop,
-            String msg, Object... msgArgs) throws JsonMappingException
-    {
-        msg = _format(msg, msgArgs);
-        JavaType type = (prop == null) ? null : prop.getType();
-        throw MismatchedInputException.from(getParser(), type, msg);
-    }
-
-    /**
-     * Helper method used to indicate a problem with input in cases where more
-     * specific <code>reportXxx()</code> method was not available.
-     *
-     * @since 2.9
-     */
     public <T> T reportInputMismatch(JsonDeserializer<?> src,
             String msg, Object... msgArgs) throws JsonMappingException
     {
@@ -1356,6 +1445,57 @@
         throw MismatchedInputException.from(getParser(), targetType, msg);
     }
 
+    /**
+     * Helper method used to indicate a problem with input in cases where more
+     * specific <code>reportXxx()</code> method was not available.
+     *
+     * @since 2.9
+     */
+    public <T> T reportInputMismatch(BeanProperty prop,
+            String msg, Object... msgArgs) throws JsonMappingException
+    {
+        msg = _format(msg, msgArgs);
+        JavaType type = (prop == null) ? null : prop.getType();
+        final MismatchedInputException e = MismatchedInputException.from(getParser(), type, msg);
+        // [databind#2357]: Include property name, if we have it
+        if (prop != null) {
+            AnnotatedMember member = prop.getMember();
+            if (member != null) {
+                e.prependPath(member.getDeclaringClass(), prop.getName());
+            }
+        }
+        throw e;
+    }
+
+    /**
+     * Helper method used to indicate a problem with input in cases where more
+     * specific <code>reportXxx()</code> method was not available.
+     *
+     * @since 2.10
+     */
+    public <T> T reportPropertyInputMismatch(Class<?> targetType, String propertyName,
+            String msg, Object... msgArgs) throws JsonMappingException
+    {
+        msg = _format(msg, msgArgs);
+        MismatchedInputException e = MismatchedInputException.from(getParser(), targetType, msg);
+        if (propertyName != null) {
+            e.prependPath(targetType, propertyName);
+        }
+        throw e;
+    }
+
+    /**
+     * Helper method used to indicate a problem with input in cases where more
+     * specific <code>reportXxx()</code> method was not available.
+     *
+     * @since 2.10
+     */
+    public <T> T reportPropertyInputMismatch(JavaType targetType, String propertyName,
+            String msg, Object... msgArgs) throws JsonMappingException
+    {
+        return reportPropertyInputMismatch(targetType.getRawClass(), propertyName, msg, msgArgs);
+    }    
+
     public <T> T reportTrailingTokens(Class<?> targetType,
             JsonParser p, JsonToken trailingToken) throws JsonMappingException
     {
@@ -1453,24 +1593,12 @@
     }
 
     /**
-     * Method that deserializer may call if it is called to do an update ("merge")
-     * but deserializer operates on a non-mergeable type. Although this should
-     * usually be caught earlier, sometimes it may only be caught during operation
-     * and if so this is the method to call.
-     * Note that if {@link MapperFeature#IGNORE_MERGE_FOR_UNMERGEABLE} is enabled,
-     * this method will simply return null; otherwise {@link InvalidDefinitionException}
-     * will be thrown.
-     *
-     * @since 2.9
+     * @deprecated Since 2.10 use {@link #handleBadMerge} instead
      */
-    public <T> T reportBadMerge(JsonDeserializer<?> deser) throws JsonMappingException
-    {
-        if (isEnabled(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)) {
-            return null;
-        }
-        JavaType type = constructType(deser.handledType());
-        String msg = String.format("Invalid configuration: values of type %s cannot be merged", type);
-        throw InvalidDefinitionException.from(getParser(), msg, type);
+    @Deprecated // since 2.10
+    public <T> T reportBadMerge(JsonDeserializer<?> deser) throws JsonMappingException {
+        handleBadMerge(deser);
+        return null;
     }
 
     /*
@@ -1540,16 +1668,15 @@
      * 
      * @param value String value from input being deserialized
      * @param instClass Type that String should be deserialized into
-     * @param msg Message that describes specific problem
+     * @param msgBase Message that describes specific problem
      * 
      * @since 2.1
      */
     public JsonMappingException weirdStringException(String value, Class<?> instClass,
-            String msg) {
-        return InvalidFormatException.from(_parser,
-                String.format("Cannot deserialize value of type %s from String %s: %s",
-                        ClassUtil.nameOf(instClass), _quotedString(value), msg),
-                value, instClass);
+            String msgBase) {
+        final String msg = String.format("Cannot deserialize value of type %s from String %s: %s",
+                ClassUtil.nameOf(instClass), _quotedString(value), msgBase);
+        return InvalidFormatException.from(_parser, msg, value, instClass);
     }
 
     /**
@@ -1595,8 +1722,6 @@
      * if necessary.
      */
     public JsonMappingException instantiationException(Class<?> instClass, Throwable cause) {
-        // Most likely problem with Creator definition, right?
-        final JavaType type = constructType(instClass);
         String excMsg;
         if (cause == null) {
             excMsg = "N/A";
@@ -1605,9 +1730,9 @@
         }
         String msg = String.format("Cannot construct instance of %s, problem: %s",
                 ClassUtil.nameOf(instClass), excMsg);
-        InvalidDefinitionException e = InvalidDefinitionException.from(_parser, msg, type);
-        e.initCause(cause);
-        return e;
+        // [databind#2162]: use specific exception type as we don't know if it's
+        // due to type definition, input, or neither
+        return ValueInstantiationException.from(_parser, msg, constructType(instClass), cause);
     }
 
     /**
@@ -1620,18 +1745,19 @@
      * if necessary.
      */
     public JsonMappingException instantiationException(Class<?> instClass, String msg0) {
-        // Most likely problem with Creator definition, right?
-        JavaType type = constructType(instClass);
-        String msg = String.format("Cannot construct instance of %s: %s",
-                ClassUtil.nameOf(instClass), msg0);
-        return InvalidDefinitionException.from(_parser, msg, type);
+        // [databind#2162]: use specific exception type as we don't know if it's
+        // due to type definition, input, or neither
+        return ValueInstantiationException.from(_parser,
+                String.format("Cannot construct instance of %s: %s",
+                        ClassUtil.nameOf(instClass), msg0),
+                constructType(instClass));
     }
 
     @Override
     public JsonMappingException invalidTypeIdException(JavaType baseType, String typeId,
             String extraDesc) {
         String msg = String.format("Could not resolve type id '%s' as a subtype of %s",
-                typeId, baseType);
+                typeId, ClassUtil.getTypeDescription(baseType));
         return InvalidTypeIdException.from(_parser, _colonConcat(msg, extraDesc), baseType, typeId);
     }
 
@@ -1661,7 +1787,7 @@
             String extraDesc)
     {
         String msg = String.format("Could not resolve type id '%s' into a subtype of %s",
-                id, type);
+                id, ClassUtil.getTypeDescription(type));
         msg = _colonConcat(msg, extraDesc);
         return MismatchedInputException.from(_parser, type, msg);
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
index 5fd5ca4..cc05d78 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
@@ -33,7 +33,13 @@
      * or {@link java.util.Collection} context) is available.
      * If enabled such values will be deserialized as {@link java.math.BigDecimal}s;
      * if disabled, will be deserialized as {@link Double}s.
-     * <p>
+     *<p>
+     * NOTE: one aspect of {@link java.math.BigDecimal} handling that may need
+     * configuring is whether trailing zeroes are trimmed:
+     * {@link com.fasterxml.jackson.databind.node.JsonNodeFactory} has
+     * {@link com.fasterxml.jackson.databind.node.JsonNodeFactory#withExactBigDecimals} for
+     * changing default behavior (default is for trailing zeroes to be trimmed).
+     *<p>
      * Feature is disabled by default, meaning that "untyped" floating
      * point numbers will by default be deserialized as {@link Double}s
      * (choice is for performance reason -- BigDecimals are slower than
@@ -84,9 +90,9 @@
     
     /**
      * Feature that determines whether JSON Array is mapped to
-     * <code>Object[]</code> or <code>List&lt;Object></code> when binding
+     * <code>Object[]</code> or <code>List&lt;Object&gt;</code> when binding
      * "untyped" objects (ones with nominal type of <code>java.lang.Object</code>).
-     * If true, binds as <code>Object[]</code>; if false, as <code>List&lt;Object></code>.
+     * If true, binds as <code>Object[]</code>; if false, as <code>List&lt;Object&gt;</code>.
      *<p>
      * Feature is disabled by default, meaning that JSON arrays are bound as
      * {@link java.util.List}s.
diff --git a/src/main/java/com/fasterxml/jackson/databind/JavaType.java b/src/main/java/com/fasterxml/jackson/databind/JavaType.java
index 3fdbb2b..f535b54 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JavaType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JavaType.java
@@ -288,7 +288,13 @@
     public boolean isArrayType() { return false; }
 
     @Override
-    public final boolean isEnumType() { return _class.isEnum(); }
+    public final boolean isEnumType() {
+        // 29-Sep-2019, tatu: `Class.isEnum()` not enough to detect custom subtypes,
+        //   but for some reason this fix will break couple of unit tests:
+        // See [databind#2480]:
+//        return ClassUtil.isEnumType(_class);
+        return _class.isEnum();
+    }
 
     @Override
     public final boolean isInterface() { return _class.isInterface(); }
diff --git a/src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java
index 469055f..9cbed3e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JsonDeserializer.java
@@ -82,7 +82,7 @@
      *  after the @class. Thus, if you want your method to work correctly
      *  both with and without polymorphism, you must begin your method with:
      *  <pre>
-     *       if (p.getCurrentToken() == JsonToken.START_OBJECT) {
+     *       if (p.currentToken() == JsonToken.START_OBJECT) {
      *         p.nextToken();
      *       }
      *  </pre>
@@ -125,11 +125,8 @@
     public T deserialize(JsonParser p, DeserializationContext ctxt, T intoValue)
         throws IOException
     {
-        if (ctxt.isEnabled(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)) {
-            return deserialize(p, ctxt);
-        }
-        throw new UnsupportedOperationException("Cannot update object of type "
-                +intoValue.getClass().getName()+" (by deserializer of type "+getClass().getName()+")");
+        ctxt.handleBadMerge(this);
+        return deserialize(p, ctxt);
     }
 
     /**
@@ -154,6 +151,22 @@
         return typeDeserializer.deserializeTypedFromAny(p, ctxt);
     }
 
+    /**
+     * Method similar to {@link #deserializeWithType(JsonParser,DeserializationContext,TypeDeserializer)}
+     * but called when merging value. Considered "bad merge" by default implementation,
+     * but if {@link MapperFeature#IGNORE_MERGE_FOR_UNMERGEABLE} is enabled will simple delegate to
+     * {@link #deserializeWithType(JsonParser, DeserializationContext, TypeDeserializer)}.
+     *
+     * @since 2.10
+     */
+    public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
+            TypeDeserializer typeDeserializer, T intoValue)
+        throws IOException
+    {
+        ctxt.handleBadMerge(this);
+        return deserializeWithType(p, ctxt, typeDeserializer);
+    }
+
     /*
     /**********************************************************
     /* Fluent factory methods for constructing decorated versions
@@ -267,9 +280,8 @@
      * Java null, but for some types (especially primitives) it may be
      * necessary to use non-null values.
      *<p>
-     * Since version 2.6 (in which the context argument was added), call is
-     * expected to be made each and every time a null token needs to
-     * be handled.
+     * This method may be called once, or multiple times, depending on what
+     * {@link #getNullAccessPattern()} returns.
      *<p>
      * Default implementation simply returns null.
      * 
@@ -282,6 +294,11 @@
     }
 
     /**
+     *  This method may be called in conjunction with calls to
+     * {@link #getNullValue(DeserializationContext)}, to check whether it needs
+     * to be called just once (static values), or each time empty value is
+     * needed.
+     *<p>
      * Default implementation indicates that "null value" to use for input null
      * is simply Java `null` for all deserializers, unless overridden by sub-classes.
      * This information may be used as optimization.
@@ -317,13 +334,11 @@
      * (most commonly when deserializing from empty JSON Strings).
      * Usually this is same as {@link #getNullValue} (which in turn
      * is usually simply Java null), but it can be overridden
-     * for types. Or, if type should never be converted from empty
+     * for specific types. Or, if type should never be converted from empty
      * String, method can also throw an exception.
      *<p>
-     * Since version 2.6 (in which the context argument was added), call is
-     * expected to be made each and every time an empty value is needed.
-     *<p>
-     * Since version 2.9 does not require return of `T` any more.
+     * This method may be called once, or multiple times, depending on what
+     * {@link #getEmptyAccessPattern()} returns.
      *<p>
      * Default implementation simply calls {@link #getNullValue} and
      * returns value.
diff --git a/src/main/java/com/fasterxml/jackson/databind/JsonMappingException.java b/src/main/java/com/fasterxml/jackson/databind/JsonMappingException.java
index 4c25818..74b9b93 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JsonMappingException.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JsonMappingException.java
@@ -251,7 +251,10 @@
     public JsonMappingException(Closeable processor, String msg, Throwable problem) {
         super(msg, problem);
         _processor = processor;
-        if (processor instanceof JsonParser) {
+        // 31-Jan-2020: [databind#2482] Retain original location
+        if (problem instanceof JsonProcessingException) {
+            _location = ((JsonProcessingException) problem).getLocation();
+        } else if (processor instanceof JsonParser) {
             _location = ((JsonParser) processor).getTokenLocation();
         }
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/JsonNode.java b/src/main/java/com/fasterxml/jackson/databind/JsonNode.java
index 78e6b65..646d547 100644
--- a/src/main/java/com/fasterxml/jackson/databind/JsonNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/JsonNode.java
@@ -81,6 +81,17 @@
     @Override
     public int size() { return 0; }
 
+    /**
+     * Convenience method that is functionally same as:
+     *<pre>
+     *    size() == 0
+     *</pre>
+     * for all node types.
+     *
+     * @since 2.10
+     */
+    public boolean isEmpty() { return size() == 0; }
+
     @Override
     public final boolean isValueNode()
     {
@@ -393,7 +404,7 @@
      * @since 2.0
      */
     public boolean canConvertToLong() { return false; }
-    
+
     /*
     /**********************************************************
     /* Public API, straight value access
@@ -481,7 +492,7 @@
      *   nodes.
      */
     public long longValue() { return 0L; }
-    
+
     /**
      * Returns 32-bit floating value for this node, <b>if and only if</b>
      * this node is numeric ({@link #isNumber} returns true). For other
@@ -666,6 +677,145 @@
     }
 
     /*
+    /**********************************************************************
+    /* Public API, extended traversal (2.10) with "required()"
+    /**********************************************************************
+     */
+
+    /**
+     * Method that may be called to verify that {@code this} node is NOT so-called
+     * "missing node": that is, one for which {@link #isMissingNode()} returns {@code true}.
+     * If not missing node, {@code this} is returned to allow chaining; otherwise
+     * {@link IllegalArgumentException} is thrown.
+     *
+     * @return {@code this} node to allow chaining
+     *
+     * @throws IllegalArgumentException if this node is "missing node"
+     *
+     * @since 2.10
+     */
+    public <T extends JsonNode> T require() throws IllegalArgumentException {
+        return _this();
+    }
+
+    /**
+     * Method that may be called to verify that {@code this} node is neither so-called
+     * "missing node" (that is, one for which {@link #isMissingNode()} returns {@code true})
+     * nor "null node" (one for which {@link #isNull()} returns {@code true}).
+     * If non-null non-missing node, {@code this} is returned to allow chaining; otherwise
+     * {@link IllegalArgumentException} is thrown.
+     *
+     * @return {@code this} node to allow chaining
+     *
+     * @throws IllegalArgumentException if this node is either "missing node" or "null node"
+     *
+     * @since 2.10
+     */
+    public <T extends JsonNode> T requireNonNull() throws IllegalArgumentException {
+        return _this();
+    }
+
+    /**
+     * Method is functionally equivalent to
+     *{@code
+     *   path(fieldName).required()
+     *}
+     * and can be used to check that this node is an {@code ObjectNode} (that is, represents
+     * JSON Object value) and has value for specified property with key {@code fieldName}
+     * (but note that value may be explicit JSON null value).
+     * If this node is Object Node and has value for specified property, {@code this} is returned
+     * to allow chaining; otherwise {@link IllegalArgumentException} is thrown.
+     *
+     * @return {@code this} node to allow chaining
+     *
+     * @throws IllegalArgumentException if this node is not an Object node or if it does not
+     *   have value for specified property
+     *
+     * @since 2.10
+     */
+    public JsonNode required(String fieldName) throws IllegalArgumentException {
+        return _reportRequiredViolation("Node of type `%s` has no fields", getClass().getName());
+    }
+
+    /**
+     * Method is functionally equivalent to
+     *{@code
+     *   path(index).required()
+     *}
+     * and can be used to check that this node is an {@code ArrayNode} (that is, represents
+     * JSON Array value) and has value for specified {@code index}
+     * (but note that value may be explicit JSON null value).
+     * If this node is Array Node and has value for specified index, {@code this} is returned
+     * to allow chaining; otherwise {@link IllegalArgumentException} is thrown.
+     *
+     * @return {@code this} node to allow chaining
+     *
+     * @throws IllegalArgumentException if this node is not an Array node or if it does not
+     *   have value for specified index
+     *
+     * @since 2.10
+     */
+    public JsonNode required(int index) throws IllegalArgumentException {
+        return _reportRequiredViolation("Node of type `%s` has no indexed values", getClass().getName());
+    }
+
+    /**
+     * Method is functionally equivalent to
+     *{@code
+     *   at(pathExpr).required()
+     *}
+     * and can be used to check that there is an actual value node at specified {@link JsonPointer}
+     * starting from {@code this} node
+     * (but note that value may be explicit JSON null value).
+     * If such value node exists {@code this} is returned
+     * to allow chaining; otherwise {@link IllegalArgumentException} is thrown.
+     *
+     * @return {@code this} node to allow chaining
+     *
+     * @throws IllegalArgumentException if no value node exists at given {@code JSON Pointer} path
+     *
+     * @since 2.10
+     */
+    public JsonNode requiredAt(String pathExpr) throws IllegalArgumentException {
+        return requiredAt(JsonPointer.compile(pathExpr));
+    }
+
+    /**
+     * Method is functionally equivalent to
+     *{@code
+     *   at(path).required()
+     *}
+     * and can be used to check that there is an actual value node at specified {@link JsonPointer}
+     * starting from {@code this} node
+     * (but note that value may be explicit JSON null value).
+     * If such value node exists {@code this} is returned
+     * to allow chaining; otherwise {@link IllegalArgumentException} is thrown.
+     *
+     * @return {@code this} node to allow chaining
+     *
+     * @throws IllegalArgumentException if no value node exists at given {@code JSON Pointer} path
+     *
+     * @since 2.10
+     */
+    public final JsonNode requiredAt(final JsonPointer path) throws IllegalArgumentException {
+        JsonPointer currentExpr = path;
+        JsonNode curr = this;
+
+        // Note: copied from `at()`
+        while (true) {
+            if (currentExpr.matches()) {
+                return curr;
+            }
+            curr = curr._at(currentExpr);
+            if (curr == null) {
+                _reportRequiredViolation("No node at '%s' (unmatched part: '%s')",
+                        path, currentExpr);
+            }
+            currentExpr = currentExpr.tail();
+        }
+    }
+
+    /*
     /**********************************************************
     /* Public API, value find / existence check methods
     /**********************************************************
@@ -893,8 +1043,10 @@
      * If the node method is called on is not Object node,
      * or if property exists and has value that is not Object node,
      * {@link UnsupportedOperationException} is thrown
+     *<p>
+     * NOTE: since 2.10 has had co-variant return type
      */
-    public JsonNode with(String propertyName) {
+    public <T extends JsonNode> T with(String propertyName) {
         throw new UnsupportedOperationException("JsonNode not of type ObjectNode (but "
                 +getClass().getName()+"), cannot call with() on it");
     }
@@ -906,8 +1058,10 @@
      * If the node method is called on is not Object node,
      * or if property exists and has value that is not Array node,
      * {@link UnsupportedOperationException} is thrown
+     *<p>
+     * NOTE: since 2.10 has had co-variant return type
      */
-    public JsonNode withArray(String propertyName) {
+    public <T extends JsonNode> T withArray(String propertyName) {
         throw new UnsupportedOperationException("JsonNode not of type ObjectNode (but "
                 +getClass().getName()+"), cannot call withArray() on it");
     }
@@ -947,10 +1101,10 @@
      */
     
     /**
-     * Method that will produce developer-readable representation of the
-     * node; which may <b>or may not</b> be as valid JSON.
-     * If you want valid JSON output (or output formatted using one of
-     * other Jackson supported data formats) make sure to use
+     * Method that will produce (as of Jackson 2.10) valid JSON using
+     * default settings of databind, as String.
+     * If you want other kinds of JSON output (or output formatted using one of
+     * other Jackson-supported data formats) make sure to use
      * {@link ObjectMapper} or {@link ObjectWriter} to serialize an
      * instance, for example:
      *<pre>
@@ -965,6 +1119,16 @@
     public abstract String toString();
 
     /**
+     * Alternative to {@link #toString} that will serialize this node using
+     * Jackson default pretty-printer.
+     *
+     * @since 2.10
+     */
+    public String toPrettyString() {
+        return toString();
+    }
+    
+    /**
      * Equality for node objects is defined as full (deep) value
      * equality. This means that it is possible to compare complete
      * JSON trees for equality by comparing equality of root nodes.
@@ -975,4 +1139,25 @@
      */
     @Override
     public abstract boolean equals(Object o);
+
+    /*
+    /**********************************************************************
+    /* Helper methods,  for sub-classes
+    /**********************************************************************
+     */
+
+    // @since 2.10
+    @SuppressWarnings("unchecked")
+    protected <T extends JsonNode> T _this() {
+        return (T) this;
+    }
+
+    /**
+     * Helper method that throws {@link IllegalArgumentException} as a result of
+     * violating "required-constraint" for this node (for {@link #required} or related
+     * methods).
+     */
+    protected <T> T _reportRequiredViolation(String msgTemplate, Object...args) {
+        throw new IllegalArgumentException(String.format(msgTemplate, args));
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java b/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
index 81884ad..f97706b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
+++ b/src/main/java/com/fasterxml/jackson/databind/MapperFeature.java
@@ -195,15 +195,15 @@
     INFER_PROPERTY_MUTATORS(true),
 
     /**
-     * Feature that determines handling of <code>java.beans.ConstructorProperties<code>
+     * Feature that determines handling of {@code java.beans.ConstructorProperties}
      * annotation: when enabled, it is considered as alias of
      * {@link com.fasterxml.jackson.annotation.JsonCreator}, to mean that constructor
      * should be considered a property-based Creator; when disabled, only constructor
      * parameter name information is used, but constructor is NOT considered an explicit
      * Creator (although may be discovered as one using other annotations or heuristics).
      *<p>
-     * Feature is mostly used to help interoperability with frameworks like Lombok
-     * that may automatically generate <code>ConstructorProperties</code> annotation
+     * Feature is mostly used to help inter-operability with frameworks like Lombok
+     * that may automatically generate {@code ConstructorProperties} annotation
      * but without necessarily meaning that constructor should be used as Creator
      * for deserialization.
      *<p>
@@ -296,7 +296,7 @@
      *<p>
      * Feature is disabled by default for backwards compatibility.
      *
-     * @since 2.9.6
+     * @since 2.10
      */
     USE_BASE_TYPE_AS_DEFAULT_IMPL(false),
 
@@ -361,7 +361,7 @@
      *<p>
      * Note that there is additional performance overhead since incoming property
      * names need to be lower-cased before comparison, for cases where there are upper-case
-     * letters. Overhead for names that are already lower-case should be negligible however.
+     * letters. Overhead for names that are already lower-case should be negligible.
      *<p>
      * Feature is disabled by default.
      * 
@@ -373,7 +373,7 @@
     /**
      * Feature that determines if Enum deserialization should be case sensitive or not.
      * If enabled, Enum deserialization will ignore case, that is, case of incoming String
-     * value and enum id (dependant on other settings, either `name()`, `toString()`, or
+     * value and enum id (depending on other settings, either `name()`, `toString()`, or
      * explicit override) do not need to match.
      * <p>
      * Feature is disabled by default.
@@ -383,6 +383,20 @@
     ACCEPT_CASE_INSENSITIVE_ENUMS(false),
 
     /**
+     * Feature that permits parsing some enumerated text-based value types but ignoring the case
+     * of the values on deserialization: for example, date/time type deserializers.
+     * Support for this feature depends on deserializer implementations using it.
+     *<p>
+     * Note, however, that regular {@code Enum} types follow {@link #ACCEPT_CASE_INSENSITIVE_ENUMS}
+     * setting instead.
+     *<p>
+     * Feature is disabled by default.
+     * 
+     * @since 2.10
+     */
+    ACCEPT_CASE_INSENSITIVE_VALUES(false),
+
+    /**
      * Feature that can be enabled to make property names be
      * overridden by wrapper name (usually detected with annotations
      * as defined by {@link AnnotationIntrospector#findWrapperName}.
@@ -482,9 +496,8 @@
      * merging is skipped and new value is created (<code>true</code>) or
      * an exception is thrown (false).
      *<p>
-     * Feature is disabled by default since non-mergeable property types are ignored
-     * even if defaults call for merging, and usually explicit per-type or per-property
-     * settings for such types should result in an exception.
+     * Feature is enabled by default, to allow use of merge defaults even in presence
+     * of some unmergeable properties.
      *
      * @since 2.9
      */
diff --git a/src/main/java/com/fasterxml/jackson/databind/MappingIterator.java b/src/main/java/com/fasterxml/jackson/databind/MappingIterator.java
index 06a4758..5ba57ed 100644
--- a/src/main/java/com/fasterxml/jackson/databind/MappingIterator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/MappingIterator.java
@@ -152,7 +152,7 @@
                 // regardless, recovery context should be whatever context we have now,
                 // with sole exception of pointing to a start marker, in which case it's
                 // the parent
-                JsonToken t = p.getCurrentToken();
+                JsonToken t = p.currentToken();
                 if ((t == JsonToken.START_OBJECT) || (t == JsonToken.START_ARRAY)) {
                     sctxt = sctxt.getParent();
                 }
@@ -162,11 +162,17 @@
         }
     }
 
+    /**
+     * Method for getting an "empty" iterator instance: one that never
+     * has more values; may be freely shared.
+     *
+     * @since 2.10 Existed earlier but {@code public} since 2.10
+     */
     @SuppressWarnings("unchecked")
-    protected static <T> MappingIterator<T> emptyIterator() {
+    public static <T> MappingIterator<T> emptyIterator() {
         return (MappingIterator<T>) EMPTY_ITERATOR;
     }
-    
+
     /*
     /**********************************************************
     /* Basic iterator impl
@@ -185,15 +191,16 @@
         }
     }
     
+    @SuppressWarnings("unchecked")
     @Override
     public T next()
     {
         try {
             return nextValue();
         } catch (JsonMappingException e) {
-            throw new RuntimeJsonMappingException(e.getMessage(), e);
+            return (T) _handleMappingException(e);
         } catch (IOException e) {
-            throw new RuntimeException(e.getMessage(), e);
+            return (T) _handleIOException(e);
         }
     }
 
@@ -218,10 +225,6 @@
     /**********************************************************
      */
 
-
-    /*
-     */
-    
     /**
      * Equivalent of {@link #next} but one that may throw checked
      * exceptions from Jackson due to invalid input.
@@ -235,7 +238,7 @@
             _resync();
             // fall-through
         case STATE_MAY_HAVE_VALUE:
-            JsonToken t = _parser.getCurrentToken();
+            JsonToken t = _parser.currentToken();
             if (t == null) { // un-initialized or cleared; find next
                 t = _parser.nextToken();
                 // If EOF, no more, or if we hit END_ARRAY (although we don't clear the token).
diff --git a/src/main/java/com/fasterxml/jackson/databind/Module.java b/src/main/java/com/fasterxml/jackson/databind/Module.java
index 1fe6096..3ae41f0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/Module.java
+++ b/src/main/java/com/fasterxml/jackson/databind/Module.java
@@ -15,6 +15,7 @@
 import com.fasterxml.jackson.databind.ser.Serializers;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.fasterxml.jackson.databind.type.TypeModifier;
+import java.util.Collections;
 
 /**
  * Simple interface for extensions that can be registered with {@link ObjectMapper}
@@ -73,7 +74,19 @@
      * using callback methods passed-in context object exposes.
      */
     public abstract void setupModule(SetupContext context);
-    
+
+    /**
+     * Returns the list of dependent modules this module has, if any.
+     * It is called to let modules register other modules as dependencies.
+     * Modules returned will be registered before this module is registered,
+     * in iteration order.
+     *
+     * @since 2.10
+     */
+    public Iterable<? extends Module> getDependencies() {
+        return Collections.emptyList();
+    }
+
     /*
     /**********************************************************
     /* Helper types
@@ -163,7 +176,7 @@
          *<pre>
          *   mapper.configOverride(java.util.Date.class)
          *       .setFormat(JsonFormat.Value.forPattern("yyyy-MM-dd"));
-         *<pre>
+         *</pre>
          * to change the default format to use for properties of type
          * {@link java.util.Date} (possibly further overridden by per-property
          * annotations)
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
index f4e571d..be5b8ee 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
@@ -23,6 +23,7 @@
 import com.fasterxml.jackson.databind.introspect.*;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
 import com.fasterxml.jackson.databind.jsontype.*;
+import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
 import com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver;
 import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
 import com.fasterxml.jackson.databind.node.*;
@@ -129,7 +130,7 @@
      */
 
     /**
-     * Enumeration used with {@link ObjectMapper#enableDefaultTyping()}
+     * Enumeration used with {@link ObjectMapper#activateDefaultTyping(PolymorphicTypeValidator)}
      * to specify what kind of types (classes) default typing should
      * be used for. It will only be used if no explicit type information
      * is found, but this enumeration further limits subset of those types.
@@ -142,9 +143,9 @@
      *<p>
      * NOTE: use of Default Typing can be a potential security risk if incoming
      * content comes from untrusted sources, and it is recommended that this
-     * is either not done, or, if enabled, use {@link #setDefaultTyping}
-     * passing a custom {@link TypeResolverBuilder} implementation that white-lists
-     * legal types to use.
+     * is either not done, or, if enabled, make sure to {@code activateDefaultTyping(...)}
+     * methods that take {@link PolymorphicTypeValidator} that limits applicability
+     * to known trusted types.
      */
     public enum DefaultTyping {
         /**
@@ -154,7 +155,7 @@
          * typing.
          */
         JAVA_LANG_OBJECT,
-        
+
         /**
          * Value that means that default typing will be used for
          * properties with declared type of {@link java.lang.Object}
@@ -173,7 +174,7 @@
          * Since 2.4, this does NOT apply to {@link TreeNode} and its subtypes.
          */
         NON_CONCRETE_AND_ARRAYS,
-        
+
         /**
          * Value that means that default typing will be used for
          * all non-final types, with exception of small number of
@@ -183,13 +184,29 @@
          *<p>
          * Since 2.4, this does NOT apply to {@link TreeNode} and its subtypes.
          */
-        NON_FINAL
+        NON_FINAL,
+
+        /**
+         * Value that means that default typing will be used for
+         * all non-final types, with exception of small number of
+         * "natural" types (String, Boolean, Integer, Double) that
+         * can be correctly inferred from JSON, and primitives (which
+         * can not be polymorphic either). Typing is also enabled for
+         * all array types.
+         *<p>
+         * Note that the only known use case for this setting is for serialization
+         * when passing instances of final class, and base type is not
+         * separately specified.
+         *
+         * @since 2.10
+         */
+        EVERYTHING
     }
 
     /**
      * Customized {@link TypeResolverBuilder} that provides type resolver builders
      * used with so-called "default typing"
-     * (see {@link ObjectMapper#enableDefaultTyping()} for details).
+     * (see {@link ObjectMapper#activateDefaultTyping(PolymorphicTypeValidator)} for details).
      *<p>
      * Type resolver construction is based on configuration: implementation takes care
      * of only providing builders in cases where type information should be applied.
@@ -207,8 +224,51 @@
          */
         protected final DefaultTyping _appliesFor;
 
+        /**
+         * {@link PolymorphicTypeValidator} top use for validating that the subtypes
+         * resolved are valid for use (usually to protect against possible
+         * security issues)
+         *
+         * @since 2.10
+         */
+        protected final PolymorphicTypeValidator _subtypeValidator;
+
+        /**
+         * @deprecated Since 2.10
+         */
+        @Deprecated // since 2.10
         public DefaultTypeResolverBuilder(DefaultTyping t) {
-            _appliesFor = t;
+            this(t, LaissezFaireSubTypeValidator.instance);
+        }
+
+        /**
+         * @since 2.10
+         */
+        public DefaultTypeResolverBuilder(DefaultTyping t, PolymorphicTypeValidator ptv) {
+            _appliesFor = _requireNonNull(t, "Can not pass `null` DefaultTyping");
+            _subtypeValidator = _requireNonNull(ptv, "Can not pass `null` PolymorphicTypeValidator");
+        }
+
+        // 20-Jan-2020: as per [databind#2599] Objects.requireNonNull() from JDK7 not in all Android so
+        private static <T> T _requireNonNull(T value, String msg) {
+            // Replacement for: return Objects.requireNonNull(t, msg);
+            if (value == null) {
+                throw new NullPointerException(msg);
+            }
+            return value;
+        }
+
+        /**
+         * @since 2.10
+         */
+        public static DefaultTypeResolverBuilder construct(DefaultTyping t,
+                PolymorphicTypeValidator ptv) {
+            return new DefaultTypeResolverBuilder(t, ptv);
+        }
+
+        @Override // since 2.10
+        public PolymorphicTypeValidator subTypeValidator(MapperConfig<?> config) {
+            return _subtypeValidator;
         }
 
         @Override
@@ -267,25 +327,24 @@
                 }
                 // [databind#88] Should not apply to JSON tree models:
                 return !t.isFinal() && !TreeNode.class.isAssignableFrom(t.getRawClass());
+            case EVERYTHING:
+                // So, excluding primitives (handled earlier) and "Natural types" (handled
+                // before this method is called), applied to everything
+                return true;
             default:
-            //case JAVA_LANG_OBJECT:
+            case JAVA_LANG_OBJECT:
                 return t.isJavaLangObject();
             }
         }
     }
 
+    
+    
     /*
     /**********************************************************
     /* Internal constants, singletons
     /**********************************************************
      */
-    
-    // Quick little shortcut, to avoid having to use global TypeFactory instance...
-    // 19-Oct-2015, tatu: Not sure if this is really safe to do; let's at least allow
-    //   some amount of introspection
-    private final static JavaType JSON_NODE_TYPE =
-            SimpleType.constructUnsafe(JsonNode.class);
-//            TypeFactory.defaultInstance().constructType(JsonNode.class);
 
     // 16-May-2009, tatu: Ditto ^^^
     protected final static AnnotationIntrospector DEFAULT_ANNOTATION_INTROSPECTOR = new JacksonAnnotationIntrospector();
@@ -301,7 +360,8 @@
             null, StdDateFormat.instance, null,
             Locale.getDefault(),
             null, // to indicate "use Jackson default TimeZone" (UTC since Jackson 2.7)
-            Base64Variants.getDefaultVariant() // 2.1
+            Base64Variants.getDefaultVariant(), // 2.1
+            LaissezFaireSubTypeValidator.instance
     );
 
     /*
@@ -347,7 +407,7 @@
     /* Configuration settings: mix-in annotations
     /**********************************************************
      */
-    
+
     /**
      * Mapping that defines how to apply mix-in annotations: key is
      * the type to received additional annotations, and value is the
@@ -426,7 +486,7 @@
      * @since 2.5
      */
     protected Set<Object> _registeredModuleTypes;
-    
+
     /*
     /**********************************************************
     /* Caching
@@ -719,6 +779,25 @@
      */
     public ObjectMapper registerModule(Module module)
     {
+        _assertNotNull("module", module);
+        // Let's ensure we have access to name and version information, 
+        // even if we do not have immediate use for either. This way we know
+        // that they will be available from beginning
+        String name = module.getModuleName();
+        if (name == null) {
+            throw new IllegalArgumentException("Module without defined name");
+        }
+        Version version = module.version();
+        if (version == null) {
+            throw new IllegalArgumentException("Module without defined version");
+        }
+
+        // [databind#2432]: Modules may depend on other modules; if so, register those first
+        for (Module dep : module.getDependencies()) {
+            registerModule(dep);
+        }
+
+        // then module itself
         if (isEnabled(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS)) {
             Object typeId = module.getTypeId();
             if (typeId != null) {
@@ -733,19 +812,6 @@
                 }
             }
         }
-        
-        /* Let's ensure we have access to name and version information, 
-         * even if we do not have immediate use for either. This way we know
-         * that they will be available from beginning
-         */
-        String name = module.getModuleName();
-        if (name == null) {
-            throw new IllegalArgumentException("Module without defined name");
-        }
-        Version version = module.version();
-        if (version == null) {
-            throw new IllegalArgumentException("Module without defined version");
-        }
 
         // And then call registration
         module.setupModule(new Module.SetupContext()
@@ -912,6 +978,7 @@
                 setPropertyNamingStrategy(naming);
             }
         });
+
         return this;
     }
 
@@ -947,6 +1014,7 @@
      */
     public ObjectMapper registerModules(Iterable<? extends Module> modules)
     {
+        _assertNotNull("modules", modules);
         for (Module module : modules) {
             registerModule(module);
         }
@@ -1379,6 +1447,32 @@
         setVisibility(vc);
     }
 
+    /**
+     * Method for specifying {@link PolymorphicTypeValidator} to use for validating
+     * polymorphic subtypes used with explicit polymorphic types (annotation-based),
+     * but NOT one with "default typing" (see {@link #activateDefaultTyping(PolymorphicTypeValidator)}
+     * for details).
+     *
+     * @since 2.10
+     */
+    public ObjectMapper setPolymorphicTypeValidator(PolymorphicTypeValidator ptv) {
+        BaseSettings s = _deserializationConfig.getBaseSettings().with(ptv);
+        _deserializationConfig = _deserializationConfig._withBase(s);
+        return this;
+    }
+
+    /**
+     * Accessor for configured {@link PolymorphicTypeValidator} used for validating
+     * polymorphic subtypes used with explicit polymorphic types (annotation-based),
+     * but NOT one with "default typing" (see {@link #activateDefaultTyping(PolymorphicTypeValidator)}
+     * for details).
+     *
+     * @since 2.10
+     */
+    public PolymorphicTypeValidator getPolymorphicTypeValidator() {
+        return _deserializationConfig.getBaseSettings().getPolymorphicTypeValidator();
+    }
+
     /*
     /**********************************************************
     /* Configuration: global-default/per-type override settings
@@ -1470,130 +1564,20 @@
         return this;
     }
 
-    /*
-    /**********************************************************
-    /* Type information configuration
-    /**********************************************************
-     */
-
     /**
-     * Convenience method that is equivalent to calling
-     *<pre>
-     *  enableDefaultTyping(DefaultTyping.OBJECT_AND_NON_CONCRETE);
-     *</pre>
-     *<p>
-     * NOTE: use of Default Typing can be a potential security risk if incoming
-     * content comes from untrusted sources, and it is recommended that this
-     * is either not done, or, if enabled, use {@link #setDefaultTyping}
-     * passing a custom {@link TypeResolverBuilder} implementation that white-lists
-     * legal types to use.
+     * @since 2.10
      */
-    public ObjectMapper enableDefaultTyping() {
-        return enableDefaultTyping(DefaultTyping.OBJECT_AND_NON_CONCRETE);
-    }
-
-    /**
-     * Convenience method that is equivalent to calling
-     *<pre>
-     *  enableDefaultTyping(dti, JsonTypeInfo.As.WRAPPER_ARRAY);
-     *</pre>
-     *<p>
-     * NOTE: use of Default Typing can be a potential security risk if incoming
-     * content comes from untrusted sources, and it is recommended that this
-     * is either not done, or, if enabled, use {@link #setDefaultTyping}
-     * passing a custom {@link TypeResolverBuilder} implementation that white-lists
-     * legal types to use.
-     */
-    public ObjectMapper enableDefaultTyping(DefaultTyping dti) {
-        return enableDefaultTyping(dti, JsonTypeInfo.As.WRAPPER_ARRAY);
-    }
-
-    /**
-     * Method for enabling automatic inclusion of type information, needed
-     * for proper deserialization of polymorphic types (unless types
-     * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}).
-     *<P>
-     * NOTE: use of <code>JsonTypeInfo.As#EXTERNAL_PROPERTY</code> <b>NOT SUPPORTED</b>;
-     * and attempts of do so will throw an {@link IllegalArgumentException} to make
-     * this limitation explicit.
-     *<p>
-     * NOTE: use of Default Typing can be a potential security risk if incoming
-     * content comes from untrusted sources, and it is recommended that this
-     * is either not done, or, if enabled, use {@link #setDefaultTyping}
-     * passing a custom {@link TypeResolverBuilder} implementation that white-lists
-     * legal types to use.
-     * 
-     * @param applicability Defines kinds of types for which additional type information
-     *    is added; see {@link DefaultTyping} for more information.
-     */
-    public ObjectMapper enableDefaultTyping(DefaultTyping applicability, JsonTypeInfo.As includeAs)
-    {
-        /* 18-Sep-2014, tatu: Let's add explicit check to ensure no one tries to
-         *   use "As.EXTERNAL_PROPERTY", since that will not work (with 2.5+)
-         */
-        if (includeAs == JsonTypeInfo.As.EXTERNAL_PROPERTY) {
-            throw new IllegalArgumentException("Cannot use includeAs of "+includeAs);
-        }
-        
-        TypeResolverBuilder<?> typer = new DefaultTypeResolverBuilder(applicability);
-        // we'll always use full class name, when using defaulting
-        typer = typer.init(JsonTypeInfo.Id.CLASS, null);
-        typer = typer.inclusion(includeAs);
-        return setDefaultTyping(typer);
-    }
-
-    /**
-     * Method for enabling automatic inclusion of type information -- needed
-     * for proper deserialization of polymorphic types (unless types
-     * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) --
-     * using "As.PROPERTY" inclusion mechanism and specified property name
-     * to use for inclusion (default being "@class" since default type information
-     * always uses class name as type identifier)
-     *<p>
-     * NOTE: use of Default Typing can be a potential security risk if incoming
-     * content comes from untrusted sources, and it is recommended that this
-     * is either not done, or, if enabled, use {@link #setDefaultTyping}
-     * passing a custom {@link TypeResolverBuilder} implementation that white-lists
-     * legal types to use.
-     */
-    public ObjectMapper enableDefaultTypingAsProperty(DefaultTyping applicability, String propertyName)
-    {
-        TypeResolverBuilder<?> typer = new DefaultTypeResolverBuilder(applicability);
-        // we'll always use full class name, when using defaulting
-        typer = typer.init(JsonTypeInfo.Id.CLASS, null);
-        typer = typer.inclusion(JsonTypeInfo.As.PROPERTY);
-        typer = typer.typeProperty(propertyName);
-        return setDefaultTyping(typer);
-    }
-
-    /**
-     * Method for disabling automatic inclusion of type information; if so, only
-     * explicitly annotated types (ones with
-     * {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) will have
-     * additional embedded type information.
-     */
-    public ObjectMapper disableDefaultTyping() {
-        return setDefaultTyping(null);
-    }
-
-    /**
-     * Method for enabling automatic inclusion of type information, using
-     * specified handler object for determining which types this affects,
-     * as well as details of how information is embedded.
-     *<p>
-     * NOTE: use of Default Typing can be a potential security risk if incoming
-     * content comes from untrusted sources, so care should be taken to use
-     * a {@link TypeResolverBuilder} that can limit allowed classes to
-     * deserialize.
-     * 
-     * @param typer Type information inclusion handler
-     */
-    public ObjectMapper setDefaultTyping(TypeResolverBuilder<?> typer) {
-        _deserializationConfig = _deserializationConfig.with(typer);
-        _serializationConfig = _serializationConfig.with(typer);
+    public ObjectMapper setDefaultLeniency(Boolean b) {
+        _configOverrides.setDefaultLeniency(b);
         return this;
     }
 
+    /*
+    /**********************************************************
+    /* Subtype registration
+    /**********************************************************
+     */
+
     /**
      * Method for registering specified class as a subtype, so that
      * typename-based resolution can link supertypes to subtypes
@@ -1626,6 +1610,196 @@
 
     /*
     /**********************************************************
+    /* Default typing (automatic polymorphic types): current (2.10)
+    /**********************************************************
+     */
+
+    /**
+     * Convenience method that is equivalent to calling
+     *<pre>
+     *  enableDefaultTyping(ptv, DefaultTyping.OBJECT_AND_NON_CONCRETE);
+     *</pre>
+     *<p>
+     * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
+     * as allowing all subtypes can be risky for untrusted content.
+     *
+     * @param ptv Validator used to verify that actual subtypes to deserialize are valid against
+     *    whatever criteria validator uses: important in case where untrusted content is deserialized.
+     *
+     * @since 2.10
+     */
+    public ObjectMapper activateDefaultTyping(PolymorphicTypeValidator ptv) {
+        return activateDefaultTyping(ptv, DefaultTyping.OBJECT_AND_NON_CONCRETE);
+    }
+
+    /**
+     * Convenience method that is equivalent to calling
+     *<pre>
+     *  enableDefaultTyping(ptv, dti, JsonTypeInfo.As.WRAPPER_ARRAY);
+     *</pre>
+     *<p>
+     * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
+     * as allowing all subtypes can be risky for untrusted content.
+     *
+     * @param ptv Validator used to verify that actual subtypes to deserialize are valid against
+     *    whatever criteria validator uses: important in case where untrusted content is deserialized.
+     * @param applicability Defines kinds of types for which additional type information
+     *    is added; see {@link DefaultTyping} for more information.
+     *
+     * @since 2.10
+     */
+    public ObjectMapper activateDefaultTyping(PolymorphicTypeValidator ptv,
+            DefaultTyping applicability) {
+        return activateDefaultTyping(ptv, applicability, JsonTypeInfo.As.WRAPPER_ARRAY);
+    }
+
+    /**
+     * Method for enabling automatic inclusion of type information, needed
+     * for proper deserialization of polymorphic types (unless types
+     * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}).
+     *<P>
+     * NOTE: use of <code>JsonTypeInfo.As#EXTERNAL_PROPERTY</code> <b>NOT SUPPORTED</b>;
+     * and attempts of do so will throw an {@link IllegalArgumentException} to make
+     * this limitation explicit.
+     *<p>
+     * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
+     * as allowing all subtypes can be risky for untrusted content.
+     *
+     * @param ptv Validator used to verify that actual subtypes to deserialize are valid against
+     *    whatever criteria validator uses: important in case where untrusted content is deserialized.
+     * @param applicability Defines kinds of types for which additional type information
+     *    is added; see {@link DefaultTyping} for more information.
+     * @param includeAs
+     *
+     * @since 2.10
+     */
+    public ObjectMapper activateDefaultTyping(PolymorphicTypeValidator ptv,
+            DefaultTyping applicability, JsonTypeInfo.As includeAs)
+    {
+        // 18-Sep-2014, tatu: Let's add explicit check to ensure no one tries to
+        //   use "As.EXTERNAL_PROPERTY", since that will not work (with 2.5+)
+        if (includeAs == JsonTypeInfo.As.EXTERNAL_PROPERTY) {
+            throw new IllegalArgumentException("Cannot use includeAs of "+includeAs);
+        }
+        
+        TypeResolverBuilder<?> typer = _constructDefaultTypeResolverBuilder(applicability, ptv);
+        // we'll always use full class name, when using defaulting
+        typer = typer.init(JsonTypeInfo.Id.CLASS, null);
+        typer = typer.inclusion(includeAs);
+        return setDefaultTyping(typer);
+    }
+
+    /**
+     * Method for enabling automatic inclusion of type information -- needed
+     * for proper deserialization of polymorphic types (unless types
+     * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) --
+     * using "As.PROPERTY" inclusion mechanism and specified property name
+     * to use for inclusion (default being "@class" since default type information
+     * always uses class name as type identifier)
+     *<p>
+     * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
+     * as allowing all subtypes can be risky for untrusted content.
+     *
+     * @param ptv Validator used to verify that actual subtypes to deserialize are valid against
+     *    whatever criteria validator uses: important in case where untrusted content is deserialized.
+     * @param applicability Defines kinds of types for which additional type information
+     *    is added; see {@link DefaultTyping} for more information.
+     * @param propertyName Name of property used for including type id for polymorphic values.
+     *
+     * @since 2.10
+     */
+    public ObjectMapper activateDefaultTypingAsProperty(PolymorphicTypeValidator ptv,
+            DefaultTyping applicability, String propertyName)
+    {
+        TypeResolverBuilder<?> typer = _constructDefaultTypeResolverBuilder(applicability,
+                getPolymorphicTypeValidator());
+
+        // we'll always use full class name, when using defaulting
+        typer = typer.init(JsonTypeInfo.Id.CLASS, null);
+        typer = typer.inclusion(JsonTypeInfo.As.PROPERTY);
+        typer = typer.typeProperty(propertyName);
+        return setDefaultTyping(typer);
+    }
+
+    /**
+     * Method for disabling automatic inclusion of type information; if so, only
+     * explicitly annotated types (ones with
+     * {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) will have
+     * additional embedded type information.
+     */
+    public ObjectMapper deactivateDefaultTyping() {
+        return setDefaultTyping(null);
+    }
+
+    /**
+     * Method for enabling automatic inclusion of type information, using
+     * specified handler object for determining which types this affects,
+     * as well as details of how information is embedded.
+     *<p>
+     * NOTE: use of Default Typing can be a potential security risk if incoming
+     * content comes from untrusted sources, so care should be taken to use
+     * a {@link TypeResolverBuilder} that can limit allowed classes to
+     * deserialize. Note in particular that
+     * {@link com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder}
+     * DOES NOT limit applicability but creates type (de)serializers for all
+     * types.
+     *
+     * @param typer Type information inclusion handler
+     */
+    public ObjectMapper setDefaultTyping(TypeResolverBuilder<?> typer) {
+        _deserializationConfig = _deserializationConfig.with(typer);
+        _serializationConfig = _serializationConfig.with(typer);
+        return this;
+    }
+
+    /*
+    /**********************************************************
+    /* Default typing (automatic polymorphic types): deprecated (pre-2.10)
+    /**********************************************************
+     */
+    
+    /**
+     * @deprecated Since 2.10 use {@link #activateDefaultTyping(PolymorphicTypeValidator)} instead
+     */
+    @Deprecated
+    public ObjectMapper enableDefaultTyping() {
+        return activateDefaultTyping(getPolymorphicTypeValidator());
+    }
+
+    /**
+     * @deprecated Since 2.10 use {@link #activateDefaultTyping(PolymorphicTypeValidator,DefaultTyping)} instead
+     */
+    @Deprecated
+    public ObjectMapper enableDefaultTyping(DefaultTyping dti) {
+        return enableDefaultTyping(dti, JsonTypeInfo.As.WRAPPER_ARRAY);
+    }
+
+    /**
+     * @deprecated Since 2.10 use {@link #activateDefaultTyping(PolymorphicTypeValidator,DefaultTyping,JsonTypeInfo.As)} instead
+     */
+    @Deprecated
+    public ObjectMapper enableDefaultTyping(DefaultTyping applicability, JsonTypeInfo.As includeAs) {
+        return activateDefaultTyping(getPolymorphicTypeValidator(), applicability, includeAs);
+    }
+
+    /**
+     * @deprecated Since 2.10 use {@link #activateDefaultTypingAsProperty(PolymorphicTypeValidator,DefaultTyping,String)} instead
+     */
+    @Deprecated
+    public ObjectMapper enableDefaultTypingAsProperty(DefaultTyping applicability, String propertyName) {
+        return activateDefaultTypingAsProperty(getPolymorphicTypeValidator(), applicability, propertyName);
+    }
+
+    /**
+     * @deprecated Since 2.10 use {@link #deactivateDefaultTyping} instead
+     */
+    @Deprecated
+    public ObjectMapper disableDefaultTyping() {
+        return setDefaultTyping(null);
+    }
+
+    /*
+    /**********************************************************
     /* Configuration, basic type handling
     /**********************************************************
      */
@@ -1640,7 +1814,7 @@
      *<pre>
      *   mapper.configOverride(java.util.Date.class)
      *       .setFormat(JsonFormat.Value.forPattern("yyyy-MM-dd"));
-     *<pre>
+     *</pre>
      * to change the default format to use for properties of type
      * {@link java.util.Date} (possibly further overridden by per-property
      * annotations)
@@ -1685,6 +1859,7 @@
      * context.
      */
     public JavaType constructType(Type t) {
+        _assertNotNull("t", t);
         return _typeFactory.constructType(t);
     }
 
@@ -1751,6 +1926,7 @@
      * @since 2.4
      */
     public ObjectMapper setConfig(DeserializationConfig config) {
+        _assertNotNull("config", config);
         _deserializationConfig = config;
         return this;
     }
@@ -1816,6 +1992,7 @@
      * @since 2.4
      */
     public ObjectMapper setConfig(SerializationConfig config) {
+        _assertNotNull("config", config);
         _serializationConfig = config;
         return this;
     }
@@ -1842,7 +2019,11 @@
      *
      * @return {@link JsonFactory} that this mapper uses when it needs to
      *   construct Json parser and generators
+     *
+     * @since 2.10
      */
+    public JsonFactory tokenStreamFactory() { return _jsonFactory; }
+
     @Override
     public JsonFactory getFactory() { return _jsonFactory; }
     
@@ -1941,11 +2122,10 @@
         // ok to use either one, should be kept in sync
         return _serializationConfig.isEnabled(f);
     }
-    
-    /**
-     * Method for changing state of an on/off mapper feature for
-     * this mapper instance.
-     */
+
+    // Note: planned to be deprecated in 2.11 (not needed with 2.10):
+    // @deprecated Since 2.10 use {@code JsonMapper.builder().configure(...)} (or similarly for other datatypes)
+    // @Deprecated
     public ObjectMapper configure(MapperFeature f, boolean state) {
         _serializationConfig = state ?
                 _serializationConfig.with(f) : _serializationConfig.without(f);
@@ -1954,26 +2134,24 @@
         return this;
     }
 
-    /**
-     * Method for enabling specified {@link MapperConfig} features.
-     * Modifies and returns this instance; no new object is created.
-     */
+    // Note: planned to be deprecated in 2.11 (not needed with 2.10):
+    // @deprecated Since 2.10 use {@code JsonMapper.builder().Enable(...)} (or similarly for other datatypes)
+    // @Deprecated
     public ObjectMapper enable(MapperFeature... f) {
         _deserializationConfig = _deserializationConfig.with(f);
         _serializationConfig = _serializationConfig.with(f);
         return this;
     }
 
-    /**
-     * Method for enabling specified {@link DeserializationConfig} features.
-     * Modifies and returns this instance; no new object is created.
-     */
+    // Note: planned to be deprecated in 2.11 (not needed with 2.10):
+    // @deprecated Since 2.10 use {@code JsonMapper.builder().disable(...)} (or similarly for other datatypes)
+    // @Deprecated
     public ObjectMapper disable(MapperFeature... f) {
         _deserializationConfig = _deserializationConfig.without(f);
         _serializationConfig = _serializationConfig.without(f);
         return this;
     }
-    
+
     /*
     /**********************************************************
     /* Configuration, simple features: SerializationFeature
@@ -2244,6 +2422,26 @@
 
     /*
     /**********************************************************
+    /* Configuration, 2.10+ stream features
+    /**********************************************************
+     */
+
+    /**
+     * @since 2.10
+     */
+    public boolean isEnabled(StreamReadFeature f) {
+        return isEnabled(f.mappedFeature());
+    }
+
+    /**
+     * @since 2.10
+     */
+    public boolean isEnabled(StreamWriteFeature f) {
+        return isEnabled(f.mappedFeature());
+    }
+    
+    /*
+    /**********************************************************
     /* Public API (from ObjectCodec): deserialization
     /* (mapping from JSON to Java types);
     /* main methods
@@ -2274,6 +2472,7 @@
     public <T> T readValue(JsonParser p, Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("p", p);
         return (T) _readValue(getDeserializationConfig(), p, _typeFactory.constructType(valueType));
     } 
 
@@ -2295,9 +2494,10 @@
      */
     @Override
     @SuppressWarnings("unchecked")
-    public <T> T readValue(JsonParser p, TypeReference<?> valueTypeRef)
+    public <T> T readValue(JsonParser p, TypeReference<T> valueTypeRef)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("p", p);
         return (T) _readValue(getDeserializationConfig(), p, _typeFactory.constructType(valueTypeRef));
     }
 
@@ -2321,6 +2521,7 @@
     public final <T> T readValue(JsonParser p, ResolvedType valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("p", p);
         return (T) _readValue(getDeserializationConfig(), p, (JavaType) valueType);
     }
 
@@ -2340,15 +2541,19 @@
     public <T> T readValue(JsonParser p, JavaType valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("p", p);
         return (T) _readValue(getDeserializationConfig(), p, valueType);
     }
     
     /**
-     * Method to deserialize JSON content as tree expressed
-     * using set of {@link JsonNode} instances. Returns
-     * root of the resulting tree (where root can consist
-     * of just a single node if the current event is a
-     * value event, not container).
+     * Method to deserialize JSON content as a tree {@link JsonNode}.
+     * Returns {@link JsonNode} that represents the root of the resulting tree, if there
+     * was content to read, or {@code null} if no more content is accessible
+     * via passed {@link JsonParser}.
+     *<p>
+     * NOTE! Behavior with end-of-input (no more content) differs between this
+     * {@code readTree} method, and all other methods that take input source: latter
+     * will return "missing node", NOT {@code null}
      * 
      * @return a {@link JsonNode}, if valid JSON content found; null
      *   if input has no content to bind -- note, however, that if
@@ -2367,13 +2572,8 @@
     public <T extends TreeNode> T readTree(JsonParser p)
         throws IOException, JsonProcessingException
     {
-        /* 02-Mar-2009, tatu: One twist; deserialization provider
-         *   will map JSON null straight into Java null. But what
-         *   we want to return is the "null node" instead.
-         */
-        /* 05-Aug-2011, tatu: Also, must check for EOF here before
-         *   calling readValue(), since that'll choke on it otherwise
-         */
+        _assertNotNull("p", p);
+        // Must check for EOF here before calling readValue(), since that'll choke on it otherwise
         DeserializationConfig cfg = getDeserializationConfig();
         JsonToken t = p.getCurrentToken();
         if (t == null) {
@@ -2382,7 +2582,8 @@
                 return null;
             }
         }
-        JsonNode n = (JsonNode) _readValue(cfg, p, JSON_NODE_TYPE);
+        // NOTE! _readValue() will check for trailing tokens
+        JsonNode n = (JsonNode) _readValue(cfg, p, constructType(JsonNode.class));
         if (n == null) {
             n = getNodeFactory().nullNode();
         }
@@ -2427,6 +2628,7 @@
     public <T> MappingIterator<T> readValues(JsonParser p, JavaType valueType)
         throws IOException, JsonProcessingException
     {
+        _assertNotNull("p", p);
         DeserializationConfig config = getDeserializationConfig();
         DeserializationContext ctxt = createDeserializationContext(p, config);
         JsonDeserializer<?> deser = _findRootDeserializer(ctxt, valueType);
@@ -2454,7 +2656,7 @@
      * Method for reading sequence of Objects from parser stream.
      */
     @Override
-    public <T> MappingIterator<T> readValues(JsonParser p, TypeReference<?> valueTypeRef)
+    public <T> MappingIterator<T> readValues(JsonParser p, TypeReference<T> valueTypeRef)
         throws IOException, JsonProcessingException
     {
         return readValues(p, _typeFactory.constructType(valueTypeRef));
@@ -2495,130 +2697,75 @@
      */
     public JsonNode readTree(InputStream in) throws IOException
     {
+        _assertNotNull("in", in);
         return _readTreeAndClose(_jsonFactory.createParser(in));
     }
 
     /**
-     * Method to deserialize JSON content as tree expressed
-     * using set of {@link JsonNode} instances.
-     * Returns root of the resulting tree (where root can consist
-     * of just a single node if the current event is a
-     * value event, not container).
-     *<p>
-     * If a low-level I/O problem (missing input, network error) occurs,
-     * a {@link IOException} will be thrown.
-     * If a parsing problem occurs (invalid JSON),
-     * {@link JsonParseException} will be thrown.
-     * If no content is found from input (end-of-input), Java
-     * <code>null</code> will be returned.
-     *
-     * @param r Reader used to read JSON content
-     *   for building the JSON tree.
-     * 
-     * @return a {@link JsonNode}, if valid JSON content found; null
-     *   if input has no content to bind -- note, however, that if
-     *   JSON <code>null</code> token is found, it will be represented
-     *   as a non-null {@link JsonNode} (one that returns <code>true</code>
-     *   for {@link JsonNode#isNull()}
+     * Same as {@link #readTree(InputStream)} except content accessed through
+     * passed-in {@link Reader}
      */
     public JsonNode readTree(Reader r) throws IOException {
+        _assertNotNull("r", r);
         return _readTreeAndClose(_jsonFactory.createParser(r));
     }
 
     /**
-     * Method to deserialize JSON content as tree expressed using set of {@link JsonNode} instances.
-     * Returns root of the resulting tree (where root can consist of just a single node if the current
-     * event is a value event, not container).
-     *<p>
-     * If a low-level I/O problem (missing input, network error) occurs,
-     * a {@link IOException} will be thrown.
-     * If a parsing problem occurs (invalid JSON),
-     * {@link JsonParseException} will be thrown.
-     * If no content is found from input (end-of-input), Java
-     * <code>null</code> will be returned.
-     *
-     * @param content JSON content to parse to build the JSON tree.
-     * 
-     * @return a {@link JsonNode}, if valid JSON content found; null
-     *   if input has no content to bind -- note, however, that if
-     *   JSON <code>null</code> token is found, it will be represented
-     *   as a non-null {@link JsonNode} (one that returns <code>true</code>
-     *   for {@link JsonNode#isNull()}
-     *
-     * @throws JsonParseException if underlying input contains invalid content
-     *    of type {@link JsonParser} supports (JSON for default case)
+     * Same as {@link #readTree(InputStream)} except content read from
+     * passed-in {@link String}
      */
-    public JsonNode readTree(String content) throws IOException {
+    public JsonNode readTree(String content) throws JsonProcessingException, JsonMappingException {
+        _assertNotNull("content", content);
+        try { // since 2.10 remove "impossible" IOException as per [databind#1675]
+            return _readTreeAndClose(_jsonFactory.createParser(content));
+        } catch (JsonProcessingException e) {
+            throw e;
+        } catch (IOException e) { // shouldn't really happen but being declared need to
+            throw JsonMappingException.fromUnexpectedIOE(e);
+        }
+    }
+
+    /**
+     * Same as {@link #readTree(InputStream)} except content read from
+     * passed-in byte array.
+     */
+    public JsonNode readTree(byte[] content) throws IOException {
+        _assertNotNull("content", content);
         return _readTreeAndClose(_jsonFactory.createParser(content));
     }
 
     /**
-     * Method to deserialize JSON content as tree expressed using set of {@link JsonNode} instances.
-     * Returns root of the resulting tree (where root can consist of just a single node if the current
-     * event is a value event, not container).
-     *
-     * @param content JSON content to parse to build the JSON tree.
-     * 
-     * @return a {@link JsonNode}, if valid JSON content found; null
-     *   if input has no content to bind -- note, however, that if
-     *   JSON <code>null</code> token is found, it will be represented
-     *   as a non-null {@link JsonNode} (one that returns <code>true</code>
-     *   for {@link JsonNode#isNull()}
-     *
-     * @throws JsonParseException if underlying input contains invalid content
-     *    of type {@link JsonParser} supports (JSON for default case)
+     * Same as {@link #readTree(InputStream)} except content read from
+     * passed-in byte array.
      */
-    public JsonNode readTree(byte[] content) throws IOException {
-        return _readTreeAndClose(_jsonFactory.createParser(content));
+    public JsonNode readTree(byte[] content, int offset, int len) throws IOException {
+        _assertNotNull("content", content);
+        return _readTreeAndClose(_jsonFactory.createParser(content, offset, len));
     }
-    
+
     /**
-     * Method to deserialize JSON content as tree expressed using set of {@link JsonNode} instances.
-     * Returns root of the resulting tree (where root can consist of just a single node if the current
-     * event is a value event, not container).
-     *
-     * @param file File of which contents to parse as JSON for building a tree instance
-     * 
-     * @return a {@link JsonNode}, if valid JSON content found; null
-     *   if input has no content to bind -- note, however, that if
-     *   JSON <code>null</code> token is found, it will be represented
-     *   as a non-null {@link JsonNode} (one that returns <code>true</code>
-     *   for {@link JsonNode#isNull()}
-     * 
-     * @throws IOException if a low-level I/O problem (unexpected end-of-input,
-     *   network error) occurs (passed through as-is without additional wrapping -- note
-     *   that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS}
-     *   does NOT result in wrapping of exception even if enabled)
-     * @throws JsonParseException if underlying input contains invalid content
-     *    of type {@link JsonParser} supports (JSON for default case)
+     * Same as {@link #readTree(InputStream)} except content read from
+     * passed-in {@link File}.
      */
     public JsonNode readTree(File file)
         throws IOException, JsonProcessingException
     {
+        _assertNotNull("file", file);
         return _readTreeAndClose(_jsonFactory.createParser(file));
     }
 
     /**
-     * Method to deserialize JSON content as tree expressed using set of {@link JsonNode} instances.
-     * Returns root of the resulting tree (where root can consist of just a single node if the current
-     * event is a value event, not container).
-     *
-     * @param source URL to use for fetching contents to parse as JSON for building a tree instance
-     * 
-     * @return a {@link JsonNode}, if valid JSON content found; null
-     *   if input has no content to bind -- note, however, that if
-     *   JSON <code>null</code> token is found, it will be represented
-     *   as a non-null {@link JsonNode} (one that returns <code>true</code>
-     *   for {@link JsonNode#isNull()}
-     * 
-     * @throws IOException if a low-level I/O problem (unexpected end-of-input,
-     *   network error) occurs (passed through as-is without additional wrapping -- note
-     *   that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS}
-     *   does NOT result in wrapping of exception even if enabled)
-     * @throws JsonParseException if underlying input contains invalid content
-     *    of type {@link JsonParser} supports (JSON for default case)
+     * Same as {@link #readTree(InputStream)} except content read from
+     * passed-in {@link URL}.
+     *<p>
+     * NOTE: handling of {@link java.net.URL} is delegated to
+     * {@link JsonFactory#createParser(java.net.URL)} and usually simply
+     * calls {@link java.net.URL#openStream()}, meaning no special handling
+     * is done. If different HTTP connection options are needed you will need
+     * to create {@link java.io.InputStream} separately.
      */
     public JsonNode readTree(URL source) throws IOException {
+        _assertNotNull("source", source);
         return _readTreeAndClose(_jsonFactory.createParser(source));
     }
 
@@ -2637,6 +2784,7 @@
     public void writeValue(JsonGenerator g, Object value)
         throws IOException, JsonGenerationException, JsonMappingException
     {
+        _assertNotNull("g", g);
         SerializationConfig config = getSerializationConfig();
 
         /* 12-May-2015/2.6, tatu: Looks like we do NOT want to call the usual
@@ -2667,13 +2815,14 @@
      */
 
     @Override
-    public void writeTree(JsonGenerator jgen, TreeNode rootNode)
+    public void writeTree(JsonGenerator g, TreeNode rootNode)
         throws IOException, JsonProcessingException
     {
+        _assertNotNull("g", g);
         SerializationConfig config = getSerializationConfig();
-        _serializerProvider(config).serializeValue(jgen, rootNode);
+        _serializerProvider(config).serializeValue(g, rootNode);
         if (config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
-            jgen.flush();
+            g.flush();
         }
     }
     
@@ -2681,13 +2830,14 @@
      * Method to serialize given JSON Tree, using generator
      * provided.
      */
-    public void writeTree(JsonGenerator jgen, JsonNode rootNode)
+    public void writeTree(JsonGenerator g, JsonNode rootNode)
         throws IOException, JsonProcessingException
     {
+        _assertNotNull("g", g);
         SerializationConfig config = getSerializationConfig();
-        _serializerProvider(config).serializeValue(jgen, rootNode);
+        _serializerProvider(config).serializeValue(g, rootNode);
         if (config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
-            jgen.flush();
+            g.flush();
         }
     }
     
@@ -2715,6 +2865,16 @@
         return _deserializationConfig.getNodeFactory().arrayNode();
     }
 
+    @Override // since 2.10
+    public JsonNode missingNode() {
+        return _deserializationConfig.getNodeFactory().missingNode();
+    }
+
+    @Override // since 2.10
+    public JsonNode nullNode() {
+        return _deserializationConfig.getNodeFactory().nullNode();
+    }
+
     /**
      * Method for constructing a {@link JsonParser} out of JSON tree
      * representation.
@@ -2723,6 +2883,7 @@
      */
     @Override
     public JsonParser treeAsTokens(TreeNode n) {
+        _assertNotNull("n", n);
         return new TreeTraversingParser((JsonNode) n, this);
     }
 
@@ -2740,15 +2901,24 @@
     public <T> T treeToValue(TreeNode n, Class<T> valueType)
         throws JsonProcessingException
     {
+        if (n == null) {
+            return null;
+        }
         try {
+            // 25-Jan-2019, tatu: [databind#2220] won't prevent existing coercions here
             // Simple cast when we just want to cast to, say, ObjectNode
-            // ... one caveat; while everything is Object.class, let's not take shortcut
-            if (valueType != Object.class && valueType.isAssignableFrom(n.getClass())) {
+            if (TreeNode.class.isAssignableFrom(valueType)
+                    && valueType.isAssignableFrom(n.getClass())) {
                 return (T) n;
             }
+            final JsonToken tt = n.asToken();
+            // 22-Aug-2019, tatu: [databind#2430] Consider "null node" (minor optimization)
+            if (tt == JsonToken.VALUE_NULL) {
+                return null;
+            }
             // 20-Apr-2016, tatu: Another thing: for VALUE_EMBEDDED_OBJECT, assume similar
             //    short-cut coercion
-            if (n.asToken() == JsonToken.VALUE_EMBEDDED_OBJECT) {
+            if (tt == JsonToken.VALUE_EMBEDDED_OBJECT) {
                 if (n instanceof POJONode) {
                     Object ob = ((POJONode) n).getPojo();
                     if ((ob == null) || valueType.isInstance(ob)) {
@@ -2782,13 +2952,18 @@
      * @param <T> Actual node type; usually either basic {@link JsonNode} or
      *  {@link com.fasterxml.jackson.databind.node.ObjectNode}
      * @param fromValue Bean value to convert
-     * @return Root node of the resulting JSON tree
+     *
+     * @return (non-null) Root node of the resulting JSON tree: in case of {@code null} value,
+     *    node for which {@link JsonNode#isNull()} returns {@code true}.
      */
     @SuppressWarnings({ "unchecked", "resource" })
     public <T extends JsonNode> T valueToTree(Object fromValue)
         throws IllegalArgumentException
     {
-        if (fromValue == null) return null;
+        // [databind#2430]: `null` should become "null node":
+        if (fromValue == null) {
+            return (T) getNodeFactory().nullNode();
+        }
         TokenBuffer buf = new TokenBuffer(this, false);
         if (isEnabled(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)) {
             buf = buf.forceUseOfBigDecimal(true);
@@ -2803,7 +2978,7 @@
             throw new IllegalArgumentException(e.getMessage(), e);
         }
         return (T) result;
-    } 
+    }
     
     /*
     /**********************************************************
@@ -2900,6 +3075,7 @@
     public <T> T readValue(File src, Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
     } 
 
@@ -2915,10 +3091,11 @@
      * @throws JsonMappingException if the input JSON structure does not match structure
      *   expected for result type (or has other mismatch issues)
      */
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public <T> T readValue(File src, TypeReference valueTypeRef)
+    @SuppressWarnings({ "unchecked" })
+    public <T> T readValue(File src, TypeReference<T> valueTypeRef)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef));
     } 
 
@@ -2938,11 +3115,18 @@
     public <T> T readValue(File src, JavaType valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType);
     }
 
     /**
      * Method to deserialize JSON content from given resource into given Java type.
+     *<p>
+     * NOTE: handling of {@link java.net.URL} is delegated to
+     * {@link JsonFactory#createParser(java.net.URL)} and usually simply
+     * calls {@link java.net.URL#openStream()}, meaning no special handling
+     * is done. If different HTTP connection options are needed you will need
+     * to create {@link java.io.InputStream} separately.
      * 
      * @throws IOException if a low-level I/O problem (unexpected end-of-input,
      *   network error) occurs (passed through as-is without additional wrapping -- note
@@ -2957,80 +3141,65 @@
     public <T> T readValue(URL src, Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
     } 
 
     /**
-     * Method to deserialize JSON content from given resource into given Java type.
-     * 
-     * @throws IOException if a low-level I/O problem (unexpected end-of-input,
-     *   network error) occurs (passed through as-is without additional wrapping -- note
-     *   that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS}
-     *   does NOT result in wrapping of exception even if enabled)
-     * @throws JsonParseException if underlying input contains invalid content
-     *    of type {@link JsonParser} supports (JSON for default case)
-     * @throws JsonMappingException if the input JSON structure does not match structure
-     *   expected for result type (or has other mismatch issues)
+     * Same as {@link #readValue(java.net.URL, Class)} except that target specified by {@link TypeReference}.
      */
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public <T> T readValue(URL src, TypeReference valueTypeRef)
+    @SuppressWarnings({ "unchecked" })
+    public <T> T readValue(URL src, TypeReference<T> valueTypeRef)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef));
     } 
 
+    /**
+     * Same as {@link #readValue(java.net.URL, Class)} except that target specified by {@link JavaType}.
+     */
     @SuppressWarnings("unchecked")
     public <T> T readValue(URL src, JavaType valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType);
-    } 
+    }
 
     /**
      * Method to deserialize JSON content from given JSON content String.
-     * 
-     * @throws IOException if a low-level I/O problem (unexpected end-of-input,
-     *   network error) occurs (passed through as-is without additional wrapping -- note
-     *   that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS}
-     *   does NOT result in wrapping of exception even if enabled)
+     *
      * @throws JsonParseException if underlying input contains invalid content
      *    of type {@link JsonParser} supports (JSON for default case)
      * @throws JsonMappingException if the input JSON structure does not match structure
      *   expected for result type (or has other mismatch issues)
      */
-    @SuppressWarnings("unchecked")
     public <T> T readValue(String content, Class<T> valueType)
-        throws IOException, JsonParseException, JsonMappingException
+        throws JsonProcessingException, JsonMappingException
     {
-        return (T) _readMapAndClose(_jsonFactory.createParser(content), _typeFactory.constructType(valueType));
+        _assertNotNull("content", content);
+        return readValue(content, _typeFactory.constructType(valueType));
     } 
 
     /**
      * Method to deserialize JSON content from given JSON content String.
-     * 
-     * @throws IOException if a low-level I/O problem (unexpected end-of-input,
-     *   network error) occurs (passed through as-is without additional wrapping -- note
-     *   that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS}
-     *   does NOT result in wrapping of exception even if enabled)
+     *
      * @throws JsonParseException if underlying input contains invalid content
      *    of type {@link JsonParser} supports (JSON for default case)
      * @throws JsonMappingException if the input JSON structure does not match structure
      *   expected for result type (or has other mismatch issues)
      */
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public <T> T readValue(String content, TypeReference valueTypeRef)
-        throws IOException, JsonParseException, JsonMappingException
+    public <T> T readValue(String content, TypeReference<T> valueTypeRef)
+        throws JsonProcessingException, JsonMappingException
     {
-        return (T) _readMapAndClose(_jsonFactory.createParser(content), _typeFactory.constructType(valueTypeRef));
+        _assertNotNull("content", content);
+        return readValue(content, _typeFactory.constructType(valueTypeRef));
     } 
 
     /**
      * Method to deserialize JSON content from given JSON content String.
-     * 
-     * @throws IOException if a low-level I/O problem (unexpected end-of-input,
-     *   network error) occurs (passed through as-is without additional wrapping -- note
-     *   that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS}
-     *   does NOT result in wrapping of exception even if enabled)
+     *
      * @throws JsonParseException if underlying input contains invalid content
      *    of type {@link JsonParser} supports (JSON for default case)
      * @throws JsonMappingException if the input JSON structure does not match structure
@@ -3038,22 +3207,31 @@
      */
     @SuppressWarnings("unchecked")
     public <T> T readValue(String content, JavaType valueType)
-        throws IOException, JsonParseException, JsonMappingException
+        throws JsonProcessingException, JsonMappingException
     {
-        return (T) _readMapAndClose(_jsonFactory.createParser(content), valueType);
+        _assertNotNull("content", content);
+        try { // since 2.10 remove "impossible" IOException as per [databind#1675]
+            return (T) _readMapAndClose(_jsonFactory.createParser(content), valueType);
+        } catch (JsonProcessingException e) {
+            throw e;
+        } catch (IOException e) { // shouldn't really happen but being declared need to
+            throw JsonMappingException.fromUnexpectedIOE(e);
+        }
     } 
 
     @SuppressWarnings("unchecked")
     public <T> T readValue(Reader src, Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
     } 
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public <T> T readValue(Reader src, TypeReference valueTypeRef)
+    @SuppressWarnings({ "unchecked" })
+    public <T> T readValue(Reader src, TypeReference<T> valueTypeRef)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef));
     } 
 
@@ -3061,6 +3239,7 @@
     public <T> T readValue(Reader src, JavaType valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType);
     } 
 
@@ -3068,13 +3247,15 @@
     public <T> T readValue(InputStream src, Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
     } 
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public <T> T readValue(InputStream src, TypeReference valueTypeRef)
+    @SuppressWarnings({ "unchecked" })
+    public <T> T readValue(InputStream src, TypeReference<T> valueTypeRef)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef));
     } 
 
@@ -3082,6 +3263,7 @@
     public <T> T readValue(InputStream src, JavaType valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType);
     } 
 
@@ -3089,6 +3271,7 @@
     public <T> T readValue(byte[] src, Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueType));
     } 
     
@@ -3097,21 +3280,24 @@
                                Class<T> valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src, offset, len), _typeFactory.constructType(valueType));
     } 
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public <T> T readValue(byte[] src, TypeReference valueTypeRef)
+    @SuppressWarnings({ "unchecked" })
+    public <T> T readValue(byte[] src, TypeReference<T> valueTypeRef)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), _typeFactory.constructType(valueTypeRef));
     } 
     
-    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @SuppressWarnings({ "unchecked" })
     public <T> T readValue(byte[] src, int offset, int len,
-                           TypeReference valueTypeRef)
+                           TypeReference<T> valueTypeRef)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src, offset, len), _typeFactory.constructType(valueTypeRef));
     } 
 
@@ -3119,6 +3305,7 @@
     public <T> T readValue(byte[] src, JavaType valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType);
     } 
 
@@ -3127,12 +3314,14 @@
                            JavaType valueType)
         throws IOException, JsonParseException, JsonMappingException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src, offset, len), valueType);
     } 
 
     @SuppressWarnings("unchecked")
     public <T> T readValue(DataInput src, Class<T> valueType) throws IOException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src),
                 _typeFactory.constructType(valueType));
     }
@@ -3140,6 +3329,7 @@
     @SuppressWarnings("unchecked")
     public <T> T readValue(DataInput src, JavaType valueType) throws IOException
     {
+        _assertNotNull("src", src);
         return (T) _readMapAndClose(_jsonFactory.createParser(src), valueType);
     }
 
@@ -3157,6 +3347,7 @@
     public void writeValue(File resultFile, Object value)
         throws IOException, JsonGenerationException, JsonMappingException
     {
+        _assertNotNull("resultFile", resultFile);
         _configAndWriteValue(_jsonFactory.createGenerator(resultFile, JsonEncoding.UTF8), value);
     }
 
@@ -3174,15 +3365,16 @@
     public void writeValue(OutputStream out, Object value)
         throws IOException, JsonGenerationException, JsonMappingException
     {
+        _assertNotNull("out", out);
         _configAndWriteValue(_jsonFactory.createGenerator(out, JsonEncoding.UTF8), value);
     }
 
     /**
      * @since 2.8
      */
-    public void writeValue(DataOutput out, Object value)
-        throws IOException
+    public void writeValue(DataOutput out, Object value) throws IOException
     {
+        _assertNotNull("out", out);
         _configAndWriteValue(_jsonFactory.createGenerator(out, JsonEncoding.UTF8), value);
     }
 
@@ -3199,6 +3391,7 @@
     public void writeValue(Writer w, Object value)
         throws IOException, JsonGenerationException, JsonMappingException
     {
+        _assertNotNull("w", w);
         _configAndWriteValue(_jsonFactory.createGenerator(w), value);
     }
 
@@ -3637,8 +3830,8 @@
 
     /**
      * Convenience method for doing two-step conversion from given value, into
-     * instance of given value type, if (but only if!) conversion is needed.
-     * If given value is already of requested type, value is returned as is.
+     * instance of given value type, by writing value into temporary buffer
+     * and reading from the buffer into specified target type.
      *<p>
      * This method is functionally similar to first
      * serializing given value into JSON, and then binding JSON data into value
@@ -3647,14 +3840,21 @@
      * However, same converters (serializers, deserializers) will be used as for
      * data binding, meaning same object mapper configuration works.
      *<p>
-     * Note that it is possible that in some cases behavior does differ from
-     * full serialize-then-deserialize cycle: in most case differences are
-     * unintentional (that is, flaws to fix) and should be reported.
-     * It is not guaranteed, however, that the behavior is 100% the same:
-     * the goal is just to allow efficient value conversions for structurally
+     * Note that behavior changed slightly between Jackson 2.9 and 2.10 so that
+     * whereas earlier some optimizations were used to avoid write/read cycle
+     * in case input was of target type, from 2.10 onwards full processing is
+     * always performed. See
+     * <a href="https://github.com/FasterXML/jackson-databind/issues/2220">databind#2220</a>
+     * for full details of the change.
+     *<p>
+     * Further note that it is possible that in some cases behavior does differ
+     * from full serialize-then-deserialize cycle: in most case differences are
+     * unintentional (that is, flaws to fix) and should be reported, but
+     * the behavior is not guaranteed to be 100% the same:
+     * the goal is to allow efficient value conversions for structurally
      * compatible Objects, according to standard Jackson configuration.
      *<p>
-     * Further note that functianality is not designed to support "advanced" use
+     * Finally, this functionality is not designed to support "advanced" use
      * cases, such as conversion of polymorphic values, or cases where Object Identity
      * is used.
      *      
@@ -3673,7 +3873,7 @@
      * See {@link #convertValue(Object, Class)}
      */
     @SuppressWarnings("unchecked")
-    public <T> T convertValue(Object fromValue, TypeReference<?> toValueTypeRef)
+    public <T> T convertValue(Object fromValue, TypeReference<T> toValueTypeRef)
         throws IllegalArgumentException
     {
         return (T) _convert(fromValue, _typeFactory.constructType(toValueTypeRef));
@@ -3701,20 +3901,7 @@
     protected Object _convert(Object fromValue, JavaType toValueType)
         throws IllegalArgumentException
     {
-        // [databind#1433] Do not shortcut null values.
-        // This defaults primitives and fires deserializer getNullValue hooks.
-        if (fromValue != null) {
-            // also, as per [databind#11], consider case for simple cast
-            // But with caveats: one is that while everything is Object.class, we don't
-            // want to "optimize" that out; and the other is that we also do not want
-            // to lose conversions of generic types.
-            Class<?> targetType = toValueType.getRawClass();
-            if (targetType != Object.class
-                    && !toValueType.hasGenericTypes()
-                    && targetType.isAssignableFrom(fromValue.getClass())) {
-                return fromValue;
-            }
-        }
+        // 25-Jan-2019, tatu: [databind#2220] Let's NOT try to short-circuit anything
         
         // Then use TokenBuffer, which is a JsonGenerator:
         TokenBuffer buf = new TokenBuffer(this, false);
@@ -3877,6 +4064,23 @@
 
     /*
     /**********************************************************
+    /* Internal factory methods for type ids, overridable
+    /**********************************************************
+     */
+
+    /**
+     * Overridable factory method, separate to allow format-specific mappers (and specifically
+     * XML-backed one, currently) to offer custom {@link TypeResolverBuilder} subtypes.
+     *
+     * @since 2.10
+     */
+    protected TypeResolverBuilder<?> _constructDefaultTypeResolverBuilder(DefaultTyping applicability,
+            PolymorphicTypeValidator ptv) {
+        return DefaultTypeResolverBuilder.construct(applicability, ptv);
+    }
+
+    /*
+    /**********************************************************
     /* Internal methods for serialization, overridable
     /**********************************************************
      */
@@ -4031,7 +4235,7 @@
     protected JsonNode _readTreeAndClose(JsonParser p0) throws IOException
     {
         try (JsonParser p = p0) {
-            final JavaType valueType = JSON_NODE_TYPE;
+            final JavaType valueType = constructType(JsonNode.class);
 
             DeserializationConfig cfg = getDeserializationConfig();
             // 27-Oct-2016, tatu: Need to inline `_initForReading()` due to
@@ -4041,27 +4245,37 @@
             JsonToken t = p.getCurrentToken();
             if (t == null) {
                 t = p.nextToken();
-                if (t == null) { // [databind#1406]: expose end-of-input as `null`
-                    return null;
+                if (t == null) {
+                    // [databind#2211]: return `MissingNode` (supercedes [databind#1406] which dictated
+                    // returning `null`
+                    return cfg.getNodeFactory().missingNode();
                 }
             }
+            final boolean checkTrailing = cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
+            DeserializationContext ctxt;
+            JsonNode resultNode;
+
             if (t == JsonToken.VALUE_NULL) {
-                return cfg.getNodeFactory().nullNode();
-            }
-            DeserializationContext ctxt = createDeserializationContext(p, cfg);
-            JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
-            Object result;
-            if (cfg.useRootWrapping()) {
-                result = _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser);
-            } else {
-                result = deser.deserialize(p, ctxt);
-                if (cfg.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {
-                    _verifyNoTrailingTokens(p, ctxt, valueType);
+                resultNode = cfg.getNodeFactory().nullNode();
+                if (!checkTrailing) {
+                    return resultNode;
                 }
+                ctxt = createDeserializationContext(p, cfg);
+            } else {
+                ctxt = createDeserializationContext(p, cfg);
+                JsonDeserializer<Object> deser = _findRootDeserializer(ctxt, valueType);
+                if (cfg.useRootWrapping()) {
+                    resultNode = (JsonNode) _unwrapAndDeserialize(p, ctxt, cfg, valueType, deser);
+                } else {
+                    resultNode = (JsonNode) deser.deserialize(p, ctxt);
+                }
+            }
+            if (checkTrailing) {
+                _verifyNoTrailingTokens(p, ctxt, valueType);
             }
             // No ObjectIds so can ignore
 //            ctxt.checkUnresolvedObjectId();
-            return (JsonNode) result;
+            return resultNode;
         }
     }
 
@@ -4085,7 +4299,7 @@
         }
         String actualName = p.getCurrentName();
         if (!expSimpleName.equals(actualName)) {
-            ctxt.reportInputMismatch(rootType,
+            ctxt.reportPropertyInputMismatch(rootType, actualName,
                     "Root name '%s' does not match expected ('%s') for type %s",
                     actualName, expSimpleName, rootType);
         }
@@ -4209,4 +4423,10 @@
             }
         }
     }
+
+    protected final void _assertNotNull(String paramName, Object src) {
+        if (src == null) {
+            throw new IllegalArgumentException(String.format("argument \"%s\" is null", paramName));
+        }
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java b/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java
index d313c42..3fe8ed7 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectReader.java
@@ -18,7 +18,6 @@
 import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.node.TreeTraversingParser;
-import com.fasterxml.jackson.databind.type.SimpleType;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 
@@ -46,8 +45,6 @@
 {
     private static final long serialVersionUID = 2L; // since 2.9
 
-    private final static JavaType JSON_NODE_TYPE = SimpleType.constructUnsafe(JsonNode.class);
-
     /*
     /**********************************************************
     /* Immutable configuration from ObjectMapper
@@ -155,6 +152,11 @@
      */
     final protected ConcurrentHashMap<JavaType, JsonDeserializer<Object>> _rootDeserializers;
 
+    /**
+     * Lazily resolved {@link JavaType} for {@link JsonNode}
+     */
+    protected transient JavaType _jsonNodeType;
+    
     /*
     /**********************************************************
     /* Life-cycle, construction
@@ -532,8 +534,9 @@
      * {@link JsonPointerBasedFilter} is registered and will be used for parsing later. 
      * @since 2.6
      */
-    public ObjectReader at(final String value) {
-        return new ObjectReader(this, new JsonPointerBasedFilter(value));
+    public ObjectReader at(final String pointerExpr) {
+        _assertNotNull("pointerExpr", pointerExpr);
+        return new ObjectReader(this, new JsonPointerBasedFilter(pointerExpr));
     }
 
     /**
@@ -542,6 +545,7 @@
      * @since 2.6
      */
     public ObjectReader at(final JsonPointer pointer) {
+        _assertNotNull("pointer", pointer);
         return new ObjectReader(this, new JsonPointerBasedFilter(pointer));
     }
 
@@ -907,7 +911,7 @@
     }
 
     public boolean isEnabled(JsonParser.Feature f) {
-        return _parserFactory.isEnabled(f);
+        return _config.isEnabled(f, _parserFactory);
     }
 
     /**
@@ -943,6 +947,13 @@
         return _injectableValues;
     }
 
+    /**
+     * @since 2.10
+     */
+    public JavaType getValueType() {
+        return _valueType;
+    }
+
     /*
     /**********************************************************
     /* Deserialization methods; basic ones to support ObjectCodec first
@@ -962,6 +973,7 @@
     @SuppressWarnings("unchecked")
     public <T> T readValue(JsonParser p) throws IOException
     {
+        _assertNotNull("p", p);
         return (T) _bind(p, _valueToUpdate);
     }
 
@@ -979,6 +991,7 @@
     @Override
     public <T> T readValue(JsonParser p, Class<T> valueType) throws IOException
     {
+        _assertNotNull("p", p);
         return (T) forType(valueType).readValue(p);
     }
 
@@ -994,8 +1007,9 @@
      */
     @SuppressWarnings("unchecked")
     @Override
-    public <T> T readValue(JsonParser p, TypeReference<?> valueTypeRef) throws IOException
+    public <T> T readValue(JsonParser p, TypeReference<T> valueTypeRef) throws IOException
     {
+        _assertNotNull("p", p);
         return (T) forType(valueTypeRef).readValue(p);
     }
 
@@ -1012,6 +1026,7 @@
     @Override
     @SuppressWarnings("unchecked")
     public <T> T readValue(JsonParser p, ResolvedType valueType) throws IOException {
+        _assertNotNull("p", p);
         return (T) forType((JavaType)valueType).readValue(p);
     }
 
@@ -1023,6 +1038,7 @@
      */
     @SuppressWarnings("unchecked")
     public <T> T readValue(JsonParser p, JavaType valueType) throws IOException {
+        _assertNotNull("p", p);
         return (T) forType(valueType).readValue(p);
     }
 
@@ -1047,6 +1063,7 @@
      */
     @Override
     public <T> Iterator<T> readValues(JsonParser p, Class<T> valueType) throws IOException {
+        _assertNotNull("p", p);
         return forType(valueType).readValues(p);
     }
 
@@ -1070,10 +1087,11 @@
      * (data-format specific) parser is given.
      */
     @Override
-    public <T> Iterator<T> readValues(JsonParser p, TypeReference<?> valueTypeRef) throws IOException {
+    public <T> Iterator<T> readValues(JsonParser p, TypeReference<T> valueTypeRef) throws IOException {
+        _assertNotNull("p", p);
         return forType(valueTypeRef).readValues(p);
     }
-    
+
     /**
      * Convenience method that is equivalent to:
      *<pre>
@@ -1095,6 +1113,7 @@
      */
     @Override
     public <T> Iterator<T> readValues(JsonParser p, ResolvedType valueType) throws IOException {
+        _assertNotNull("p", p);
         return readValues(p, (JavaType) valueType);
     }
 
@@ -1118,6 +1137,7 @@
      * (data-format specific) parser is given.
      */
     public <T> Iterator<T> readValues(JsonParser p, JavaType valueType) throws IOException {
+        _assertNotNull("p", p);
         return forType(valueType).readValues(p);
     }
 
@@ -1137,8 +1157,19 @@
         return _config.getNodeFactory().objectNode();
     }
 
+    @Override // since 2.10
+    public JsonNode missingNode() {
+        return _config.getNodeFactory().missingNode();
+    }
+
+    @Override // since 2.10
+    public JsonNode nullNode() {
+        return _config.getNodeFactory().nullNode();
+    }
+
     @Override
     public JsonParser treeAsTokens(TreeNode n) {
+        _assertNotNull("n", n);
         // 05-Dec-2017, tatu: Important! Must clear "valueToUpdate" since we do not
         //    want update to be applied here, as a side effect
         ObjectReader codec = withValueToUpdate(null);
@@ -1149,6 +1180,13 @@
      * Convenience method that binds content read using given parser, using
      * configuration of this reader, except that content is bound as
      * JSON tree instead of configured root value type.
+     * Returns {@link JsonNode} that represents the root of the resulting tree, if there
+     * was content to read, or {@code null} if no more content is accessible
+     * via passed {@link JsonParser}.
+     *<p>
+     * NOTE! Behavior with end-of-input (no more content) differs between this
+     * {@code readTree} method, and all other methods that take input source: latter
+     * will return "missing node", NOT {@code null}
      *<p>
      * Note: if an object was specified with {@link #withValueToUpdate}, it
      * will be ignored.
@@ -1159,14 +1197,15 @@
     @SuppressWarnings("unchecked")
     @Override
     public <T extends TreeNode> T readTree(JsonParser p) throws IOException {
-        return (T) _bindAsTree(p);
+        _assertNotNull("p", p);
+        return (T) _bindAsTreeOrNull(p);
     }
-     
+
     @Override
     public void writeTree(JsonGenerator g, TreeNode rootNode) {
         throw new UnsupportedOperationException();
     }
-    
+
     /*
     /**********************************************************
     /* Deserialization methods; others similar to what ObjectMapper has
@@ -1182,6 +1221,7 @@
     @SuppressWarnings("unchecked")
     public <T> T readValue(InputStream src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             return (T) _detectBindAndClose(_dataFormatReaders.findFormat(src), false);
         }
@@ -1197,6 +1237,7 @@
     @SuppressWarnings("unchecked")
     public <T> T readValue(Reader src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             _reportUndetectableSource(src);
         }
@@ -1210,13 +1251,19 @@
      * was specified with {@link #withValueToUpdate(Object)}.
      */
     @SuppressWarnings("unchecked")
-    public <T> T readValue(String src) throws IOException
+    public <T> T readValue(String src) throws JsonProcessingException, JsonMappingException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             _reportUndetectableSource(src);
         }
-        
-        return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src), false));
+        try { // since 2.10 remove "impossible" IOException as per [databind#1675]
+            return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src), false));
+        } catch (JsonProcessingException e) {
+            throw e;
+        } catch (IOException e) { // shouldn't really happen but being declared need to
+            throw JsonMappingException.fromUnexpectedIOE(e);
+        }
     }
 
     /**
@@ -1228,6 +1275,7 @@
     @SuppressWarnings("unchecked")
     public <T> T readValue(byte[] src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             return (T) _detectBindAndClose(src, 0, src.length);
         }
@@ -1241,9 +1289,9 @@
      * was specified with {@link #withValueToUpdate(Object)}.
      */
     @SuppressWarnings("unchecked")
-    public <T> T readValue(byte[] src, int offset, int length)
-        throws IOException
+    public <T> T readValue(byte[] src, int offset, int length) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             return (T) _detectBindAndClose(src, offset, length);
         }
@@ -1252,9 +1300,9 @@
     }
     
     @SuppressWarnings("unchecked")
-    public <T> T readValue(File src)
-        throws IOException
+    public <T> T readValue(File src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             return (T) _detectBindAndClose(_dataFormatReaders.findFormat(_inputStream(src)), true);
         }
@@ -1267,11 +1315,18 @@
      * using configuration of this reader.
      * Value return is either newly constructed, or root value that
      * was specified with {@link #withValueToUpdate(Object)}.
+     *<p>
+     *<p>
+     * NOTE: handling of {@link java.net.URL} is delegated to
+     * {@link JsonFactory#createParser(java.net.URL)} and usually simply
+     * calls {@link java.net.URL#openStream()}, meaning no special handling
+     * is done. If different HTTP connection options are needed you will need
+     * to create {@link java.io.InputStream} separately.
      */
     @SuppressWarnings("unchecked")
-    public <T> T readValue(URL src)
-        throws IOException
+    public <T> T readValue(URL src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             return (T) _detectBindAndClose(_dataFormatReaders.findFormat(_inputStream(src)), true);
         }
@@ -1286,9 +1341,9 @@
      *</pre>
      */
     @SuppressWarnings({ "unchecked", "resource" })
-    public <T> T readValue(JsonNode src)
-        throws IOException
+    public <T> T readValue(JsonNode src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             _reportUndetectableSource(src);
         }
@@ -1301,65 +1356,110 @@
     @SuppressWarnings("unchecked")
     public <T> T readValue(DataInput src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             _reportUndetectableSource(src);
         }
         return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src), false));
     }
 
-    /**
-     * Method that reads content from given input source,
-     * using configuration of this reader, and binds it as JSON Tree.
-     *<p>
-     * Note that if an object was specified with a call to
-     * {@link #withValueToUpdate(Object)}
-     * it will just be ignored; result is always a newly constructed
-     * {@link JsonNode} instance.
+    /*
+    /**********************************************************
+    /* Deserialization methods; JsonNode ("tree")
+    /**********************************************************
      */
-    public JsonNode readTree(InputStream in) throws IOException
-    {
-        if (_dataFormatReaders != null) {
-            return _detectBindAndCloseAsTree(in);
-        }
-        return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(in), false));
-    }
     
     /**
      * Method that reads content from given input source,
      * using configuration of this reader, and binds it as JSON Tree.
+     * Returns {@link JsonNode} that represents the root of the resulting tree, if there
+     * was content to read, or "missing node" (instance of {@link JsonNode} for which
+     * {@link JsonNode#isMissingNode()} returns true, and behaves otherwise similar to
+     * "null node") if no more content is accessible through passed-in input source.
+     *<p>
+     * NOTE! Behavior with end-of-input (no more content) differs between this
+     * {@code readTree} method, and {@link #readTree(JsonParser)} -- latter returns
+     * {@code null} for "no content" case.
      *<p>
      * Note that if an object was specified with a call to
      * {@link #withValueToUpdate(Object)}
      * it will just be ignored; result is always a newly constructed
      * {@link JsonNode} instance.
      */
-    public JsonNode readTree(Reader r) throws IOException
+    public JsonNode readTree(InputStream src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
-            _reportUndetectableSource(r);
+            return _detectBindAndCloseAsTree(src);
         }
-        return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(r), false));
+        return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(src), false));
+    }
+    
+    /**
+     * Same as {@link #readTree(InputStream)} except content accessed through
+     * passed-in {@link Reader}
+     */
+    public JsonNode readTree(Reader src) throws IOException
+    {
+        _assertNotNull("src", src);
+        if (_dataFormatReaders != null) {
+            _reportUndetectableSource(src);
+        }
+        return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(src), false));
     }
 
     /**
-     * Method that reads content from given JSON input String,
-     * using configuration of this reader, and binds it as JSON Tree.
-     *<p>
-     * Note that if an object was specified with a call to
-     * {@link #withValueToUpdate(Object)}
-     * it will just be ignored; result is always a newly constructed
-     * {@link JsonNode} instance.
+     * Same as {@link #readTree(InputStream)} except content read from
+     * passed-in {@link String}
      */
-    public JsonNode readTree(String json) throws IOException
+    public JsonNode readTree(String json) throws JsonProcessingException, JsonMappingException
     {
+        _assertNotNull("json", json);
+        if (_dataFormatReaders != null) {
+            _reportUndetectableSource(json);
+        }
+        try { // since 2.10 remove "impossible" IOException as per [databind#1675]
+            return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(json), false));
+        } catch (JsonProcessingException e) {
+            throw e;
+        } catch (IOException e) { // shouldn't really happen but being declared need to
+            throw JsonMappingException.fromUnexpectedIOE(e);
+        }
+    }
+
+    /**
+     * Same as {@link #readTree(InputStream)} except content read from
+     * passed-in byte array.
+     */
+    public JsonNode readTree(byte[] json) throws IOException
+    {
+        _assertNotNull("json", json);
         if (_dataFormatReaders != null) {
             _reportUndetectableSource(json);
         }
         return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(json), false));
     }
+    
+    /**
+     * Same as {@link #readTree(InputStream)} except content read from
+     * passed-in byte array.
+     */
+    public JsonNode readTree(byte[] json, int offset, int len) throws IOException
+    {
+        _assertNotNull("json", json);
+        if (_dataFormatReaders != null) {
+            _reportUndetectableSource(json);
+        }
+        return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(json, offset, len), false));
+    }
 
+    /**
+     * Same as {@link #readTree(InputStream)} except content read using
+     * passed-in {@link DataInput}.
+     */
     public JsonNode readTree(DataInput src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             _reportUndetectableSource(src);
         }
@@ -1383,9 +1483,9 @@
      * parser MUST NOT point to the surrounding <code>START_ARRAY</code> but rather
      * to the token following it.
      */
-    public <T> MappingIterator<T> readValues(JsonParser p)
-        throws IOException
+    public <T> MappingIterator<T> readValues(JsonParser p) throws IOException
     {
+        _assertNotNull("p", p);
         DeserializationContext ctxt = createDeserializationContext(p);
         // false -> do not close as caller gave parser instance
         return _newIterator(p, ctxt, _findRootDeserializer(ctxt), false);
@@ -1411,9 +1511,9 @@
      * points to the first token of the first element (i.e. the second
      * <code>START_ARRAY</code> which is part of the first element).
      */
-    public <T> MappingIterator<T> readValues(InputStream src)
-        throws IOException
+    public <T> MappingIterator<T> readValues(InputStream src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             return _detectBindAndReadValues(_dataFormatReaders.findFormat(src), false);
         }
@@ -1425,9 +1525,9 @@
      * Overloaded version of {@link #readValue(InputStream)}.
      */
     @SuppressWarnings("resource")
-    public <T> MappingIterator<T> readValues(Reader src)
-        throws IOException
+    public <T> MappingIterator<T> readValues(Reader src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             _reportUndetectableSource(src);
         }
@@ -1444,9 +1544,9 @@
      * @param json String that contains JSON content to parse
      */
     @SuppressWarnings("resource")
-    public <T> MappingIterator<T> readValues(String json)
-        throws IOException
+    public <T> MappingIterator<T> readValues(String json) throws IOException
     {
+        _assertNotNull("json", json);
         if (_dataFormatReaders != null) {
             _reportUndetectableSource(json);
         }
@@ -1460,9 +1560,9 @@
     /**
      * Overloaded version of {@link #readValue(InputStream)}.
      */
-    public <T> MappingIterator<T> readValues(byte[] src, int offset, int length)
-        throws IOException
+    public <T> MappingIterator<T> readValues(byte[] src, int offset, int length) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             return _detectBindAndReadValues(_dataFormatReaders.findFormat(src, offset, length), false);
         }
@@ -1473,17 +1573,17 @@
     /**
      * Overloaded version of {@link #readValue(InputStream)}.
      */
-    public final <T> MappingIterator<T> readValues(byte[] src)
-            throws IOException {
+    public final <T> MappingIterator<T> readValues(byte[] src) throws IOException {
+        _assertNotNull("src", src);
         return readValues(src, 0, src.length);
     }
     
     /**
      * Overloaded version of {@link #readValue(InputStream)}.
      */
-    public <T> MappingIterator<T> readValues(File src)
-        throws IOException
+    public <T> MappingIterator<T> readValues(File src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             return _detectBindAndReadValues(
                     _dataFormatReaders.findFormat(_inputStream(src)), false);
@@ -1493,12 +1593,18 @@
 
     /**
      * Overloaded version of {@link #readValue(InputStream)}.
+     *<p>
+     * NOTE: handling of {@link java.net.URL} is delegated to
+     * {@link JsonFactory#createParser(java.net.URL)} and usually simply
+     * calls {@link java.net.URL#openStream()}, meaning no special handling
+     * is done. If different HTTP connection options are needed you will need
+     * to create {@link java.io.InputStream} separately.
      * 
      * @param src URL to read to access JSON content to parse.
      */
-    public <T> MappingIterator<T> readValues(URL src)
-        throws IOException
+    public <T> MappingIterator<T> readValues(URL src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             return _detectBindAndReadValues(
                     _dataFormatReaders.findFormat(_inputStream(src)), true);
@@ -1511,6 +1617,7 @@
      */
     public <T> MappingIterator<T> readValues(DataInput src) throws IOException
     {
+        _assertNotNull("src", src);
         if (_dataFormatReaders != null) {
             _reportUndetectableSource(src);
         }
@@ -1526,6 +1633,7 @@
     @Override
     public <T> T treeToValue(TreeNode n, Class<T> valueType) throws JsonProcessingException
     {
+        _assertNotNull("n", n);
         try {
             return readValue(treeAsTokens(n), valueType);
         } catch (JsonProcessingException e) {
@@ -1630,9 +1738,7 @@
 
     protected final JsonNode _bindAsTree(JsonParser p) throws IOException
     {
-        // 27-Oct-2016, tatu: Need to inline `_initForReading()` due to
-        //   special requirements by tree reading (no fail on eof)
-        
+        // Need to inline `_initForReading()` due to tree reading handling end-of-input specially
         _config.initialize(p);
         if (_schema != null) {
             p.setSchema(_schema);
@@ -1641,27 +1747,76 @@
         JsonToken t = p.getCurrentToken();
         if (t == null) {
             t = p.nextToken();
-            if (t == null) { // [databind#1406]: expose end-of-input as `null`
+            if (t == null) {
+                return _config.getNodeFactory().missingNode();
+            }
+        }
+        final DeserializationContext ctxt;
+        final JsonNode resultNode;
+        final boolean checkTrailing = _config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
+
+        if (t == JsonToken.VALUE_NULL) {
+            resultNode = _config.getNodeFactory().nullNode();
+            if (!checkTrailing) {
+                return resultNode;
+            }
+            ctxt = createDeserializationContext(p);
+        } else {
+            ctxt = createDeserializationContext(p);
+            final JsonDeserializer<Object> deser = _findTreeDeserializer(ctxt);
+            if (_unwrapRoot) {
+                resultNode = (JsonNode) _unwrapAndDeserialize(p, ctxt, _jsonNodeType(), deser);
+            } else {
+                resultNode = (JsonNode) deser.deserialize(p, ctxt);
+            }
+        }
+        if (_config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {
+            _verifyNoTrailingTokens(p, ctxt, _jsonNodeType());
+        }
+        return resultNode;
+    }
+
+    /**
+     * Same as {@link #_bindAsTree} except end-of-input is reported by returning
+     * {@code null}, not "missing node"
+     */
+    protected final JsonNode _bindAsTreeOrNull(JsonParser p) throws IOException
+    {
+        _config.initialize(p);
+        if (_schema != null) {
+            p.setSchema(_schema);
+        }
+        JsonToken t = p.getCurrentToken();
+        if (t == null) {
+            t = p.nextToken();
+            if (t == null) {
                 return null;
             }
         }
-        DeserializationContext ctxt = createDeserializationContext(p);
+        final DeserializationContext ctxt;
+        final JsonNode resultNode;
+        final boolean checkTrailing = _config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
         if (t == JsonToken.VALUE_NULL) {
-            return ctxt.getNodeFactory().nullNode();
-        }
-        JsonDeserializer<Object> deser = _findTreeDeserializer(ctxt);
-        Object result;
-        if (_unwrapRoot) {
-            result = _unwrapAndDeserialize(p, ctxt, JSON_NODE_TYPE, deser);
+            resultNode = _config.getNodeFactory().nullNode();
+            if (!checkTrailing) {
+                return resultNode;
+            }
+            ctxt = createDeserializationContext(p);
         } else {
-            result = deser.deserialize(p, ctxt);
-            if (_config.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS)) {
-                _verifyNoTrailingTokens(p, ctxt, JSON_NODE_TYPE);
+            ctxt = createDeserializationContext(p);
+            final JsonDeserializer<Object> deser = _findTreeDeserializer(ctxt);
+            if (_unwrapRoot) {
+                resultNode = (JsonNode) _unwrapAndDeserialize(p, ctxt, _jsonNodeType(), deser);
+            } else {
+                resultNode = (JsonNode) deser.deserialize(p, ctxt);
             }
         }
-        return (JsonNode) result;
+        if (checkTrailing) {
+            _verifyNoTrailingTokens(p, ctxt, _jsonNodeType());
+        }
+        return resultNode;
     }
-
+    
     /**
      * @since 2.1
      */
@@ -1692,7 +1847,7 @@
         }
         String actualName = p.getCurrentName();
         if (!expSimpleName.equals(actualName)) {
-            ctxt.reportInputMismatch(rootType,
+            ctxt.reportPropertyInputMismatch(rootType, actualName,
                     "Root name '%s' does not match expected ('%s') for type %s",
                     actualName, expSimpleName, rootType);
         }
@@ -1763,7 +1918,7 @@
         return match.getReader()._bindAndClose(p);
     }
 
-    @SuppressWarnings("resource")
+    @SuppressWarnings({ "resource" })
     protected Object _detectBindAndClose(DataFormatReaders.Match match, boolean forceClosing)
         throws IOException
     {
@@ -1780,7 +1935,7 @@
         return match.getReader()._bindAndClose(p);
     }
 
-    @SuppressWarnings("resource")
+    @SuppressWarnings({ "resource" })
     protected <T> MappingIterator<T> _detectBindAndReadValues(DataFormatReaders.Match match, boolean forceClosing)
         throws IOException
     {
@@ -1797,7 +1952,7 @@
         return match.getReader()._bindAndReadValues(p);
     }
     
-    @SuppressWarnings("resource")
+    @SuppressWarnings({ "resource" })
     protected JsonNode _detectBindAndCloseAsTree(InputStream in) throws IOException
     {
         DataFormatReaders.Match match = _dataFormatReaders.findFormat(in);
@@ -1857,7 +2012,7 @@
         return new FileInputStream(f);
     }
 
-    protected void _reportUndetectableSource(Object src) throws JsonProcessingException
+    protected void _reportUndetectableSource(Object src) throws JsonParseException
     {
         // 17-Aug-2015, tatu: Unfortunately, no parser/generator available so:
         throw new JsonParseException(null, "Cannot use source of type "
@@ -1906,15 +2061,16 @@
     protected JsonDeserializer<Object> _findTreeDeserializer(DeserializationContext ctxt)
         throws JsonMappingException
     {
-        JsonDeserializer<Object> deser = _rootDeserializers.get(JSON_NODE_TYPE);
+        final JavaType nodeType = _jsonNodeType();
+        JsonDeserializer<Object> deser = _rootDeserializers.get(nodeType);
         if (deser == null) {
             // Nope: need to ask provider to resolve it
-            deser = ctxt.findRootValueDeserializer(JSON_NODE_TYPE);
+            deser = ctxt.findRootValueDeserializer(nodeType);
             if (deser == null) { // can this happen?
-                ctxt.reportBadDefinition(JSON_NODE_TYPE,
-                        "Cannot find a deserializer for type "+JSON_NODE_TYPE);
+                ctxt.reportBadDefinition(nodeType,
+                        "Cannot find a deserializer for type "+nodeType);
             }
-            _rootDeserializers.put(JSON_NODE_TYPE, deser);
+            _rootDeserializers.put(nodeType, deser);
         }
         return deser;
     }
@@ -1946,4 +2102,22 @@
         }
         return deser;
     }
+
+    /**
+     * @since 2.10
+     */
+    protected final JavaType _jsonNodeType() {
+        JavaType t = _jsonNodeType;
+        if (t == null) {
+            t = getTypeFactory().constructType(JsonNode.class);
+            _jsonNodeType = t;
+        }
+        return t;
+    }
+
+    protected final void _assertNotNull(String paramName, Object src) {
+        if (src == null) {
+            throw new IllegalArgumentException(String.format("argument \"%s\" is null", paramName));
+        }
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java b/src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java
index 5098612..831834e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java
@@ -104,12 +104,14 @@
         _generatorSettings = (pp == null) ? GeneratorSettings.empty
                 : new GeneratorSettings(pp, null, null, null);
 
-        // 29-Apr-2014, tatu: There is no "untyped serializer", so:
-        if (rootType == null || rootType.hasRawClass(Object.class)) {
+        if (rootType == null) {
             _prefetch = Prefetch.empty;
-        } else {
-            rootType = rootType.withStaticTyping();
+        } else if (rootType.hasRawClass(Object.class)) {
+            // 15-Sep-2019, tatu: There is no "untyped serializer", but...
+            //     as per [databind#1093] we do need `TypeSerializer`
             _prefetch = Prefetch.empty.forRootType(this, rootType);
+        } else {
+            _prefetch = Prefetch.empty.forRootType(this, rootType.withStaticTyping());
         }
     }
 
@@ -202,11 +204,9 @@
     }
 
     /*
-    /**********************************************************
-    /* Methods sub-classes MUST override, used for constructing
-    /* writer instances, (re)configuring parser instances.
-    /* Added in 2.5
-    /**********************************************************
+    /**********************************************************************
+    /* Internal factory methods, for convenience
+    /**********************************************************************
      */
 
     /**
@@ -411,9 +411,6 @@
      * @since 2.5
      */
     public ObjectWriter forType(Class<?> rootType) {
-        if (rootType == Object.class) {
-            return forType((JavaType) null);
-        }
         return forType(_config.constructType(rootType));
     }
 
@@ -662,6 +659,7 @@
      * @since 2.5
      */
     public SequenceWriter writeValues(File out) throws IOException {
+        _assertNotNull("out", out);
         return _newSequenceWriter(false,
                 _generatorFactory.createGenerator(out, JsonEncoding.UTF8), true);
     }
@@ -676,14 +674,15 @@
      * the generator. However, since a {@link JsonGenerator} is explicitly passed,
      * it will NOT be closed when {@link SequenceWriter#close()} is called.
      *
-     * @param gen Low-level generator caller has already constructed that will
+     * @param g Low-level generator caller has already constructed that will
      *   be used for actual writing of token stream.
      *
      * @since 2.5
      */
-    public SequenceWriter writeValues(JsonGenerator gen) throws IOException {
-        _configureGenerator(gen);
-        return _newSequenceWriter(false, gen, false);
+    public SequenceWriter writeValues(JsonGenerator g) throws IOException {
+        _assertNotNull("g", g);
+        _configureGenerator(g);
+        return _newSequenceWriter(false, g, false);
     }
 
     /**
@@ -700,6 +699,7 @@
      * @since 2.5
      */
     public SequenceWriter writeValues(Writer out) throws IOException {
+        _assertNotNull("out", out);
         return _newSequenceWriter(false,
                 _generatorFactory.createGenerator(out), true);
     }
@@ -718,6 +718,7 @@
      * @since 2.5
      */
     public SequenceWriter writeValues(OutputStream out) throws IOException {
+        _assertNotNull("out", out);
         return _newSequenceWriter(false,
                 _generatorFactory.createGenerator(out, JsonEncoding.UTF8), true);
     }
@@ -726,6 +727,7 @@
      * @since 2.8
      */
     public SequenceWriter writeValues(DataOutput out) throws IOException {
+        _assertNotNull("out", out);
         return _newSequenceWriter(false,
                 _generatorFactory.createGenerator(out), true);
     }
@@ -746,6 +748,7 @@
      * @since 2.5
      */
     public SequenceWriter writeValuesAsArray(File out) throws IOException {
+        _assertNotNull("out", out);
         return _newSequenceWriter(true,
                 _generatorFactory.createGenerator(out, JsonEncoding.UTF8), true);
     }
@@ -767,6 +770,7 @@
      * @since 2.5
      */
     public SequenceWriter writeValuesAsArray(JsonGenerator gen) throws IOException {
+        _assertNotNull("gen", gen);
         return _newSequenceWriter(true, gen, false);
     }
 
@@ -786,6 +790,7 @@
      * @since 2.5
      */
     public SequenceWriter writeValuesAsArray(Writer out) throws IOException {
+        _assertNotNull("out", out);
         return _newSequenceWriter(true, _generatorFactory.createGenerator(out), true);
     }
 
@@ -805,6 +810,7 @@
      * @since 2.5
      */
     public SequenceWriter writeValuesAsArray(OutputStream out) throws IOException {
+        _assertNotNull("out", out);
         return _newSequenceWriter(true,
                 _generatorFactory.createGenerator(out, JsonEncoding.UTF8), true);
     }
@@ -813,6 +819,7 @@
      * @since 2.8
      */
     public SequenceWriter writeValuesAsArray(DataOutput out) throws IOException {
+        _assertNotNull("out", out);
         return _newSequenceWriter(true, _generatorFactory.createGenerator(out), true);
     }
 
@@ -892,17 +899,18 @@
      * Method that can be used to serialize any Java value as
      * JSON output, using provided {@link JsonGenerator}.
      */
-    public void writeValue(JsonGenerator gen, Object value) throws IOException
+    public void writeValue(JsonGenerator g, Object value) throws IOException
     {
-        _configureGenerator(gen);
+        _assertNotNull("g", g);
+        _configureGenerator(g);
         if (_config.isEnabled(SerializationFeature.CLOSE_CLOSEABLE)
                 && (value instanceof Closeable)) {
 
             Closeable toClose = (Closeable) value;
             try {
-                _prefetch.serialize(gen, value, _serializerProvider());
+                _prefetch.serialize(g, value, _serializerProvider());
                 if (_config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
-                    gen.flush();
+                    g.flush();
                 }
             } catch (Exception e) {
                 ClassUtil.closeOnFailAndThrowAsIOE(null, toClose, e);
@@ -910,9 +918,9 @@
             }
             toClose.close();
         } else {
-            _prefetch.serialize(gen, value, _serializerProvider());
+            _prefetch.serialize(g, value, _serializerProvider());
             if (_config.isEnabled(SerializationFeature.FLUSH_AFTER_WRITE_VALUE)) {
-                gen.flush();
+                g.flush();
             }
         }
     }
@@ -930,6 +938,7 @@
     public void writeValue(File resultFile, Object value)
         throws IOException, JsonGenerationException, JsonMappingException
     {
+        _assertNotNull("resultFile", resultFile);
         _configAndWriteValue(_generatorFactory.createGenerator(resultFile, JsonEncoding.UTF8), value);
     }
 
@@ -947,6 +956,7 @@
     public void writeValue(OutputStream out, Object value)
         throws IOException, JsonGenerationException, JsonMappingException
     {
+        _assertNotNull("out", out);
         _configAndWriteValue(_generatorFactory.createGenerator(out, JsonEncoding.UTF8), value);
     }
 
@@ -963,6 +973,7 @@
     public void writeValue(Writer w, Object value)
         throws IOException, JsonGenerationException, JsonMappingException
     {
+        _assertNotNull("w", w);
         _configAndWriteValue(_generatorFactory.createGenerator(w), value);
     }
 
@@ -972,6 +983,7 @@
     public void writeValue(DataOutput out, Object value)
         throws IOException
     {
+        _assertNotNull("out", out);
         _configAndWriteValue(_generatorFactory.createGenerator(out), value);
     }
 
@@ -1045,20 +1057,22 @@
      */
     public void acceptJsonFormatVisitor(JavaType type, JsonFormatVisitorWrapper visitor) throws JsonMappingException
     {
-        if (type == null) {
-            throw new IllegalArgumentException("type must be provided");
-        }
+        _assertNotNull("type", type);
+        _assertNotNull("visitor", visitor);
         _serializerProvider().acceptJsonFormatVisitor(type, visitor);
     }
 
     /**
      * Since 2.6
      */
-    public void acceptJsonFormatVisitor(Class<?> rawType, JsonFormatVisitorWrapper visitor) throws JsonMappingException {
-        acceptJsonFormatVisitor(_config.constructType(rawType), visitor);
+    public void acceptJsonFormatVisitor(Class<?> type, JsonFormatVisitorWrapper visitor) throws JsonMappingException {
+        _assertNotNull("type", type);
+        _assertNotNull("visitor", visitor);
+        acceptJsonFormatVisitor(_config.constructType(type), visitor);
     }
 
     public boolean canSerialize(Class<?> type) {
+        _assertNotNull("type", type);
         return _serializerProvider().hasSerializerFor(type, null);
     }
 
@@ -1069,6 +1083,7 @@
      * @since 2.3
      */
     public boolean canSerialize(Class<?> type, AtomicReference<Throwable> cause) {
+        _assertNotNull("type", type);
         return _serializerProvider().hasSerializerFor(type, cause);
     }
 
@@ -1159,6 +1174,12 @@
         _generatorSettings.initialize(gen);
     }
 
+    protected final void _assertNotNull(String paramName, Object src) {
+        if (src == null) {
+            throw new IllegalArgumentException(String.format("argument \"%s\" is null", paramName));
+        }
+    }
+    
     /*
     /**********************************************************
     /* Helper classes for configuration
@@ -1336,19 +1357,35 @@
         }
 
         public Prefetch forRootType(ObjectWriter parent, JavaType newType) {
-            // First: if nominal type not defined, or trivial (java.lang.Object),
-            // not thing much to do
-            boolean noType = (newType == null) || newType.isJavaLangObject();
-
-            if (noType) {
+            // First: if nominal type not defined not thing much to do
+            if (newType == null) {
                 if ((rootType == null) || (valueSerializer == null)) {
                     return this;
                 }
-                return new Prefetch(null, null, typeSerializer);
+                return new Prefetch(null, null, null);
             }
+
+            // Second: if no change, nothing to do either
             if (newType.equals(rootType)) {
                 return this;
             }
+
+            // But one more trick: `java.lang.Object` has no serialized, but may
+            // have `TypeSerializer` to use
+            if (newType.isJavaLangObject()) {
+                DefaultSerializerProvider prov = parent._serializerProvider();
+                TypeSerializer typeSer;
+
+                try {
+                    typeSer = prov.findTypeSerializer(newType);
+                } catch (JsonMappingException e) {
+                    // Unlike with value serializer pre-fetch, let's not allow exception
+                    // for TypeSerializer be swallowed
+                    throw new RuntimeJsonMappingException(e);
+                }
+                return new Prefetch(null, null, typeSer);
+            }
+
             if (parent.isEnabled(SerializationFeature.EAGER_SERIALIZER_FETCH)) {
                 DefaultSerializerProvider prov = parent._serializerProvider();
                 // 17-Dec-2014, tatu: Need to be bit careful here; TypeSerializers are NOT cached,
@@ -1363,7 +1400,7 @@
                                 ((TypeWrappedSerializer) ser).typeSerializer());
                     }
                     return new Prefetch(newType, ser, null);
-                } catch (JsonProcessingException e) {
+                } catch (JsonMappingException e) {
                     // need to swallow?
                     ;
                 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategy.java b/src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategy.java
index e302426..0b5563b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategy.java
+++ b/src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategy.java
@@ -76,6 +76,15 @@
      */
     public static final PropertyNamingStrategy KEBAB_CASE = new KebabCaseStrategy();
 
+    /**
+     * Naming convention widely used as configuration properties name, where words are in
+     * lower-case letters, separated by dots.
+     * See {@link LowerDotCaseStrategy} for details.
+     *
+     * @since 2.10
+     */
+    public static final PropertyNamingStrategy LOWER_DOT_CASE = new LowerDotCaseStrategy();
+
     /*
     /**********************************************************
     /* API
@@ -194,9 +203,47 @@
         }
         
         public abstract String translate(String propertyName);
-    }
-        
+
+        /**
+         * Helper method to share implementation between snake and dotted case.
+         */
+        protected static String translateLowerCaseWithSeparator(final String input, final char separator)
+        {
+            if (input == null) {
+                return input; // garbage in, garbage out
+            }
+            final int length = input.length();
+            if (length == 0) {
+                return input;
+            }
     
+            final StringBuilder result = new StringBuilder(length + (length >> 1));
+            int upperCount = 0;
+            for (int i = 0; i < length; ++i) {
+                char ch = input.charAt(i);
+                char lc = Character.toLowerCase(ch);
+    
+                if (lc == ch) { // lower-case letter means we can get new word
+                    // but need to check for multi-letter upper-case (acronym), where assumption
+                    // is that the last upper-case char is start of a new word
+                    if (upperCount > 1) {
+                        // so insert hyphen before the last character now
+                        result.insert(result.length() - 1, separator);
+                    }
+                    upperCount = 0;
+                } else {
+                    // Otherwise starts new word, unless beginning of string
+                    if ((upperCount == 0) && (i > 0)) {
+                        result.append(separator);
+                    }
+                    ++upperCount;
+                }
+                result.append(lc);
+            }
+            return result.toString();
+        }
+    }
+
     /*
     /**********************************************************
     /* Standard implementations 
@@ -360,43 +407,24 @@
     public static class KebabCaseStrategy extends PropertyNamingStrategyBase
     {
         @Override
-        public String translate(String input)
-        {
-            if (input == null) return input; // garbage in, garbage out
-            int length = input.length();
-            if (length == 0) {
-                return input;
-            }
-
-            StringBuilder result = new StringBuilder(length + (length >> 1));
-
-            int upperCount = 0;
-
-            for (int i = 0; i < length; ++i) {
-                char ch = input.charAt(i);
-                char lc = Character.toLowerCase(ch);
-                
-                if (lc == ch) { // lower-case letter means we can get new word
-                    // but need to check for multi-letter upper-case (acronym), where assumption
-                    // is that the last upper-case char is start of a new word
-                    if (upperCount > 1) {
-                        // so insert hyphen before the last character now
-                        result.insert(result.length() - 1, '-');
-                    }
-                    upperCount = 0;
-                } else {
-                    // Otherwise starts new word, unless beginning of string
-                    if ((upperCount == 0) && (i > 0)) {
-                        result.append('-');
-                    }
-                    ++upperCount;
-                }
-                result.append(lc);
-            }
-            return result.toString();
+        public String translate(String input) {
+            return translateLowerCaseWithSeparator(input, '-');
         }
     }
-    
+
+    /**
+     * Naming strategy similar to {@link KebabCaseStrategy}, but instead of hyphens
+     * as separators, uses dots. Naming convention widely used as configuration properties name.
+     *
+     * @since 2.10
+     */
+    public static class LowerDotCaseStrategy extends PropertyNamingStrategyBase {
+        @Override
+        public String translate(String input){
+            return translateLowerCaseWithSeparator(input, '.');
+        }
+    }
+
     /*
     /**********************************************************
     /* Deprecated variants, aliases
diff --git a/src/main/java/com/fasterxml/jackson/databind/SequenceWriter.java b/src/main/java/com/fasterxml/jackson/databind/SequenceWriter.java
index 3902cf6..509ddf5 100644
--- a/src/main/java/com/fasterxml/jackson/databind/SequenceWriter.java
+++ b/src/main/java/com/fasterxml/jackson/databind/SequenceWriter.java
@@ -93,6 +93,10 @@
         _dynamicSerializers = PropertySerializerMap.emptyForRootValues();
     }
 
+    /**
+     * Internal method called by {@link ObjectWriter}: should not be called by code
+     * outside {@code jackson-databind} classes.
+     */
     public SequenceWriter init(boolean wrapInArray) throws IOException
     {
         if (wrapInArray) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/SerializationConfig.java b/src/main/java/com/fasterxml/jackson/databind/SerializationConfig.java
index eece8c6..f644837 100644
--- a/src/main/java/com/fasterxml/jackson/databind/SerializationConfig.java
+++ b/src/main/java/com/fasterxml/jackson/databind/SerializationConfig.java
@@ -5,6 +5,7 @@
 import com.fasterxml.jackson.annotation.*;
 
 import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.core.json.JsonWriteFeature;
 import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
 import com.fasterxml.jackson.core.util.Instantiatable;
 
@@ -36,6 +37,9 @@
     // since 2.6
     protected final static PrettyPrinter DEFAULT_PRETTY_PRINTER = new DefaultPrettyPrinter();
 
+    // since 2.10.1
+    private final static int SER_FEATURE_DEFAULTS = collectFeatureDefaults(SerializationFeature.class);
+
     /*
     /**********************************************************
     /* Configured helper objects
@@ -112,7 +116,7 @@
             ConfigOverrides configOverrides)
     {
         super(base, str, mixins, rootNames, configOverrides);
-        _serFeatures = collectFeatureDefaults(SerializationFeature.class);
+        _serFeatures = SER_FEATURE_DEFAULTS;
         _filterProvider = null;
         _defaultPrettyPrinter = DEFAULT_PRETTY_PRINTER;
         _generatorFeatures = 0;
@@ -521,6 +525,10 @@
      */
     public SerializationConfig with(FormatFeature feature)
     {
+        // 27-Oct-2018, tatu: Alas, complexity due to newly (2.10) refactored json-features:
+        if (feature instanceof JsonWriteFeature) {
+            return _withJsonWriteFeatures(feature);
+        }
         int newSet = _formatWriteFeatures | feature.getMask();
         int newMask = _formatWriteFeaturesToChange | feature.getMask();
         return ((_formatWriteFeatures == newSet) && (_formatWriteFeaturesToChange == newMask)) ? this :
@@ -537,6 +545,10 @@
      */
     public SerializationConfig withFeatures(FormatFeature... features)
     {
+        // 27-Oct-2018, tatu: Alas, complexity due to newly (2.10) refactored json-features:
+        if (features.length > 0 && (features[0] instanceof JsonWriteFeature)) {
+            return _withJsonWriteFeatures(features);
+        }
         int newSet = _formatWriteFeatures;
         int newMask = _formatWriteFeaturesToChange;
         for (FormatFeature f : features) {
@@ -558,6 +570,10 @@
      */
     public SerializationConfig without(FormatFeature feature)
     {
+        // 27-Oct-2018, tatu: Alas, complexity due to newly (2.10) refactored json-features:
+        if (feature instanceof JsonWriteFeature) {
+            return _withoutJsonWriteFeatures(feature);
+        }
         int newSet = _formatWriteFeatures & ~feature.getMask();
         int newMask = _formatWriteFeaturesToChange | feature.getMask();
         return ((_formatWriteFeatures == newSet) && (_formatWriteFeaturesToChange == newMask)) ? this :
@@ -574,6 +590,9 @@
      */
     public SerializationConfig withoutFeatures(FormatFeature... features)
     {
+        if (features.length > 0 && (features[0] instanceof JsonWriteFeature)) {
+            return _withoutJsonWriteFeatures(features);
+        }
         int newSet = _formatWriteFeatures;
         int newMask = _formatWriteFeaturesToChange;
         for (FormatFeature f : features) {
@@ -586,7 +605,61 @@
                     _generatorFeatures, _generatorFeaturesToChange,
                     newSet, newMask);
     }
-    
+
+    // temporary for 2.10
+    private SerializationConfig _withJsonWriteFeatures(FormatFeature... features) {
+        int parserSet = _generatorFeatures;
+        int parserMask = _generatorFeaturesToChange;
+        int newSet = _formatWriteFeatures;
+        int newMask = _formatWriteFeaturesToChange;
+        for (FormatFeature f : features) {
+            final int mask = f.getMask();
+            newSet |= mask;
+            newMask |= mask;
+
+            if (f instanceof JsonWriteFeature) {
+                JsonGenerator.Feature oldF = ((JsonWriteFeature) f).mappedFeature();
+                if (oldF != null) {
+                    final int pmask = oldF.getMask();
+                    parserSet |= pmask;
+                    parserMask |= pmask;
+                }
+            }
+        }
+        return ((_formatWriteFeatures == newSet) && (_formatWriteFeaturesToChange == newMask)
+                && (_generatorFeatures == parserSet) && (_generatorFeaturesToChange == parserMask)
+                ) ? this :
+            new SerializationConfig(this,  _mapperFeatures, _serFeatures,
+                    parserSet, parserMask, newSet, newMask);
+    }
+
+    // temporary for 2.10
+    private SerializationConfig _withoutJsonWriteFeatures(FormatFeature... features) {
+        int parserSet = _generatorFeatures;
+        int parserMask = _generatorFeaturesToChange;
+        int newSet = _formatWriteFeatures;
+        int newMask = _formatWriteFeaturesToChange;
+        for (FormatFeature f : features) {
+            final int mask = f.getMask();
+            newSet &= ~mask;
+            newMask |= mask;
+
+            if (f instanceof JsonWriteFeature) {
+                JsonGenerator.Feature oldF = ((JsonWriteFeature) f).mappedFeature();
+                if (oldF != null) {
+                    final int pmask = oldF.getMask();
+                    parserSet &= ~pmask;
+                    parserMask |= pmask;
+                }
+            }
+        }
+        return ((_formatWriteFeatures == newSet) && (_formatWriteFeaturesToChange == newMask)
+                && (_generatorFeatures == parserSet) && (_generatorFeaturesToChange == parserMask)
+                ) ? this :
+            new SerializationConfig(this,  _mapperFeatures, _serFeatures,
+                    parserSet, parserMask, newSet, newMask);
+    }
+
     /*
     /**********************************************************
     /* Factory methods, other
diff --git a/src/main/java/com/fasterxml/jackson/databind/SerializationFeature.java b/src/main/java/com/fasterxml/jackson/databind/SerializationFeature.java
index 1b46dc0..b37b5d8 100644
--- a/src/main/java/com/fasterxml/jackson/databind/SerializationFeature.java
+++ b/src/main/java/com/fasterxml/jackson/databind/SerializationFeature.java
@@ -257,7 +257,7 @@
     WRITE_ENUMS_USING_TO_STRING(false),
 
     /**
-     * Feature that determines whethere Java Enum values are serialized
+     * Feature that determines whether Java Enum values are serialized
      * as numbers (true), or textual values (false). If textual values are
      * used, other settings are also considered.
      * If this feature is enabled,
@@ -267,11 +267,28 @@
      * Note that this feature has precedence over {@link #WRITE_ENUMS_USING_TO_STRING},
      * which is only considered if this feature is set to false.
      *<p>
+     * Note that since 2.10, this does NOT apply to {@link Enum}s written as
+     * keys of {@link java.util.Map} values, which has separate setting,
+     * {@link #WRITE_ENUM_KEYS_USING_INDEX}.
+     *<p>
      * Feature is disabled by default.
      */
     WRITE_ENUMS_USING_INDEX(false),
 
     /**
+     * Feature that determines whether {link Enum}s
+     * used as {@link java.util.Map} keys are serialized
+     * as using {@link Enum#ordinal()} or not.
+     * Similar to {@link #WRITE_ENUMS_USING_INDEX} used when writing
+     * {@link Enum}s as regular values.
+     *<p>
+     * Feature is disabled by default.
+     * 
+     * @since 2.10
+     */
+    WRITE_ENUM_KEYS_USING_INDEX(false),
+    
+    /**
      * Feature that determines whether Map entries with null values are
      * to be serialized (true) or not (false).
      *<p>
@@ -360,7 +377,7 @@
      * and this setting <b>has no effect</b> on such types.
      *<p>
      * If disabled, standard millisecond timestamps are assumed.
-     * This is the counterpart to {@link SerializationFeature#WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS}.
+     * This is the counterpart to {@link DeserializationFeature#READ_DATE_TIMESTAMPS_AS_NANOSECONDS}.
      *<p>
      * Feature is enabled by default, to support most accurate time values possible.
      *
diff --git a/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java b/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java
index ac24e11..8722b05 100644
--- a/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java
+++ b/src/main/java/com/fasterxml/jackson/databind/SerializerProvider.java
@@ -362,7 +362,7 @@
      * @since 2.8
      */
     public final JsonInclude.Value getDefaultPropertyInclusion(Class<?> baseType) {
-        return _config.getDefaultPropertyInclusion();
+        return _config.getDefaultPropertyInclusion(baseType);
     }
 
     /**
@@ -386,7 +386,7 @@
     public TimeZone getTimeZone() {
         return _config.getTimeZone();
     }
-    
+
     /*
     /**********************************************************
     /* Generic attributes (2.3+)
@@ -1227,7 +1227,7 @@
     public JsonMappingException invalidTypeIdException(JavaType baseType, String typeId,
             String extraDesc) {
         String msg = String.format("Could not resolve type id '%s' as a subtype of %s",
-                typeId, baseType);
+                typeId, ClassUtil.getTypeDescription(baseType));
         return InvalidTypeIdException.from(null, _colonConcat(msg, extraDesc), baseType, typeId);
     }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/BaseSettings.java b/src/main/java/com/fasterxml/jackson/databind/cfg/BaseSettings.java
index e289ab6..a1b9340 100644
--- a/src/main/java/com/fasterxml/jackson/databind/cfg/BaseSettings.java
+++ b/src/main/java/com/fasterxml/jackson/databind/cfg/BaseSettings.java
@@ -8,6 +8,7 @@
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair;
 import com.fasterxml.jackson.databind.introspect.ClassIntrospector;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.fasterxml.jackson.databind.util.StdDateFormat;
@@ -65,16 +66,24 @@
 
     /*
     /**********************************************************
-    /* Configuration settings; type resolution
+    /* Configuration settings; poly type resolution
     /**********************************************************
      */
 
     /**
-     * Type information handler used for "untyped" values (ones declared
-     * to have type <code>Object.class</code>)
+     * Builder used to create type resolver for serializing and deserializing
+     * values for which polymorphic type handling is needed.
      */
     protected final TypeResolverBuilder<?> _typeResolverBuilder;
-    
+
+    /**
+     * Validator that is used to limit allowed polymorphic subtypes, mostly
+     * for security reasons when dealing with untrusted content.
+     *
+     * @since 2.10
+     */
+    protected final PolymorphicTypeValidator _typeValidator;
+
     /*
     /**********************************************************
     /* Configuration settings; other
@@ -130,10 +139,14 @@
     /**********************************************************
      */
 
+    /**
+     * @since 2.10
+     */
     public BaseSettings(ClassIntrospector ci, AnnotationIntrospector ai,
             PropertyNamingStrategy pns, TypeFactory tf,
             TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi,
-            Locale locale, TimeZone tz, Base64Variant defaultBase64)
+            Locale locale, TimeZone tz, Base64Variant defaultBase64,
+            PolymorphicTypeValidator ptv)
     {
         _classIntrospector = ci;
         _annotationIntrospector = ai;
@@ -145,6 +158,16 @@
         _locale = locale;
         _timeZone = tz;
         _defaultBase64 = defaultBase64;
+        _typeValidator = ptv;
+    }
+
+    @Deprecated // since 2.10 
+    public BaseSettings(ClassIntrospector ci, AnnotationIntrospector ai,
+            PropertyNamingStrategy pns, TypeFactory tf,
+            TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi,
+            Locale locale, TimeZone tz, Base64Variant defaultBase64)
+    {
+        this(ci, ai, pns, tf, typer, dateFormat, hi, locale, tz, defaultBase64, null);
     }
 
     /**
@@ -163,7 +186,8 @@
             _handlerInstantiator,
             _locale,
             _timeZone,
-            _defaultBase64);
+            _defaultBase64,
+            _typeValidator);
 
     }
 
@@ -179,7 +203,7 @@
         }
         return new BaseSettings(ci, _annotationIntrospector, _propertyNamingStrategy, _typeFactory,
                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
-                _timeZone, _defaultBase64);
+                _timeZone, _defaultBase64, _typeValidator);
     }
     
     public BaseSettings withAnnotationIntrospector(AnnotationIntrospector ai) {
@@ -188,7 +212,7 @@
         }
         return new BaseSettings(_classIntrospector, ai, _propertyNamingStrategy, _typeFactory,
                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
-                _timeZone, _defaultBase64);
+                _timeZone, _defaultBase64, _typeValidator);
     }
 
     public BaseSettings withInsertedAnnotationIntrospector(AnnotationIntrospector ai) {
@@ -205,7 +229,7 @@
                 _visibilityChecker.withVisibility(forMethod, visibility),
                 _propertyNamingStrategy, _typeFactory,
                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
-                _timeZone, _defaultBase64);
+                _timeZone, _defaultBase64, _typeValidator);
     }
     */
     
@@ -215,7 +239,7 @@
         }
         return new BaseSettings(_classIntrospector, _annotationIntrospector, pns, _typeFactory,
                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
-                _timeZone, _defaultBase64);
+                _timeZone, _defaultBase64, _typeValidator);
     }
 
     public BaseSettings withTypeFactory(TypeFactory tf) {
@@ -224,7 +248,7 @@
         }
         return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, tf,
                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
-                _timeZone, _defaultBase64);
+                _timeZone, _defaultBase64, _typeValidator);
     }
 
     public BaseSettings withTypeResolverBuilder(TypeResolverBuilder<?> typer) {
@@ -233,7 +257,7 @@
         }
         return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory,
                 typer, _dateFormat, _handlerInstantiator, _locale,
-                _timeZone, _defaultBase64);
+                _timeZone, _defaultBase64, _typeValidator);
     }
     
     public BaseSettings withDateFormat(DateFormat df) {
@@ -247,7 +271,7 @@
         }
         return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory,
                 _typeResolverBuilder, df, _handlerInstantiator, _locale,
-                _timeZone, _defaultBase64);
+                _timeZone, _defaultBase64, _typeValidator);
     }
 
     public BaseSettings withHandlerInstantiator(HandlerInstantiator hi) {
@@ -256,7 +280,7 @@
         }
         return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory,
                 _typeResolverBuilder, _dateFormat, hi, _locale,
-                _timeZone, _defaultBase64);
+                _timeZone, _defaultBase64, _typeValidator);
     }
 
     public BaseSettings with(Locale l) {
@@ -265,7 +289,7 @@
         }
         return new BaseSettings(_classIntrospector, _annotationIntrospector, _propertyNamingStrategy, _typeFactory,
                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, l,
-                _timeZone, _defaultBase64);
+                _timeZone, _defaultBase64, _typeValidator);
     }
 
     /**
@@ -286,7 +310,7 @@
         return new BaseSettings(_classIntrospector, _annotationIntrospector,
                 _propertyNamingStrategy, _typeFactory,
                 _typeResolverBuilder, df, _handlerInstantiator, _locale,
-                tz, _defaultBase64);
+                tz, _defaultBase64, _typeValidator);
     }
 
     /**
@@ -299,7 +323,20 @@
         return new BaseSettings(_classIntrospector, _annotationIntrospector,
                 _propertyNamingStrategy, _typeFactory,
                 _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
-                _timeZone, base64);
+                _timeZone, base64, _typeValidator);
+    }
+
+    /**
+     * @since 2.10
+     */
+    public BaseSettings with(PolymorphicTypeValidator v) {
+        if (v == _typeValidator) {
+            return this;
+        }
+        return new BaseSettings(_classIntrospector, _annotationIntrospector,
+                _propertyNamingStrategy, _typeFactory,
+                _typeResolverBuilder, _dateFormat, _handlerInstantiator, _locale,
+                _timeZone, _defaultBase64, v);
     }
     
     /*
@@ -327,6 +364,13 @@
     public TypeResolverBuilder<?> getTypeResolverBuilder() {
         return _typeResolverBuilder;
     }
+
+    /**
+     * @since 2.10
+     */
+    public PolymorphicTypeValidator getPolymorphicTypeValidator() {
+        return _typeValidator;
+    }
     
     public DateFormat getDateFormat() {
         return _dateFormat;
diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverrides.java b/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverrides.java
index 49c622c..dfc87e8 100644
--- a/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverrides.java
+++ b/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverrides.java
@@ -2,6 +2,7 @@
 
 import java.util.*;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonSetter;
 import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
@@ -43,10 +44,20 @@
      */
     protected Boolean _defaultMergeable;
 
+    /**
+     * Global default setting (if any) for leniency: if disabled ({link Boolean#TRUE}),
+     * "strict" (not lenient): default setting if absence of value is considered "lenient"
+     * in Jackson 2.x. Default setting may be overridden by per-type and per-property
+     * settings.
+     *
+     * @since 2.10
+     */
+    protected Boolean _defaultLeniency;
+
     /*
-    /**********************************************************
+    /**********************************************************************
     /* Life cycle
-    /**********************************************************
+    /**********************************************************************
      */
 
     public ConfigOverrides() {
@@ -55,22 +66,35 @@
                 JsonInclude.Value.empty(),
                 JsonSetter.Value.empty(),
                 VisibilityChecker.Std.defaultInstance(),
-                null
+                null, null
         );
     }
 
+    /**
+     * @since 2.10
+     */
     protected ConfigOverrides(Map<Class<?>, MutableConfigOverride> overrides,
-            JsonInclude.Value defIncl,
-            JsonSetter.Value defSetter,
-            VisibilityChecker<?> defVisibility,
-            Boolean defMergeable) {
+            JsonInclude.Value defIncl, JsonSetter.Value defSetter,
+            VisibilityChecker<?> defVisibility, Boolean defMergeable, Boolean defLeniency)
+    {
         _overrides = overrides;
         _defaultInclusion = defIncl;
         _defaultSetterInfo = defSetter;
         _visibilityChecker = defVisibility;
         _defaultMergeable = defMergeable;
+        _defaultLeniency = defLeniency;
     }
 
+    /**
+     * @deprecated Since 2.10
+     */
+    @Deprecated // since 2.10
+    protected ConfigOverrides(Map<Class<?>, MutableConfigOverride> overrides,
+            JsonInclude.Value defIncl, JsonSetter.Value defSetter,
+            VisibilityChecker<?> defVisibility, Boolean defMergeable) {
+        this(overrides, defIncl, defSetter, defVisibility, defMergeable, null);
+    }
+    
     public ConfigOverrides copy()
     {
         Map<Class<?>, MutableConfigOverride> newOverrides;
@@ -83,15 +107,16 @@
             }
         }
         return new ConfigOverrides(newOverrides,
-                _defaultInclusion, _defaultSetterInfo, _visibilityChecker, _defaultMergeable);
+                _defaultInclusion, _defaultSetterInfo, _visibilityChecker,
+                _defaultMergeable, _defaultLeniency);
     }
 
     /*
-    /**********************************************************
+    /**********************************************************************
     /* Per-type override access
-    /**********************************************************
+    /**********************************************************************
      */
-    
+
     public ConfigOverride findOverride(Class<?> type) {
         if (_overrides == null) {
             return null;
@@ -111,10 +136,38 @@
         return override;
     }
 
+    /**
+     * Specific accessor for finding {code JsonFormat.Value} for given type,
+     * considering global default for leniency as well as per-type format
+     * override (if any).
+     *
+     * @return Default format settings for type; never null.
+     *
+     * @since 2.10
+     */
+    public JsonFormat.Value findFormatDefaults(Class<?> type) {
+        if (_overrides != null) {
+            ConfigOverride override = _overrides.get(type);
+            if (override != null) {
+                JsonFormat.Value format = override.getFormat();
+                if (format != null) {
+                    if (!format.hasLenient()) {
+                        return format.withLenient(_defaultLeniency);
+                    }
+                    return format;
+                }
+            }
+        }
+        if (_defaultLeniency == null) {
+            return JsonFormat.Value.empty();
+        }
+        return JsonFormat.Value.forLeniency(_defaultLeniency);
+    }
+
     /*
-    /**********************************************************
+    /**********************************************************************
     /* Global defaults access
-    /**********************************************************
+    /**********************************************************************
      */
 
     public JsonInclude.Value getDefaultInclusion() {
@@ -130,6 +183,13 @@
     }
 
     /**
+     * @since 2.10
+     */
+    public Boolean getDefaultLeniency() {
+        return _defaultLeniency;
+    }
+    
+    /**
      * @since 2.9
      */
     public VisibilityChecker<?> getDefaultVisibility() {
@@ -158,6 +218,13 @@
     }
 
     /**
+     * @since 2.10
+     */
+    public void setDefaultLeniency(Boolean v) {
+        _defaultLeniency = v;
+    }
+
+    /**
      * @since 2.9
      */
     public void setDefaultVisibility(VisibilityChecker<?> v) {
@@ -165,9 +232,9 @@
     }
 
     /*
-    /**********************************************************
+    /**********************************************************************
     /* Helper methods
-    /**********************************************************
+    /**********************************************************************
      */
     
     protected Map<Class<?>, MutableConfigOverride> _newMap() {
diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/MapperBuilder.java b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperBuilder.java
new file mode 100644
index 0000000..7d513e1
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperBuilder.java
@@ -0,0 +1,716 @@
+package com.fasterxml.jackson.databind.cfg;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.text.DateFormat;
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonSetter;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.deser.*;
+import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
+import com.fasterxml.jackson.databind.jsontype.NamedType;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
+import com.fasterxml.jackson.databind.jsontype.SubtypeResolver;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.ser.*;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+/**
+ * Jackson 3 will introduce fully immutable, builder-based system for constructing
+ * {@link ObjectMapper}s. Same can not be done with 2.10 for backwards-compatibility
+ * reasons; but we can offer sort of "fake" builder, which simply encapsulates
+ * configuration calls. The main (and only) point is to allow gradual upgrade.
+ *
+ * @since 2.10
+ */
+public abstract class MapperBuilder<M extends ObjectMapper,
+    B extends MapperBuilder<M,B>>
+{
+    protected final M _mapper;
+
+    /*
+    /**********************************************************************
+    /* Life-cycle
+    /**********************************************************************
+     */
+
+    protected MapperBuilder(M mapper)
+    {
+        _mapper = mapper;
+    }
+
+    /**
+     * Method to call to create actual mapper instance.
+     *<p>
+     * Implementation detail: in 2.10 (but not 3.x) underlying mapper is eagerly
+     * constructed when builder is constructed, and method simply returns that
+     * instance.
+     */
+    public M build() {
+        return _mapper;
+    }
+
+    /*
+    /**********************************************************************
+    /* Accessors, features
+    /**********************************************************************
+     */
+
+    public boolean isEnabled(MapperFeature f) {
+        return _mapper.isEnabled(f);
+    }
+    public boolean isEnabled(DeserializationFeature f) {
+        return _mapper.isEnabled(f);
+    }
+    public boolean isEnabled(SerializationFeature f) {
+        return _mapper.isEnabled(f);
+    }
+
+    public boolean isEnabled(JsonParser.Feature f) {
+        return _mapper.isEnabled(f);
+    }
+    public boolean isEnabled(JsonGenerator.Feature f) {
+        return _mapper.isEnabled(f);
+    }
+
+    /*
+    /**********************************************************************
+    /* Accessors, other
+    /**********************************************************************
+     */
+
+    public TokenStreamFactory streamFactory() {
+        return _mapper.tokenStreamFactory();
+    }
+
+    /*
+    /**********************************************************************
+    /* Changing features: mapper, ser, deser
+    /**********************************************************************
+     */
+
+    public B enable(MapperFeature... features) {
+        _mapper.enable(features);
+        return _this();
+    }
+
+    public B disable(MapperFeature... features) {
+        _mapper.disable(features);
+        return _this();
+    }
+
+    public B configure(MapperFeature feature, boolean state) {
+        _mapper.configure(feature, state);
+        return _this();
+    }
+
+    public B enable(SerializationFeature... features) {
+        for (SerializationFeature f : features) {
+            _mapper.enable(f);
+        }
+        return _this();
+    }
+
+    public B disable(SerializationFeature... features) {
+        for (SerializationFeature f : features) {
+            _mapper.disable(f);
+        }
+        return _this();
+    }
+
+    public B configure(SerializationFeature feature, boolean state) {
+        _mapper.configure(feature, state);
+        return _this();
+    }
+
+    public B enable(DeserializationFeature... features) {
+        for (DeserializationFeature f : features) {
+            _mapper.enable(f);
+        }
+        return _this();
+    }
+
+    public B disable(DeserializationFeature... features) {
+        for (DeserializationFeature f : features) {
+            _mapper.disable(f);
+        }
+        return _this();
+    }
+
+    public B configure(DeserializationFeature feature, boolean state) {
+        _mapper.configure(feature, state);
+        return _this();
+    }
+
+    /*
+    /**********************************************************************
+    /* Changing features: parser, generator, pre-2.10
+    /**********************************************************************
+     */
+
+    public B enable(JsonParser.Feature... features) {
+        _mapper.enable(features);
+        return _this();
+    }
+
+    public B disable(JsonParser.Feature... features) {
+        _mapper.disable(features);
+        return _this();
+    }
+
+    public B configure(JsonParser.Feature feature, boolean state) {
+        _mapper.configure(feature, state);
+        return _this();
+    }
+
+    public B enable(JsonGenerator.Feature... features) {
+        _mapper.enable(features);
+        return _this();
+    }
+
+    public B disable(JsonGenerator.Feature... features) {
+        _mapper.disable(features);
+        return _this();
+    }
+
+    public B configure(JsonGenerator.Feature feature, boolean state) {
+        _mapper.configure(feature, state);
+        return _this();
+    }
+
+    /*
+    /**********************************************************************
+    /* Changing features: parser, generator, 2.10+
+    /**********************************************************************
+     */
+
+    public B enable(StreamReadFeature... features) {
+        for (StreamReadFeature f : features) {
+            _mapper.enable(f.mappedFeature());
+        }
+        return _this();
+    }
+
+    public B disable(StreamReadFeature... features) {
+        for (StreamReadFeature f : features) {
+            _mapper.disable(f.mappedFeature());
+        }
+        return _this();
+    }
+
+    public B configure(StreamReadFeature feature, boolean state) {
+        _mapper.configure(feature.mappedFeature(), state);
+        return _this();
+    }
+
+    public B enable(StreamWriteFeature... features) {
+        for (StreamWriteFeature f : features) {
+            _mapper.enable(f.mappedFeature());
+        }
+        return _this();
+    }
+
+    public B disable(StreamWriteFeature... features) {
+        for (StreamWriteFeature f : features) {
+            _mapper.disable(f.mappedFeature());
+        }
+        return _this();
+    }
+
+    public B configure(StreamWriteFeature feature, boolean state) {
+        _mapper.configure(feature.mappedFeature(), state);
+        return _this();
+    }
+
+    /*
+    /**********************************************************************
+    /* Module registration, discovery, access
+    /**********************************************************************
+     */
+
+    public B addModule(com.fasterxml.jackson.databind.Module module)
+    {
+        _mapper.registerModule(module);
+        return _this();
+    }
+
+    public B addModules(com.fasterxml.jackson.databind.Module... modules)
+    {
+        for (com.fasterxml.jackson.databind.Module module : modules) {
+            addModule(module);
+        }
+        return _this();
+    }
+
+    public B addModules(Iterable<? extends com.fasterxml.jackson.databind.Module> modules)
+    {
+        for (com.fasterxml.jackson.databind.Module module : modules) {
+            addModule(module);
+        }
+        return _this();
+    }
+
+    /**
+     * Method for locating available methods, using JDK {@link ServiceLoader}
+     * facility, along with module-provided SPI.
+     *<p>
+     * Note that method does not do any caching, so calls should be considered
+     * potentially expensive.
+     */
+    public static List<com.fasterxml.jackson.databind.Module> findModules() {
+        return findModules(null);
+    }
+
+    /**
+     * Method for locating available methods, using JDK {@link ServiceLoader}
+     * facility, along with module-provided SPI.
+     *<p>
+     * Note that method does not do any caching, so calls should be considered
+     * potentially expensive.
+     */
+    public static List<com.fasterxml.jackson.databind.Module> findModules(ClassLoader classLoader)
+    {
+        ArrayList<com.fasterxml.jackson.databind.Module> modules = new ArrayList<>();
+        ServiceLoader<com.fasterxml.jackson.databind.Module> loader = secureGetServiceLoader(com.fasterxml.jackson.databind.Module.class, classLoader);
+        for (com.fasterxml.jackson.databind.Module module : loader) {
+            modules.add(module);
+        }
+        return modules;
+    }
+
+    private static <T> ServiceLoader<T> secureGetServiceLoader(final Class<T> clazz, final ClassLoader classLoader) {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm == null) {
+            return (classLoader == null) ?
+                    ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader);
+        }
+        return AccessController.doPrivileged(new PrivilegedAction<ServiceLoader<T>>() {
+            @Override
+            public ServiceLoader<T> run() {
+                return (classLoader == null) ?
+                        ServiceLoader.load(clazz) : ServiceLoader.load(clazz, classLoader);
+            }
+        });
+    }
+
+    /**
+     * Convenience method that is functionally equivalent to:
+     *<code>
+     *   addModules(builder.findModules());
+     *</code>
+     *<p>
+     * As with {@link #findModules()}, no caching is done for modules, so care
+     * needs to be taken to either create and share a single mapper instance;
+     * or to cache introspected set of modules.
+     */
+    public B findAndAddModules() {
+        return addModules(findModules());
+    }
+
+    /*
+    /**********************************************************************
+    /* Changing base settings
+    /**********************************************************************
+     */
+
+    /**
+     * Method for replacing {@link AnnotationIntrospector} used by the
+     * mapper instance to be built.
+     * Note that doing this will replace the current introspector, which
+     * may lead to unavailability of core Jackson annotations.
+     * If you want to combine handling of multiple introspectors,
+     * have a look at {@link com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair}.
+     *
+     * @see com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair
+     */
+    public B annotationIntrospector(AnnotationIntrospector intr) {
+        _mapper.setAnnotationIntrospector(intr);
+        return _this();
+    }
+
+    public B nodeFactory(JsonNodeFactory f) {
+        _mapper.setNodeFactory(f);
+        return _this();
+    }
+
+    /*
+    /**********************************************************************
+    /* Changing introspection helpers
+    /**********************************************************************
+     */
+
+    public B typeFactory(TypeFactory f) {
+        _mapper.setTypeFactory(f);
+        return _this();
+    }
+
+    public B subtypeResolver(SubtypeResolver r) {
+        _mapper.setSubtypeResolver(r);
+        return _this();
+    }
+
+    public B visibility(VisibilityChecker<?> vc) {
+        _mapper.setVisibility(vc);
+        return _this();
+    }
+
+    public B visibility(PropertyAccessor forMethod, JsonAutoDetect.Visibility visibility) {
+        _mapper.setVisibility(forMethod, visibility);
+        return _this();
+    }
+
+    /**
+     * Method for configuring {@link HandlerInstantiator} to use for creating
+     * instances of handlers (such as serializers, deserializers, type and type
+     * id resolvers), given a class.
+     *
+     * @param hi Instantiator to use; if null, use the default implementation
+     */
+    public B handlerInstantiator(HandlerInstantiator hi) {
+        _mapper.setHandlerInstantiator(hi);
+        return _this();
+    }
+
+    public B propertyNamingStrategy(PropertyNamingStrategy s) {
+        _mapper.setPropertyNamingStrategy(s);
+        return _this();
+    }
+
+    /*
+    /**********************************************************************
+    /* Changing factories, serialization
+    /**********************************************************************
+     */
+
+    public B serializerFactory(SerializerFactory f) {
+        _mapper.setSerializerFactory(f);
+        return _this();
+    }
+
+    /**
+     * Method for configuring this mapper to use specified {@link FilterProvider} for
+     * mapping Filter Ids to actual filter instances.
+     *<p>
+     * Note that usually it is better to use method in {@link ObjectWriter}, but sometimes
+     * this method is more convenient. For example, some frameworks only allow configuring
+     * of ObjectMapper instances and not {@link ObjectWriter}s.
+     */
+    public B filterProvider(FilterProvider prov) {
+        _mapper.setFilterProvider(prov);
+        return _this();
+    }
+
+    public B defaultPrettyPrinter(PrettyPrinter pp) {
+        _mapper.setDefaultPrettyPrinter(pp);
+        return _this();
+    }
+
+    /*
+    /**********************************************************************
+    /* Changing factories, related, deserialization
+    /**********************************************************************
+     */
+
+    public B injectableValues(InjectableValues v) {
+        _mapper.setInjectableValues(v);
+        return _this();
+    }
+
+    /**
+     * Method used for adding a {@link DeserializationProblemHandler} for this
+     * builder, at the head of the list (meaning it has priority over handler
+     * registered earlier).
+     */
+    public B addHandler(DeserializationProblemHandler h) {
+        _mapper.addHandler(h);
+        return _this();
+    }
+
+    /**
+     * Method that may be used to remove all {@link DeserializationProblemHandler}s added
+     * to this builder (if any).
+     */
+    public B clearProblemHandlers() {
+        _mapper.clearProblemHandlers();
+        return _this();
+    }
+
+    /*
+    /**********************************************************************
+    /* Changing global defaults
+    /**********************************************************************
+     */
+
+    public B defaultSetterInfo(JsonSetter.Value v) {
+        _mapper.setDefaultSetterInfo(v);
+        return _this();
+    }
+    
+    /**
+     * Method for setting default Setter configuration, regarding things like
+     * merging, null-handling; used for properties for which there are
+     * no per-type or per-property overrides (via annotations or config overrides).
+     */
+    public B defaultMergeable(Boolean b) {
+        _mapper.setDefaultMergeable(b);
+        return _this();
+    }
+
+    /**
+     * Method for setting default Setter configuration, regarding things like
+     * merging, null-handling; used for properties for which there are
+     * no per-type or per-property overrides (via annotations or config overrides).
+     */
+    public B defaultLeniency(Boolean b) {
+        _mapper.setDefaultLeniency(b);
+        return _this();
+    }
+
+    /*
+    /**********************************************************************
+    /* Changing settings, date/time
+    /**********************************************************************
+     */
+
+    /**
+     * Method for configuring the default {@link DateFormat} to use when serializing time
+     * values as Strings, and deserializing from JSON Strings.
+     * If you need per-request configuration, factory methods in
+     * {@link ObjectReader} and {@link ObjectWriter} instead.
+     */
+    public B defaultDateFormat(DateFormat df) {
+        _mapper.setDateFormat(df);
+        return _this();
+    }
+
+    /**
+     * Method for overriding default TimeZone to use for formatting.
+     * Default value used is UTC (NOT default TimeZone of JVM).
+     */
+    public B defaultTimeZone(TimeZone tz) {
+        _mapper.setTimeZone(tz);
+        return _this();
+    }
+
+    /**
+     * Method for overriding default locale to use for formatting.
+     * Default value used is {@link Locale#getDefault()}.
+     */
+    public B defaultLocale(Locale locale) {
+        _mapper.setLocale(locale);
+        return _this();
+    }
+
+    /*
+    /**********************************************************************
+    /* Changing settings, formatting
+    /**********************************************************************
+     */
+
+    /**
+     * Method that will configure default {@link Base64Variant} that
+     * <code>byte[]</code> serializers and deserializers will use.
+     * 
+     * @param v Base64 variant to use
+     * 
+     * @return This builder instance to allow call chaining
+     */
+    public B defaultBase64Variant(Base64Variant v) {
+        _mapper.setBase64Variant(v);
+        return _this();
+    }
+
+    /**
+     * Method for configured default property inclusion to use for serialization.
+     *
+     * @param incl Default property inclusion to set
+     *
+     * @return This builder instance to allow call chaining
+     */
+    public B serializationInclusion(JsonInclude.Include incl) {
+        _mapper.setSerializationInclusion(incl);
+        return _this();
+    }
+
+    /**
+     * Method for configured default property inclusion to use for serialization.
+     *
+     * @param incl Default property inclusion to set
+     *
+     * @return This builder instance to allow call chaining
+     *
+     * @since 2.11
+     */
+    public B defaultPropertyInclusion(JsonInclude.Value incl) {
+        _mapper.setDefaultPropertyInclusion(incl);
+        return _this();
+    }
+
+    /*
+    /**********************************************************************
+    /* Adding Mix-ins
+    /**********************************************************************
+     */
+
+    /**
+     * Method to use for defining mix-in annotations to use for augmenting
+     * annotations that classes have, for purpose of configuration serialization
+     * and/or deserialization processing.
+     * Mixing in is done when introspecting class annotations and properties.
+     * Annotations from "mixin" class (and its supertypes)
+     * will <b>override</b>
+     * annotations that target classes (and their super-types) have.
+     *<p>
+     * Note that standard mixin handler implementations will only allow a single mix-in
+     * source class per target, so if there was a previous mix-in defined target it will
+     * be cleared. This also means that you can remove mix-in definition by specifying
+     * {@code mixinSource} of {@code null}
+     */
+    public B addMixIn(Class<?> target, Class<?> mixinSource)
+    {
+        _mapper.addMixIn(target, mixinSource);
+        return _this();
+    }
+
+    /*
+    /**********************************************************************
+    /* Subtype registration, related
+    /**********************************************************************
+     */
+
+    public B registerSubtypes(Class<?>... subtypes) {
+        _mapper.registerSubtypes(subtypes);
+        return _this();
+    }
+
+    public B registerSubtypes(NamedType... subtypes) {
+        _mapper.registerSubtypes(subtypes);
+        return _this();
+    }
+
+    public B registerSubtypes(Collection<Class<?>> subtypes) {
+        _mapper.registerSubtypes(subtypes);
+        return _this();
+    }
+
+    /**
+     * Method for assigning {@link PolymorphicTypeValidator} to use for validating
+     * subtypes when using Class name - based polymorphic deserialization
+     * using annotations (validator used with "Default Typing" is specified by
+     * passing in {@link #activateDefaultTyping(PolymorphicTypeValidator)} instead).
+     *<p>
+     * Validator will be called on validating types for which no default databind
+     * deserializer, or module-provided deserializer is found: typically this
+     * includes "POJO" (aka Bean) types, but not (for example) most container
+     * types.
+     *
+     * @since 2.10
+     */
+    public B polymorphicTypeValidator(PolymorphicTypeValidator ptv) {
+        _mapper.setPolymorphicTypeValidator(ptv);
+        return _this();
+    }
+
+    /*
+    /**********************************************************************
+    /* Default typing
+    /**********************************************************************
+     */
+
+    /**
+     * Convenience method that is equivalent to calling
+     *<pre>
+     *  activateDefaultTyping(subtypeValidator, DefaultTyping.OBJECT_AND_NON_CONCRETE);
+     *</pre>
+     *<p>
+     * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
+     * as allowing all subtypes can be risky for untrusted content.
+     */
+    public B activateDefaultTyping(PolymorphicTypeValidator subtypeValidator) {
+        _mapper.activateDefaultTyping(subtypeValidator);
+        return _this();
+    }
+
+    /**
+     * Convenience method that is equivalent to calling
+     *<pre>
+     *  activateDefaultTyping(subtypeValidator, dti, JsonTypeInfo.As.WRAPPER_ARRAY);
+     *</pre>
+     *<p>
+     * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
+     * as allowing all subtypes can be risky for untrusted content.
+     */
+    public B activateDefaultTyping(PolymorphicTypeValidator subtypeValidator,
+            DefaultTyping dti) {
+        _mapper.activateDefaultTyping(subtypeValidator, dti);
+        return _this();
+    }
+
+    /**
+     * Method for enabling automatic inclusion of type information, needed
+     * for proper deserialization of polymorphic types (unless types
+     * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}).
+     *<P>
+     * NOTE: use of <code>JsonTypeInfo.As#EXTERNAL_PROPERTY</code> <b>NOT SUPPORTED</b>;
+     * and attempts of do so will throw an {@link IllegalArgumentException} to make
+     * this limitation explicit.
+     *<p>
+     * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
+     * as allowing all subtypes can be risky for untrusted content.
+     * 
+     * @param applicability Defines kinds of types for which additional type information
+     *    is added; see {@link DefaultTyping} for more information.
+     */
+    public B activateDefaultTyping(PolymorphicTypeValidator subtypeValidator,
+            DefaultTyping applicability, JsonTypeInfo.As includeAs)
+    {
+        _mapper.activateDefaultTyping(subtypeValidator, applicability, includeAs);
+        return _this();
+    }
+
+    /**
+     * Method for enabling automatic inclusion of type information -- needed
+     * for proper deserialization of polymorphic types (unless types
+     * have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) --
+     * using "As.PROPERTY" inclusion mechanism and specified property name
+     * to use for inclusion (default being "@class" since default type information
+     * always uses class name as type identifier)
+     *<p>
+     * NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
+     * as allowing all subtypes can be risky for untrusted content.
+     */
+    public B activateDefaultTypingAsProperty(PolymorphicTypeValidator subtypeValidator,
+            DefaultTyping applicability, String propertyName)
+    {
+        _mapper.activateDefaultTypingAsProperty(subtypeValidator, applicability, propertyName);
+        return _this();
+    }
+
+    /**
+     * Method for disabling automatic inclusion of type information; if so, only
+     * explicitly annotated types (ones with
+     * {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) will have
+     * additional embedded type information.
+     */
+    public B deactivateDefaultTyping() {
+        _mapper.deactivateDefaultTyping();
+        return _this();
+    }
+    
+    /*
+    /**********************************************************************
+    /* Other helper methods
+    /**********************************************************************
+     */
+
+    // silly convenience cast method we need
+    @SuppressWarnings("unchecked")
+    protected final B _this() { return (B) this; }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfig.java b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfig.java
index 7bc3e7f..de96181 100644
--- a/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfig.java
+++ b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfig.java
@@ -15,6 +15,7 @@
 import com.fasterxml.jackson.databind.introspect.ClassIntrospector;
 import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector;
 import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
 import com.fasterxml.jackson.databind.jsontype.SubtypeResolver;
 import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
@@ -265,6 +266,13 @@
     
     public abstract SubtypeResolver getSubtypeResolver();
 
+    /**
+     * @since 2.10
+     */
+    public PolymorphicTypeValidator getPolymorphicTypeValidator() {
+        return _base.getPolymorphicTypeValidator();
+    }
+
     public final TypeFactory getTypeFactory() {
         return _base.getTypeFactory();
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfigBase.java b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfigBase.java
index a7ca2e5..044d13b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfigBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfigBase.java
@@ -637,14 +637,7 @@
 
     @Override
     public final JsonFormat.Value getDefaultPropertyFormat(Class<?> type) {
-        ConfigOverride overrides = _configOverrides.findOverride(type);
-        if (overrides != null) {
-            JsonFormat.Value v = overrides.getFormat();
-            if (v != null) {
-                return v;
-            }
-        }
-        return EMPTY_FORMAT;
+        return _configOverrides.findFormatDefaults(type);
     }
 
     @Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java
index 1e1d80e..57a7eba 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/AbstractDeserializer.java
@@ -221,7 +221,7 @@
     /* Deserializer implementation
     /**********************************************************
      */
-    
+
     @Override
     public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
             TypeDeserializer typeDeserializer)
@@ -230,7 +230,7 @@
         // Hmmh. One tricky question; for scalar, is it an Object Id, or "Natural" type?
         // for now, prefer Object Id:
         if (_objectIdReader != null) {
-            JsonToken t = p.getCurrentToken();
+            JsonToken t = p.currentToken();
             if (t != null) {
                 // Most commonly, a scalar (int id, uuid String, ...)
                 if (t.isScalarValue()) {
@@ -280,7 +280,7 @@
          * Finally, we may have to consider possibility of custom handlers for
          * these values: but for now this should work ok.
          */
-        switch (p.getCurrentTokenId()) {
+        switch (p.currentTokenId()) {
         case JsonTokenId.ID_STRING:
             if (_acceptString) {
                 return p.getText();
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
index fb97cd4..81ea9f7 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java
@@ -1,5 +1,6 @@
 package com.fasterxml.jackson.databind.deser;
 
+import java.io.Serializable;
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.AtomicReference;
@@ -7,14 +8,19 @@
 import com.fasterxml.jackson.annotation.JacksonInject;
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonSetter;
+import com.fasterxml.jackson.annotation.Nulls;
 import com.fasterxml.jackson.annotation.JsonCreator.Mode;
-import com.fasterxml.jackson.core.JsonLocation;
+
 import com.fasterxml.jackson.core.JsonParser;
+
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.cfg.ConfigOverride;
 import com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig;
 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
 import com.fasterxml.jackson.databind.deser.impl.CreatorCandidate;
 import com.fasterxml.jackson.databind.deser.impl.CreatorCollector;
+import com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators;
 import com.fasterxml.jackson.databind.deser.impl.JavaUtilCollectionsDeserializers;
 import com.fasterxml.jackson.databind.deser.std.*;
 import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
@@ -46,64 +52,13 @@
     private final static Class<?> CLASS_CHAR_SEQUENCE = CharSequence.class;
     private final static Class<?> CLASS_ITERABLE = Iterable.class;
     private final static Class<?> CLASS_MAP_ENTRY = Map.Entry.class;
+    private final static Class<?> CLASS_SERIALIZABLE = Serializable.class;
 
     /**
      * We need a placeholder for creator properties that don't have name
      * but are marked with `@JsonWrapped` annotation.
      */
     protected final static PropertyName UNWRAPPED_CREATOR_PARAM_NAME = new PropertyName("@JsonUnwrapped");
-    
-    /* We do some defaulting for abstract Map classes and
-     * interfaces, to avoid having to use exact types or annotations in
-     * cases where the most common concrete Maps will do.
-     */
-    @SuppressWarnings("rawtypes")
-    final static HashMap<String, Class<? extends Map>> _mapFallbacks =
-        new HashMap<String, Class<? extends Map>>();
-    static {
-        @SuppressWarnings("rawtypes")
-        final Class<? extends Map> DEFAULT_MAP = LinkedHashMap.class;
-        _mapFallbacks.put(Map.class.getName(), DEFAULT_MAP);
-        _mapFallbacks.put(AbstractMap.class.getName(), DEFAULT_MAP);
-        _mapFallbacks.put(ConcurrentMap.class.getName(), ConcurrentHashMap.class);
-        _mapFallbacks.put(SortedMap.class.getName(), TreeMap.class);
-
-        _mapFallbacks.put(java.util.NavigableMap.class.getName(), TreeMap.class);
-        _mapFallbacks.put(java.util.concurrent.ConcurrentNavigableMap.class.getName(),
-                java.util.concurrent.ConcurrentSkipListMap.class);
-    }
-
-    /* We do some defaulting for abstract Collection classes and
-     * interfaces, to avoid having to use exact types or annotations in
-     * cases where the most common concrete Collection will do.
-     */
-    @SuppressWarnings("rawtypes")
-    final static HashMap<String, Class<? extends Collection>> _collectionFallbacks =
-        new HashMap<String, Class<? extends Collection>>();
-    static {
-        @SuppressWarnings("rawtypes")
-        final Class<? extends Collection> DEFAULT_LIST = ArrayList.class;
-        @SuppressWarnings("rawtypes")
-        final Class<? extends Collection> DEFAULT_SET = HashSet.class;
-
-        _collectionFallbacks.put(Collection.class.getName(), DEFAULT_LIST);
-        _collectionFallbacks.put(List.class.getName(), DEFAULT_LIST);
-        _collectionFallbacks.put(Set.class.getName(), DEFAULT_SET);
-        _collectionFallbacks.put(SortedSet.class.getName(), TreeSet.class);
-        _collectionFallbacks.put(Queue.class.getName(), LinkedList.class);
-
-        // 09-Feb-2019, tatu: How did we miss these? Related in [databind#2251] problem
-        _collectionFallbacks.put(AbstractList.class.getName(), DEFAULT_LIST);
-        _collectionFallbacks.put(AbstractSet.class.getName(), DEFAULT_SET);
-
-        // then JDK 1.6 types:
-        /* 17-May-2013, tatu: [databind#216] Should be fine to use straight Class references EXCEPT
-         *   that some god-forsaken platforms (... looking at you, Android) do not
-         *   include these. So, use "soft" references...
-         */
-        _collectionFallbacks.put("java.util.Deque", LinkedList.class);
-        _collectionFallbacks.put("java.util.NavigableSet", TreeSet.class);
-    }
 
     /*
     /**********************************************************
@@ -264,7 +219,7 @@
         if (instantiator == null) {
             // Second: see if some of standard Jackson/JDK types might provide value
             // instantiators.
-            instantiator = _findStdValueInstantiator(config, beanDesc);
+            instantiator = JDKValueInstantiators.findStdValueInstantiator(config, beanDesc.getBeanClass());
             if (instantiator == null) {
                 instantiator = _constructDefaultValueInstantiator(ctxt, beanDesc);
             }
@@ -294,30 +249,6 @@
         return instantiator;
     }
 
-    private ValueInstantiator _findStdValueInstantiator(DeserializationConfig config,
-            BeanDescription beanDesc)
-        throws JsonMappingException
-    {
-        Class<?> raw = beanDesc.getBeanClass();
-        if (raw == JsonLocation.class) {
-            return new JsonLocationInstantiator();
-        }
-        // [databind#1868]: empty List/Set/Map
-        if (Collection.class.isAssignableFrom(raw)) {
-            if (Collections.EMPTY_SET.getClass() == raw) {
-                return new ConstantValueInstantiator(Collections.EMPTY_SET);
-            }
-            if (Collections.EMPTY_LIST.getClass() == raw) {
-                return new ConstantValueInstantiator(Collections.EMPTY_LIST);
-            }
-        } else if (Map.class.isAssignableFrom(raw)) {
-            if (Collections.EMPTY_MAP.getClass() == raw) {
-                return new ConstantValueInstantiator(Collections.EMPTY_MAP);
-            }
-        }
-        return null;
-    }
-
     /**
      * Method that will construct standard default {@link ValueInstantiator}
      * using annotations (like @JsonCreator) and visibility rules
@@ -1075,11 +1006,14 @@
         if (typeDeser == null) {
             typeDeser = findTypeDeserializer(config, type);
         }
+
+        // 22-Sep-2019, tatu: for [databind#2458] need more work on getting metadata
+        //   about SetterInfo, mergeability
+        metadata = _getSetterInfo(ctxt, property, metadata);
+
         // Note: contextualization of typeDeser _should_ occur in constructor of CreatorProperty
         // so it is not called directly here
-
         Object injectableValueId = (injectable == null) ? null : injectable.getId();
-        
         SettableBeanProperty prop = new CreatorProperty(name, type, property.getWrapperName(),
                 typeDeser, beanDesc.getClassAnnotations(), param, index, injectableValueId,
                 metadata);
@@ -1113,6 +1047,65 @@
         return null;
     }
 
+    /**
+     * Helper method copied from {@code POJOPropertyBuilder} since that won't be
+     * applied to creator parameters
+     *
+     * @since 2.10
+     */
+    protected PropertyMetadata _getSetterInfo(DeserializationContext ctxt,
+            BeanProperty prop, PropertyMetadata metadata)
+    {
+        final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
+        final DeserializationConfig config = ctxt.getConfig();
+
+        boolean needMerge = true;
+        Nulls valueNulls = null;
+        Nulls contentNulls = null;
+
+        // NOTE: compared to `POJOPropertyBuilder`, we only have access to creator
+        // parameter, not other accessors, so code bit simpler
+        AnnotatedMember prim = prop.getMember();
+
+        if (prim != null) {
+            // Ok, first: does property itself have something to say?
+            if (intr != null) {
+                JsonSetter.Value setterInfo = intr.findSetterInfo(prim);
+                if (setterInfo != null) {
+                    valueNulls = setterInfo.nonDefaultValueNulls();
+                    contentNulls = setterInfo.nonDefaultContentNulls();
+                }
+            }
+            // If not, config override?
+            // 25-Oct-2016, tatu: Either this, or type of accessor...
+            if (needMerge || (valueNulls == null) || (contentNulls == null)) {
+                ConfigOverride co = config.getConfigOverride(prop.getType().getRawClass());
+                JsonSetter.Value setterInfo = co.getSetterInfo();
+                if (setterInfo != null) {
+                    if (valueNulls == null) {
+                        valueNulls = setterInfo.nonDefaultValueNulls();
+                    }
+                    if (contentNulls == null) {
+                        contentNulls = setterInfo.nonDefaultContentNulls();
+                    }
+                }
+            }
+        }
+        if (needMerge || (valueNulls == null) || (contentNulls == null)) {
+            JsonSetter.Value setterInfo = config.getDefaultSetterInfo();
+            if (valueNulls == null) {
+                valueNulls = setterInfo.nonDefaultValueNulls();
+            }
+            if (contentNulls == null) {
+                contentNulls = setterInfo.nonDefaultContentNulls();
+            }
+        }
+        if ((valueNulls != null) || (contentNulls != null)) {
+            metadata = metadata.withNulls(valueNulls, contentNulls);
+        }
+        return metadata;
+    }
+
     /*
     /**********************************************************
     /* JsonDeserializerFactory impl: array deserializers
@@ -1150,7 +1143,7 @@
             }
             deser = new ObjectArrayDeserializer(type, contentDeser, elemTypeDeser);
         }
-        // and then new with 2.2: ability to post-process it too (Issue#120)
+        // and then new with 2.2: ability to post-process it too (databind#120)
         if (_factoryConfig.hasDeserializerModifiers()) {
             for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
                 deser = mod.modifyArrayDeserializer(config, type, beanDesc, deser);
@@ -1160,9 +1153,9 @@
     }
 
     /*
-    /**********************************************************
+    /**********************************************************************
     /* JsonDeserializerFactory impl: Collection(-like) deserializers
-    /**********************************************************
+    /**********************************************************************
      */
 
     @Override
@@ -1251,14 +1244,13 @@
 
     protected CollectionType _mapAbstractCollectionType(JavaType type, DeserializationConfig config)
     {
-        Class<?> collectionClass = type.getRawClass();
-        collectionClass = _collectionFallbacks.get(collectionClass.getName());
-        if (collectionClass == null) {
-            return null;
+        final Class<?> collectionClass = ContainerDefaultMappings.findCollectionFallback(type);
+        if (collectionClass != null) {
+            return (CollectionType) config.constructSpecializedType(type, collectionClass);
         }
-        return (CollectionType) config.constructSpecializedType(type, collectionClass);
+        return null;
     }
-    
+
     // Copied almost verbatim from "createCollectionDeserializer" -- should try to share more code
     @Override
     public JsonDeserializer<?> createCollectionLikeDeserializer(DeserializationContext ctxt,
@@ -1335,7 +1327,7 @@
                     inst = findValueInstantiator(ctxt, beanDesc);
                 }
                 Class<?> kt = keyType.getRawClass();
-                if (kt == null || !kt.isEnum()) {
+                if (kt == null || !ClassUtil.isEnumType(kt)) {
                     throw new IllegalArgumentException("Cannot construct EnumMap; generic (key) type not available");
                 }
                 deser = new EnumMapDeserializer(type, inst, null,
@@ -1355,11 +1347,10 @@
              */
             if (deser == null) {
                 if (type.isInterface() || type.isAbstract()) {
-                    @SuppressWarnings("rawtypes")
-                    Class<? extends Map> fallback = _mapFallbacks.get(mapClass.getName());
+                    MapType fallback = _mapAbstractMapType(type, config);
                     if (fallback != null) {
-                        mapClass = fallback;
-                        type = (MapType) config.constructSpecializedType(type, mapClass);
+                        type = (MapType) fallback;
+                        mapClass = type.getRawClass();
                         // But if so, also need to re-check creators...
                         beanDesc = config.introspectForCreation(type);
                     } else {
@@ -1400,6 +1391,16 @@
         return deser;
     }
 
+    protected MapType _mapAbstractMapType(JavaType type, DeserializationConfig config)
+    {
+        final Class<?> mapClass = ContainerDefaultMappings.findMapFallback(type);
+        if (mapClass != null) {
+            return (MapType) config.constructSpecializedType(type, mapClass);
+        }
+        return null;
+    }
+
+    
     // Copied almost verbatim from "createMapDeserializer" -- should try to share more code
     @Override
     public JsonDeserializer<?> createMapLikeDeserializer(DeserializationContext ctxt,
@@ -1740,7 +1741,14 @@
         // but if annotations found, may need to resolve subtypes:
         Collection<NamedType> subtypes = config.getSubtypeResolver().collectAndResolveSubtypesByTypeId(
                 config, annotated, baseType);
-        return b.buildTypeDeserializer(config, baseType, subtypes);
+        try {
+            return b.buildTypeDeserializer(config, baseType, subtypes);
+        } catch (IllegalArgumentException e0) {
+            InvalidDefinitionException e = InvalidDefinitionException.from((JsonParser) null,
+                    ClassUtil.exceptionMessage(e0), baseType);
+            e.initCause(e0);
+            throw e;
+        }
     }
     
     /**
@@ -1783,8 +1791,8 @@
         throws JsonMappingException
     {
         Class<?> rawType = type.getRawClass();
-        // Object ("untyped"), String equivalents:
-        if (rawType == CLASS_OBJECT) {
+        // Object ("untyped"), and as of 2.10 (see [databind#2115]), `java.io.Serializable`
+        if ((rawType == CLASS_OBJECT) || (rawType == CLASS_SERIALIZABLE)) {
             // 11-Feb-2015, tatu: As per [databind#700] need to be careful wrt non-default Map, List.
             DeserializationConfig config = ctxt.getConfig();
             JavaType lt, mt;
@@ -1797,6 +1805,7 @@
             }
             return new UntypedObjectDeserializer(lt, mt);
         }
+        // String and equivalents
         if (rawType == CLASS_STRING || rawType == CLASS_CHAR_SEQUENCE) {
             return StringDeserializer.instance;
         }
@@ -2186,4 +2195,69 @@
         BeanDescription beanDesc = config.introspect(enumType);
         return beanDesc.findJsonValueMethod();
     }
+
+    /**
+     * Helper class to contain default mappings for abstract JDK {@link java.util.Collection}
+     * and {@link java.util.Map} types. Separated out here to defer cost of creating lookups
+     * until mappings are actually needed.
+     *
+     * @since 2.10
+     */
+    @SuppressWarnings("rawtypes")
+    protected static class ContainerDefaultMappings {
+        // We do some defaulting for abstract Collection classes and
+        // interfaces, to avoid having to use exact types or annotations in
+        // cases where the most common concrete Collection will do.
+        final static HashMap<String, Class<? extends Collection>> _collectionFallbacks;
+        static {
+            HashMap<String, Class<? extends Collection>> fallbacks = new HashMap<>();
+
+            final Class<? extends Collection> DEFAULT_LIST = ArrayList.class;
+            final Class<? extends Collection> DEFAULT_SET = HashSet.class;
+
+            fallbacks.put(Collection.class.getName(), DEFAULT_LIST);
+            fallbacks.put(List.class.getName(), DEFAULT_LIST);
+            fallbacks.put(Set.class.getName(), DEFAULT_SET);
+            fallbacks.put(SortedSet.class.getName(), TreeSet.class);
+            fallbacks.put(Queue.class.getName(), LinkedList.class);
+
+            // 09-Feb-2019, tatu: How did we miss these? Related in [databind#2251] problem
+            fallbacks.put(AbstractList.class.getName(), DEFAULT_LIST);
+            fallbacks.put(AbstractSet.class.getName(), DEFAULT_SET);
+
+            // 09-Feb-2019, tatu: And more esoteric types added in JDK6
+            fallbacks.put(Deque.class.getName(), LinkedList.class);
+            fallbacks.put(NavigableSet.class.getName(), TreeSet.class);
+
+            _collectionFallbacks = fallbacks;
+        }
+
+        // We do some defaulting for abstract Map classes and
+        // interfaces, to avoid having to use exact types or annotations in
+        // cases where the most common concrete Maps will do.
+        final static HashMap<String, Class<? extends Map>> _mapFallbacks;
+        static {
+            HashMap<String, Class<? extends Map>> fallbacks = new HashMap<>();
+
+            final Class<? extends Map> DEFAULT_MAP = LinkedHashMap.class;
+            fallbacks.put(Map.class.getName(), DEFAULT_MAP);
+            fallbacks.put(AbstractMap.class.getName(), DEFAULT_MAP);
+            fallbacks.put(ConcurrentMap.class.getName(), ConcurrentHashMap.class);
+            fallbacks.put(SortedMap.class.getName(), TreeMap.class);
+
+            fallbacks.put(java.util.NavigableMap.class.getName(), TreeMap.class);
+            fallbacks.put(java.util.concurrent.ConcurrentNavigableMap.class.getName(),
+                    java.util.concurrent.ConcurrentSkipListMap.class);
+
+            _mapFallbacks = fallbacks;
+        }
+
+        public static Class<?> findCollectionFallback(JavaType type) {
+            return _collectionFallbacks.get(type.getRawClass().getName());
+        }
+
+        public static Class<?> findMapFallback(JavaType type) {
+            return _mapFallbacks.get(type.getRawClass().getName());
+        }
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
index 88051e7..841adcf 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java
@@ -195,7 +195,7 @@
             default:
             }
         }
-        return ctxt.handleUnexpectedToken(handledType(), p);
+        return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
     }
 
     @Deprecated // since 2.8; remove unless getting used
@@ -559,7 +559,7 @@
             p2.close();
             return ob;
         }
-        return ctxt.handleUnexpectedToken(handledType(), p);
+        return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
     }
 
     /*
@@ -992,7 +992,10 @@
             if (_anySetter != null) {
                 buffer.bufferAnyProperty(_anySetter, propName,
                         _anySetter.deserialize(p, ctxt));
+                continue;
             }
+            // Unknown: let's call handler method
+            handleUnknownProperty(p, ctxt, _valueClass, propName);
         }
         tokens.writeEndObject();
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
index 6ce41f7..4a15bfb 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java
@@ -899,9 +899,9 @@
                 }
             } else if (!mayMerge.booleanValue()) { // prevented
                 if (!merge.fromDefaults) {
-                    // If attempts was made via explicit annotation/per-type config override,
+                    // If attempt was made via explicit annotation/per-type config override,
                     // should be reported; may or may not result in exception
-                    ctxt.reportBadMerge(valueDeser);
+                    ctxt.handleBadMerge(valueDeser);
                 }
                 return prop;
             }
@@ -1292,7 +1292,7 @@
         Class<?> raw = _beanType.getRawClass();
         if (ClassUtil.isNonStaticInnerClass(raw)) {
             return ctxt.handleMissingInstantiator(raw, null, p,
-"can only instantiate non-static inner class by using default, no-argument constructor");
+"non-static inner classes like this can only by instantiated using default, no-argument constructor");
         }
         return ctxt.handleMissingInstantiator(raw, getValueInstantiator(), p,
                 "cannot deserialize from Object value (no delegate- or property-based Creator)");
@@ -1455,10 +1455,9 @@
             if (t == JsonToken.END_ARRAY) {
                 return null;
             }
-            return ctxt.handleUnexpectedToken(handledType(),
-                    JsonToken.START_ARRAY, p, null);
+            return ctxt.handleUnexpectedToken(getValueType(ctxt), JsonToken.START_ARRAY, p, null);
         }
-        return ctxt.handleUnexpectedToken(handledType(), p);
+        return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
     }
 
     public Object deserializeFromEmbedded(JsonParser p, DeserializationContext ctxt)
@@ -1548,23 +1547,27 @@
     /**
      * Helper method called for an unknown property, when using "vanilla"
      * processing.
+     *
+     * @param beanOrBuilder Either POJO instance (if constructed), or builder
+     *   (in case of builder-based approach), that has property we haven't been
+     *   able to handle yet.
      */
     protected void handleUnknownVanilla(JsonParser p, DeserializationContext ctxt,
-            Object bean, String propName)
+            Object beanOrBuilder, String propName)
         throws IOException
     {
         if (_ignorableProps != null && _ignorableProps.contains(propName)) {
-            handleIgnoredProperty(p, ctxt, bean, propName);
+            handleIgnoredProperty(p, ctxt, beanOrBuilder, propName);
         } else if (_anySetter != null) {
             try {
                // should we consider return type of any setter?
-                _anySetter.deserializeAndSet(p, ctxt, bean, propName);
+                _anySetter.deserializeAndSet(p, ctxt, beanOrBuilder, propName);
             } catch (Exception e) {
-                wrapAndThrow(e, bean, propName, ctxt);
+                wrapAndThrow(e, beanOrBuilder, propName, ctxt);
             }
         } else {
             // Unknown: let's call handler method
-            handleUnknownProperty(p, ctxt, bean, propName);         
+            handleUnknownProperty(p, ctxt, beanOrBuilder, propName);         
         }
     }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java
index c105307..a0879ed 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBuilder.java
@@ -449,6 +449,16 @@
             propertyMap = propertyMap.withProperty(prop);
         }
 
+        return createBuilderBasedDeserializer(valueType, propertyMap, anyViews);
+    }
+
+    /**
+     * Extension point for overriding the actual creation of the builder deserializer.
+     *
+     * @since 2.10.1 (officially in 2.10.0)
+     */
+    protected JsonDeserializer<?> createBuilderBasedDeserializer(JavaType valueType,
+            BeanPropertyMap propertyMap, boolean anyViews) {
         return new BuilderBasedDeserializer(this,
                 _beanDesc, valueType, propertyMap, _backRefProperties, _ignorableProps, _ignoreAllUnknown,
                 anyViews);
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java
index 1f02d70..0df42e0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerFactory.java
@@ -86,6 +86,7 @@
      * deserializer for types other than Collections, Maps, arrays and
      * enums.
      */
+    @SuppressWarnings("unchecked")
     @Override
     public JsonDeserializer<Object> createBeanDeserializer(DeserializationContext ctxt,
             JavaType type, BeanDescription beanDesc)
@@ -93,9 +94,15 @@
     {
         final DeserializationConfig config = ctxt.getConfig();
         // We may also have custom overrides:
-        JsonDeserializer<Object> custom = _findCustomBeanDeserializer(type, config, beanDesc);
-        if (custom != null) {
-            return custom;
+        JsonDeserializer<?> deser = _findCustomBeanDeserializer(type, config, beanDesc);
+        if (deser != null) {
+            // [databind#2392]
+            if (_factoryConfig.hasDeserializerModifiers()) {
+                for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
+                    deser = mod.modifyDeserializer(ctxt.getConfig(), beanDesc, deser);
+                }
+            }
+            return (JsonDeserializer<Object>) deser;
         }
         /* One more thing to check: do we have an exception type
          * (Throwable or its sub-classes)? If so, need slightly
@@ -121,10 +128,9 @@
             }
         }
         // Otherwise, may want to check handlers for standard types, from superclass:
-        @SuppressWarnings("unchecked")
-        JsonDeserializer<Object> deser = (JsonDeserializer<Object>) findStdDeserializer(ctxt, type, beanDesc);
+        deser = findStdDeserializer(ctxt, type, beanDesc);
         if (deser != null) {
-            return deser;
+            return (JsonDeserializer<Object>)deser;
         }
 
         // Otherwise: could the class be a Bean class? If not, bail out
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerModifier.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerModifier.java
index 0daeee2..6caa95b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerModifier.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerModifier.java
@@ -81,9 +81,13 @@
      * Method called by {@link BeanDeserializerFactory} after constructing default
      * bean deserializer instance with properties collected and ordered earlier.
      * Implementations can modify or replace given deserializer and return deserializer
-     * to use. Note that although initial deserializer being passed is of type
+     * to use. Note that although initial deserializer being passed is usually of type
      * {@link BeanDeserializer}, modifiers may return deserializers of other types;
      * and this is why implementations must check for type before casting.
+     *<p>
+     * Since 2.10 this is also called for custom deserializers for types not deemed to
+     * be of any more specific (reference, enum, array, collection(-like), map(-like),
+     * node type)
      */
     public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config,
             BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
@@ -97,6 +101,9 @@
      */
 
     /**
+     * Method called by {@link BeanDeserializerFactory} after constructing default
+     * enum type deserializer instance.
+     *
      * @since 2.2
      */
     public JsonDeserializer<?> modifyEnumDeserializer(DeserializationConfig config,
@@ -105,6 +112,9 @@
     }
 
     /**
+     * Method called by {@link BeanDeserializerFactory} after constructing default
+     * {@link ReferenceType} deserializer instance.
+     *
      * @since 2.7
      */
     public JsonDeserializer<?> modifyReferenceDeserializer(DeserializationConfig config,
@@ -135,6 +145,9 @@
     }
 
     /**
+     * Method called by {@link BeanDeserializerFactory} after constructing default
+     * {@link CollectionType} deserializer instance.
+     *
      * @since 2.2
      */
     public JsonDeserializer<?> modifyCollectionDeserializer(DeserializationConfig config,
@@ -143,6 +156,9 @@
     }
 
     /**
+     * Method called by {@link BeanDeserializerFactory} after constructing default
+     * {@link CollectionLikeType} deserializer instance.
+     *
      * @since 2.2
      */
     public JsonDeserializer<?> modifyCollectionLikeDeserializer(DeserializationConfig config,
@@ -151,6 +167,9 @@
     }
 
     /**
+     * Method called by {@link BeanDeserializerFactory} after constructing default
+     * {@link MapType} deserializer instance.
+     *
      * @since 2.2
      */
     public JsonDeserializer<?> modifyMapDeserializer(DeserializationConfig config,
@@ -159,6 +178,9 @@
     }
 
     /**
+     * Method called by {@link BeanDeserializerFactory} after constructing default
+     * {@link MapLikeType} deserializer instance.
+     *
      * @since 2.2
      */
     public JsonDeserializer<?> modifyMapLikeDeserializer(DeserializationConfig config,
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BuilderBasedDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/BuilderBasedDeserializer.java
index 4f7b345..a92cbb6 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/BuilderBasedDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/BuilderBasedDeserializer.java
@@ -216,7 +216,7 @@
             return finishBuild(ctxt, deserializeFromObject(p, ctxt));
         default:
         }
-        return ctxt.handleUnexpectedToken(handledType(), p);
+        return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
     }
 
     /**
@@ -468,7 +468,7 @@
                 }
                 continue;
             }
-            handleUnknownVanilla(p, ctxt, handledType(), propName);
+            handleUnknownVanilla(p, ctxt, builder, propName);
         }
         return builder;
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java
index f9badf8..04fa7c2 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/CreatorProperty.java
@@ -253,7 +253,21 @@
         _verifySetter();
         return _fallbackSetter.setAndReturn(instance, value);
     }
-    
+
+    @Override
+    public PropertyMetadata getMetadata() {
+        // 03-Jun-2019, tatu: Added as per [databind#2280] to support merge.
+        //   Not 100% sure why it would be needed (or fixes things) but... appears to.
+        //   Need to understand better in future as it seems like it should probably be
+        //   linked earlier during construction or something.
+        // 22-Sep-2019, tatu: Was hoping [databind#2458] fixed this, too, but no such luck
+        PropertyMetadata md = super.getMetadata();
+        if (_fallbackSetter != null) {
+            return md.withMergeInfo(_fallbackSetter.getMetadata().getMergeInfo());
+        }
+        return md;
+    }
+
     @Override
     public Object getInjectableValueId() {
         return _injectableValueId;
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java
index 38b8705..2d6b88c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializationProblemHandler.java
@@ -202,6 +202,24 @@
     }
 
     /**
+     * Deprecated variant of
+     * {@link #handleUnexpectedToken(DeserializationContext, JavaType, JsonToken, JsonParser, String)
+     *
+     * @since 2.8
+     *
+     * @deprecated Since 2.10
+     */
+    @SuppressWarnings("javadoc")
+    @Deprecated
+    public Object handleUnexpectedToken(DeserializationContext ctxt,
+            Class<?> targetType, JsonToken t, JsonParser p,
+            String failureMsg)
+        throws IOException
+    {
+        return NOT_HANDLED;
+    }
+
+    /**
      * Method that deserializers should call if the first token of the value to
      * deserialize is of unexpected type (that is, type of token that deserializer
      * cannot handle). This could occur, for example, if a Number deserializer
@@ -226,16 +244,17 @@
      *    what to do (and exception may be thrown), or value to use (possibly
      *    <code>null</code>
      *
-     * @since 2.8
+     * @since 2.10
      */
     public Object handleUnexpectedToken(DeserializationContext ctxt,
-            Class<?> targetType, JsonToken t, JsonParser p,
+            JavaType targetType, JsonToken t, JsonParser p,
             String failureMsg)
         throws IOException
     {
-        return NOT_HANDLED;
+        // Calling class-version handler for backward compatibility, as of 2.10
+        return handleUnexpectedToken(ctxt, targetType.getRawClass(), t, p, failureMsg);
     }
-    
+
     /**
      * Method called when instance creation for a type fails due to an exception.
      * Handler may choose to do one of following things:
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerCache.java b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerCache.java
index 8aff025..a46e431 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerCache.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/DeserializerCache.java
@@ -1,7 +1,6 @@
 package com.fasterxml.jackson.databind.deser;
 
 import java.util.HashMap;
-import java.util.concurrent.ConcurrentHashMap;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.databind.*;
@@ -10,6 +9,7 @@
 import com.fasterxml.jackson.databind.type.*;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 import com.fasterxml.jackson.databind.util.Converter;
+import com.fasterxml.jackson.databind.util.LRUMap;
 
 /**
  * Class that defines caching layer between callers (like
@@ -19,7 +19,7 @@
  * ({@link com.fasterxml.jackson.databind.deser.DeserializerFactory}).
  */
 public final class DeserializerCache
-    implements java.io.Serializable // since 2.1 -- needs to be careful tho
+    implements java.io.Serializable // since 2.1
 {
     private static final long serialVersionUID = 1L;
 
@@ -32,15 +32,9 @@
     /**
      * We will also cache some dynamically constructed deserializers;
      * specifically, ones that are expensive to construct.
-     * This currently means bean and Enum deserializers; starting with
-     * 2.5, container deserializers will also be cached.
-     *<p>
-     * Given that we don't expect much concurrency for additions
-     * (should very quickly converge to zero after startup), let's
-     * define a relatively low concurrency setting.
+     * This currently means bean, Enum and container deserializers.
      */
-    final protected ConcurrentHashMap<JavaType, JsonDeserializer<Object>> _cachedDeserializers
-        = new ConcurrentHashMap<JavaType, JsonDeserializer<Object>>(64, 0.75f, 4);
+    final protected LRUMap<JavaType, JsonDeserializer<Object>> _cachedDeserializers;
 
     /**
      * During deserializer construction process we may need to keep track of partially
@@ -56,7 +50,14 @@
     /**********************************************************
      */
 
-    public DeserializerCache() { }
+    public DeserializerCache() {
+        this(2000); // see [databind#1995]
+    }
+
+    public DeserializerCache(int maxSize) {
+        int initial = Math.min(64, maxSize>>2);
+        _cachedDeserializers = new LRUMap<>(initial, maxSize);
+    }
 
     /*
     /**********************************************************
@@ -67,7 +68,6 @@
     Object writeReplace() {
         // instead of making this transient, just clear it:
         _incompleteDeserializers.clear();
-        // TODO: clear out "cheap" cached deserializers?
         return this;
     }
     
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java
index 465562e..3f88e93 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/SettableAnyProperty.java
@@ -144,8 +144,7 @@
 
     public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
     {
-        JsonToken t = p.getCurrentToken();
-        if (t == JsonToken.VALUE_NULL) {
+        if (p.hasToken(JsonToken.VALUE_NULL)) {
             return _valueDeserializer.getNullValue(ctxt);
         }
         if (_valueTypeDeserializer != null) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/ValueInstantiator.java b/src/main/java/com/fasterxml/jackson/databind/deser/ValueInstantiator.java
index a7a6951..701ca68 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/ValueInstantiator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/ValueInstantiator.java
@@ -397,7 +397,10 @@
      * to be used instead of directly extending {@link ValueInstantiator} itself.
      */
     public static class Base extends ValueInstantiator
+        implements java.io.Serializable // just because used as base for "standard" variants
     {
+        private static final long serialVersionUID = 1L;
+
         protected final Class<?> _valueType;
 
         public Base(Class<?> type) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayBuilderDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayBuilderDeserializer.java
index 0dbc50d..6d3a507 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayBuilderDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayBuilderDeserializer.java
@@ -342,11 +342,9 @@
         throws IOException
     {
         // Let's start with failure
-        return ctxt.handleUnexpectedToken(handledType(), p.getCurrentToken(), p,
-                "Cannot deserialize a POJO (of type %s) from non-Array representation (token: %s): "
-                +"type/property designed to be serialized as JSON Array",
-                _beanType.getRawClass().getName(),
-                p.getCurrentToken());
+        String message = "Cannot deserialize a POJO (of type %s) from non-Array representation (token: %s): "
+            + "type/property designed to be serialized as JSON Array";
+        return ctxt.handleUnexpectedToken(getValueType(ctxt), p.getCurrentToken(), p, message, _beanType.getRawClass().getName(), p.getCurrentToken());
         // in future, may allow use of "standard" POJO serialization as well; if so, do:
         //return _delegate.deserialize(p, ctxt);
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayDeserializer.java
index 2b39004..832afd0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/BeanAsArrayDeserializer.java
@@ -362,11 +362,9 @@
     protected Object _deserializeFromNonArray(JsonParser p, DeserializationContext ctxt)
         throws IOException
     {
-        return ctxt.handleUnexpectedToken(handledType(), p.getCurrentToken(), p,
-                "Cannot deserialize a POJO (of type %s) from non-Array representation (token: %s): "
-                +"type/property designed to be serialized as JSON Array",
-                _beanType.getRawClass().getName(),
-                p.getCurrentToken());
+        String message = "Cannot deserialize a POJO (of type %s) from non-Array representation (token: %s): "
+                +"type/property designed to be serialized as JSON Array";
+        return ctxt.handleUnexpectedToken(getValueType(ctxt), p.getCurrentToken(), p, message, _beanType.getRawClass().getName(), p.getCurrentToken());
         // in future, may allow use of "standard" POJO serialization as well; if so, do:
         //return _delegate.deserialize(p, ctxt);
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java
index 978c408..65706bf 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/CreatorCollector.java
@@ -1,8 +1,6 @@
 package com.fasterxml.jackson.databind.deser.impl;
 
-import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Member;
-import java.lang.reflect.Type;
 import java.util.*;
 
 import com.fasterxml.jackson.databind.*;
@@ -91,14 +89,8 @@
                 _creators[C_ARRAY_DELEGATE], _arrayDelegateArgs);
         final JavaType type = _beanDesc.getType();
 
-        // 11-Jul-2016, tatu: Earlier optimization by replacing the whole
-        // instantiator did not
-        // work well, so let's replace by lower-level check:
-        AnnotatedWithParams defaultCtor = StdTypeConstructor
-                .tryToOptimize(_creators[C_DEFAULT]);
-
         StdValueInstantiator inst = new StdValueInstantiator(config, type);
-        inst.configureFromObjectSettings(defaultCtor, _creators[C_DELEGATE],
+        inst.configureFromObjectSettings(_creators[C_DEFAULT], _creators[C_DELEGATE],
                 delegateType, _delegateArgs, _creators[C_PROPS],
                 _propertyBasedArgs);
         inst.configureFromArraySettings(_creators[C_ARRAY_DELEGATE],
@@ -344,173 +336,7 @@
      * @since 2.8.1
      */
     protected boolean _isEnumValueOf(AnnotatedWithParams creator) {
-        return creator.getDeclaringClass().isEnum()
+        return ClassUtil.isEnumType(creator.getDeclaringClass())
                 && "valueOf".equals(creator.getName());
     }
-
-    /*
-    /**********************************************************
-    /* Helper class(es)
-    /**********************************************************
-     */
-
-    /**
-     * Replacement for default constructor to use for a small set of
-     * "well-known" types.
-     * <p>
-     * Note: replaces earlier <code>Vanilla</code>
-     * <code>ValueInstantiator</code> implementation
-     *
-     * @since 2.8.1 (replacing earlier <code>Vanilla</code> instantiator
-     */
-    protected final static class StdTypeConstructor extends AnnotatedWithParams
-            implements java.io.Serializable {
-        private static final long serialVersionUID = 1L;
-
-        public final static int TYPE_ARRAY_LIST = 1;
-        public final static int TYPE_HASH_MAP = 2;
-        public final static int TYPE_LINKED_HASH_MAP = 3;
-
-        private final AnnotatedWithParams _base;
-
-        private final int _type;
-
-        public StdTypeConstructor(AnnotatedWithParams base, int t) {
-            super(base, null);
-            _base = base;
-            _type = t;
-        }
-
-        public static AnnotatedWithParams tryToOptimize(
-                AnnotatedWithParams src) {
-            if (src != null) {
-                final Class<?> rawType = src.getDeclaringClass();
-                if (rawType == List.class || rawType == ArrayList.class) {
-                    return new StdTypeConstructor(src, TYPE_ARRAY_LIST);
-                }
-                if (rawType == LinkedHashMap.class) {
-                    return new StdTypeConstructor(src, TYPE_LINKED_HASH_MAP);
-                }
-                if (rawType == HashMap.class) {
-                    return new StdTypeConstructor(src, TYPE_HASH_MAP);
-                }
-            }
-            return src;
-        }
-
-        protected final Object _construct() {
-            switch (_type) {
-            case TYPE_ARRAY_LIST:
-                return new ArrayList<Object>();
-            case TYPE_LINKED_HASH_MAP:
-                return new LinkedHashMap<String, Object>();
-            case TYPE_HASH_MAP:
-                return new HashMap<String, Object>();
-            }
-            throw new IllegalStateException("Unknown type " + _type);
-        }
-
-        @Override
-        public int getParameterCount() {
-            return _base.getParameterCount();
-        }
-
-        @Override
-        public Class<?> getRawParameterType(int index) {
-            return _base.getRawParameterType(index);
-        }
-
-        @Override
-        public JavaType getParameterType(int index) {
-            return _base.getParameterType(index);
-        }
-
-        @Override
-        @Deprecated
-        public Type getGenericParameterType(int index) {
-            return _base.getGenericParameterType(index);
-        }
-
-        @Override
-        public Object call() throws Exception {
-            return _construct();
-        }
-
-        @Override
-        public Object call(Object[] args) throws Exception {
-            return _construct();
-        }
-
-        @Override
-        public Object call1(Object arg) throws Exception {
-            return _construct();
-        }
-
-        @Override
-        public Class<?> getDeclaringClass() {
-            return _base.getDeclaringClass();
-        }
-
-        @Override
-        public Member getMember() {
-            return _base.getMember();
-        }
-
-        @Override
-        public void setValue(Object pojo, Object value)
-                throws UnsupportedOperationException, IllegalArgumentException {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public Object getValue(Object pojo)
-                throws UnsupportedOperationException, IllegalArgumentException {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public Annotated withAnnotations(AnnotationMap fallback) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public AnnotatedElement getAnnotated() {
-            return _base.getAnnotated();
-        }
-
-        @Override
-        protected int getModifiers() {
-            return _base.getMember().getModifiers();
-        }
-
-        @Override
-        public String getName() {
-            return _base.getName();
-        }
-
-        @Override
-        public JavaType getType() {
-            return _base.getType();
-        }
-
-        @Override
-        public Class<?> getRawType() {
-            return _base.getRawType();
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            return (o == this);
-        }
-
-        @Override
-        public int hashCode() {
-            return _base.hashCode();
-        }
-
-        @Override
-        public String toString() {
-            return _base.toString();
-        }
-    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ExternalTypeHandler.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ExternalTypeHandler.java
index 4b30ce3..5168665 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/ExternalTypeHandler.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/ExternalTypeHandler.java
@@ -225,7 +225,7 @@
                     }
                     // 26-Oct-2012, tatu: As per [databind#94], must allow use of 'defaultImpl'
                     if (!_properties[i].hasDefaultType()) {
-                        ctxt.reportInputMismatch(bean.getClass(),
+                        ctxt.reportPropertyInputMismatch(bean.getClass(), extProp.getName(),
                                 "Missing external type id property '%s'",
                                 _properties[i].getTypePropertyName());                                
                     } else  {
@@ -237,7 +237,7 @@
 
                 if(prop.isRequired() ||
                         ctxt.isEnabled(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY)) {
-                    ctxt.reportInputMismatch(bean.getClass(),
+                    ctxt.reportPropertyInputMismatch(bean.getClass(), prop.getName(),
                             "Missing property '%s' for external type id '%s'",
                             prop.getName(), _properties[i].getTypePropertyName());
                 }
@@ -270,7 +270,7 @@
                 // but not just one
                 // 26-Oct-2012, tatu: As per [databind#94], must allow use of 'defaultImpl'
                 if (!extProp.hasDefaultType()) {
-                    ctxt.reportInputMismatch(_beanType,
+                    ctxt.reportPropertyInputMismatch(_beanType, extProp.getProperty().getName(),
                             "Missing external type id property '%s'",
                             extProp.getTypePropertyName());
                 } else {
@@ -280,7 +280,7 @@
                 SettableBeanProperty prop = extProp.getProperty();
                 if (prop.isRequired() ||
                         ctxt.isEnabled(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY)) {
-                    ctxt.reportInputMismatch(_beanType,
+                    ctxt.reportPropertyInputMismatch(_beanType, prop.getName(),
                             "Missing property '%s' for external type id '%s'",
                             prop.getName(), _properties[i].getTypePropertyName());
                 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/InnerClassProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/InnerClassProperty.java
index bdc72dd..eece109 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/InnerClassProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/InnerClassProperty.java
@@ -72,7 +72,7 @@
     public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object bean)
         throws IOException
     {
-        JsonToken t = p.getCurrentToken();
+        JsonToken t = p.currentToken();
         Object value;
         if (t == JsonToken.VALUE_NULL) {
             value = _valueDeserializer.getNullValue(ctxt);
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java
new file mode 100644
index 0000000..b8b7747
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/JDKValueInstantiators.java
@@ -0,0 +1,154 @@
+package com.fasterxml.jackson.databind.deser.impl;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.core.JsonLocation;
+import com.fasterxml.jackson.databind.DeserializationConfig;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.ValueInstantiator;
+import com.fasterxml.jackson.databind.deser.std.JsonLocationInstantiator;
+
+/**
+ * Container for a set of {@link ValueInstantiator}s used for certain critical
+ * JDK value types, either as performance optimization for initialization time observed
+ * by profiling, or due to difficulty in otherwise finding constructors.
+ *
+ * @since 2.10
+ */
+public abstract class JDKValueInstantiators
+{
+    public static ValueInstantiator findStdValueInstantiator(DeserializationConfig config,
+            Class<?> raw)
+    {
+        if (raw == JsonLocation.class) {
+            return new JsonLocationInstantiator();
+        }
+        // [databind#1868]: empty List/Set/Map
+        // [databind#2416]: optimize commonly needed default creators
+        if (Collection.class.isAssignableFrom(raw)) {
+            if (raw == ArrayList.class) {
+                return ArrayListInstantiator.INSTANCE;
+            }
+            if (Collections.EMPTY_SET.getClass() == raw) {
+                return new ConstantValueInstantiator(Collections.EMPTY_SET);
+            }
+            if (Collections.EMPTY_LIST.getClass() == raw) {
+                return new ConstantValueInstantiator(Collections.EMPTY_LIST);
+            }
+        } else if (Map.class.isAssignableFrom(raw)) {
+            if (raw == LinkedHashMap.class) {
+                return LinkedHashMapInstantiator.INSTANCE;
+            }
+            if (raw == HashMap.class) {
+                return HashMapInstantiator.INSTANCE;
+            }
+            if (Collections.EMPTY_MAP.getClass() == raw) {
+                return new ConstantValueInstantiator(Collections.EMPTY_MAP);
+            }
+        }
+        return null;
+    }
+
+    private static class ArrayListInstantiator
+        extends ValueInstantiator.Base
+        implements java.io.Serializable
+    {
+        private static final long serialVersionUID = 2L;
+
+        public final static ArrayListInstantiator INSTANCE = new ArrayListInstantiator();
+        public ArrayListInstantiator() {
+            super(ArrayList.class);
+        }
+
+        @Override
+        public boolean canInstantiate() { return true; }
+
+        @Override
+        public boolean canCreateUsingDefault() {  return true; }
+
+        @Override
+        public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
+            return new ArrayList<>();
+        }
+    }
+
+    private static class HashMapInstantiator
+        extends ValueInstantiator.Base
+        implements java.io.Serializable
+    {
+        private static final long serialVersionUID = 2L;
+
+        public final static HashMapInstantiator INSTANCE = new HashMapInstantiator();
+
+        public HashMapInstantiator() {
+            super(HashMap.class);
+        }
+
+        @Override
+        public boolean canInstantiate() { return true; }
+
+        @Override
+        public boolean canCreateUsingDefault() {  return true; }
+
+        @Override
+        public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
+            return new HashMap<>();
+        }
+    }
+
+    private static class LinkedHashMapInstantiator
+        extends ValueInstantiator.Base
+        implements java.io.Serializable
+    {
+        private static final long serialVersionUID = 2L;
+
+        public final static LinkedHashMapInstantiator INSTANCE = new LinkedHashMapInstantiator();
+
+        public LinkedHashMapInstantiator() {
+            super(LinkedHashMap.class);
+        }
+
+        @Override
+        public boolean canInstantiate() { return true; }
+
+        @Override
+        public boolean canCreateUsingDefault() {  return true; }
+
+        @Override
+        public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
+            return new LinkedHashMap<>();
+        }
+    }
+
+    private static class ConstantValueInstantiator
+        extends ValueInstantiator.Base
+        implements java.io.Serializable
+    {
+        private static final long serialVersionUID = 2L;
+
+        protected final Object _value;
+
+        public ConstantValueInstantiator(Object value) {
+            super(value.getClass());
+            _value = value;
+        }
+
+        @Override // yes, since default ctor works
+        public boolean canInstantiate() { return true; }
+
+        @Override
+        public boolean canCreateUsingDefault() {  return true; }
+
+        @Override
+        public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
+            return _value;
+        }
+    }
+
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/NullsFailProvider.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/NullsFailProvider.java
index ba870c7..7c6f9ba 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/NullsFailProvider.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/NullsFailProvider.java
@@ -23,7 +23,12 @@
     }
 
     public static NullsFailProvider constructForProperty(BeanProperty prop) {
-        return new NullsFailProvider(prop.getFullName(), prop.getType());
+        return constructForProperty(prop, prop.getType());
+    }
+
+    // @since 2.10.2
+    public static NullsFailProvider constructForProperty(BeanProperty prop, JavaType type) {
+        return new NullsFailProvider(prop.getFullName(), type);
     }
 
     public static NullsFailProvider constructForRootValue(JavaType t) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyBasedCreator.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyBasedCreator.java
index 566b54f..1a24c51 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyBasedCreator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyBasedCreator.java
@@ -114,7 +114,10 @@
         }
         return new PropertyBasedCreator(ctxt, valueInstantiator, creatorProps,
                 allProperties.isCaseInsensitive(),
-                allProperties.hasAliases());
+// 05-Sep-2019, tatu: As per [databind#2378] looks like not all aliases get merged into
+//    `allProperties` so force lookup anyway.
+//                allProperties.hasAliases()
+                true);
     }
 
     /**
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java
index 23f7503..95fa25e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java
@@ -10,6 +10,7 @@
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.deser.SettableAnyProperty;
 import com.fasterxml.jackson.databind.deser.SettableBeanProperty;
+import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
 
 /**
  * Simple container used for temporarily buffering a set of
@@ -171,7 +172,7 @@
             for (int ix = 0; ix < props.length; ++ix) {
                 if (_creatorParameters[ix] == null) {
                     SettableBeanProperty prop = props[ix];
-                    _context.reportInputMismatch(prop.getType(),
+                    _context.reportInputMismatch(prop,
                             "Null value for creator property '%s' (index %d); `DeserializationFeature.FAIL_ON_NULL_FOR_CREATOR_PARAMETERS` enabled",
                             prop.getName(), props[ix].getCreatorIndex());
                 }
@@ -198,9 +199,24 @@
                     "Missing creator property '%s' (index %d); `DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES` enabled",
                     prop.getName(), prop.getCreatorIndex());
         }
-        // Third: default value
-        JsonDeserializer<Object> deser = prop.getValueDeserializer();
-        return deser.getNullValue(_context);
+        try {
+            // Third: NullValueProvider? (22-Sep-2019, [databind#2458])
+            Object nullValue = prop.getNullValueProvider().getNullValue(_context);
+            if (nullValue != null) {
+                return nullValue;
+            }
+
+            // Fourth: default value
+            JsonDeserializer<Object> deser = prop.getValueDeserializer();
+            return deser.getNullValue(_context);
+        } catch (JsonMappingException e) {
+            // [databind#2101]: Include property name, if we have it
+            AnnotatedMember member = prop.getMember();
+            if (member != null) {
+                e.prependPath(member.getDeclaringClass(), prop.getName());
+            }
+            throw e;
+        }
     }
 
     /*
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java
index a901f07..9c80e49 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java
@@ -103,8 +103,7 @@
     public final void deserializeAndSet(JsonParser p, DeserializationContext ctxt,
             Object instance) throws IOException
     {
-        JsonToken t = p.getCurrentToken();
-        if (t == JsonToken.VALUE_NULL) {
+        if (p.hasToken(JsonToken.VALUE_NULL)) {
             // Hmmh. Is this a problem? We won't be setting anything, so it's
             // equivalent of empty Collection/Map in this case
             return;
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ArrayBlockingQueueDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ArrayBlockingQueueDeserializer.java
index c92c8a4..94db832 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ArrayBlockingQueueDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ArrayBlockingQueueDeserializer.java
@@ -94,10 +94,13 @@
         }
         // Ok: must point to START_ARRAY (or equivalent)
         if (!p.isExpectedStartArrayToken()) {
-            return handleNonArray(p, ctxt, new ArrayBlockingQueue<Object>(1));
+            return handleNonArray(p, ctxt, new ArrayBlockingQueue<>(1));
         }
-        result0 = super.deserialize(p, ctxt, new ArrayList<Object>());
-        return new ArrayBlockingQueue<Object>(result0.size(), false, result0);
+        result0 = super.deserialize(p, ctxt, new ArrayList<>());
+        if (result0.isEmpty()) {
+            return new ArrayBlockingQueue<>(1, false);
+        }
+        return new ArrayBlockingQueue<>(result0.size(), false, result0);
     }
 
     @Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/AtomicReferenceDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/AtomicReferenceDeserializer.java
index 486106c..75af284 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/AtomicReferenceDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/AtomicReferenceDeserializer.java
@@ -40,14 +40,18 @@
 
     @Override
     public AtomicReference<Object> getNullValue(DeserializationContext ctxt) throws JsonMappingException {
+        // 07-May-2019, tatu: [databind#2303], needed for nested ReferenceTypes
         return new AtomicReference<Object>(_valueDeserializer.getNullValue(ctxt));
     }
 
     @Override
-    public Object getEmptyValue(DeserializationContext ctxt) {
-        return new AtomicReference<Object>();
+    public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException {
+        // 07-May-2019, tatu: I _think_ this needs to align with "null value" and
+        //    not necessarily with empty value of contents? (used to just do "absent"
+        //    so either way this seems to me like an improvement)
+        return getNullValue(ctxt);
     }
-    
+
     @Override
     public AtomicReference<Object> referenceValue(Object contents) {
         return new AtomicReference<Object>(contents);
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/CollectionDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/CollectionDeserializer.java
index c255d89..9b37ecb 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/CollectionDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/CollectionDeserializer.java
@@ -329,16 +329,15 @@
                 ((_unwrapSingle == null) &&
                         ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY));
         if (!canWrap) {
-            return (Collection<Object>) ctxt.handleUnexpectedToken(_containerType.getRawClass(), p);
+            return (Collection<Object>) ctxt.handleUnexpectedToken(_containerType, p);
         }
         JsonDeserializer<Object> valueDes = _valueDeserializer;
         final TypeDeserializer typeDeser = _valueTypeDeserializer;
-        JsonToken t = p.getCurrentToken();
 
         Object value;
 
         try {
-            if (t == JsonToken.VALUE_NULL) {
+            if (p.hasToken(JsonToken.VALUE_NULL)) {
                 // 03-Feb-2017, tatu: Hmmh. I wonder... let's try skipping here, too
                 if (_skipNullValues) {
                     return result;
@@ -350,6 +349,10 @@
                 value = valueDes.deserializeWithType(p, ctxt, typeDeser);
             }
         } catch (Exception e) {
+            boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS);
+            if (!wrap) {
+                ClassUtil.throwIfRTE(e);
+            }
             // note: pass Object.class, not Object[].class, as we need element type for error info
             throw JsonMappingException.wrapWithPath(e, Object.class, result.size());
         }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ContainerDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ContainerDeserializerBase.java
index 123cf6b..46c1537 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ContainerDeserializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ContainerDeserializerBase.java
@@ -31,6 +31,14 @@
     protected final NullValueProvider _nullProvider;
 
     /**
+     * Marker flag set if the <code>_nullProvider</code> indicates that all null
+     * content values should be skipped (instead of being possibly converted).
+     *
+     * @since 2.9
+     */
+    protected final boolean _skipNullValues;
+
+    /**
      * Specific override for this instance (from proper, or global per-type overrides)
      * to indicate whether single value may be taken to mean an unwrapped one-element array
      * or not. If null, left to global defaults.
@@ -39,14 +47,6 @@
      */
     protected final Boolean _unwrapSingle;
 
-    /**
-     * Marker flag set if the <code>_nullProvider</code> indicates that all null
-     * content values should be skipped (instead of being possibly converted).
-     *
-     * @since 2.9
-     */
-    protected final boolean _skipNullValues;
-
     protected ContainerDeserializerBase(JavaType selfType,
             NullValueProvider nuller, Boolean unwrapSingle) {
         super(selfType);
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java
index c697e1c..f8cb551 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumDeserializer.java
@@ -167,7 +167,7 @@
     @Override
     public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
     {
-        JsonToken curr = p.getCurrentToken();
+        JsonToken curr = p.currentToken();
         
         // Usually should just get string value:
         if (curr == JsonToken.VALUE_STRING || curr == JsonToken.FIELD_NAME) {
@@ -253,7 +253,7 @@
         }
         if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
             return ctxt.handleWeirdStringValue(_enumClass(), name,
-                    "value not one of declared Enum instance names: %s", lookup.keys());
+                    "not one of the values accepted for Enum class: %s",  lookup.keys());
         }
         return null;
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java
index f61b17c..37e5039 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java
@@ -19,7 +19,7 @@
  * Deserializer for {@link EnumMap} values.
  * <p>
  * Note: casting within this class is all messed up -- just could not figure out a way
- * to properly deal with recursive definition of "EnumMap&lt;K extends Enum&lt;K>, V>
+ * to properly deal with recursive definition of "EnumMap&lt;K extends Enum&lt;K&gt;, V&gt;
  */
 @SuppressWarnings({ "unchecked", "rawtypes" }) 
 public class EnumMapDeserializer
@@ -235,7 +235,7 @@
                     _delegateDeserializer.deserialize(p, ctxt));
         }
         // Ok: must point to START_OBJECT
-        JsonToken t = p.getCurrentToken();
+        JsonToken t = p.currentToken();
         if ((t != JsonToken.START_OBJECT) && (t != JsonToken.FIELD_NAME) && (t != JsonToken.END_OBJECT)) {
             // (empty) String may be ok however; or single-String-arg ctor
             if (t == JsonToken.VALUE_STRING) {
@@ -263,7 +263,7 @@
         if (p.isExpectedStartObjectToken()) {
             keyStr = p.nextFieldName();
         } else {
-            JsonToken t = p.getCurrentToken();
+            JsonToken t = p.currentToken();
             if (t != JsonToken.FIELD_NAME) {
                 if (t == JsonToken.END_OBJECT) {
                     return result;
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumSetDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumSetDeserializer.java
index 08ceee8..93eb07e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumSetDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/EnumSetDeserializer.java
@@ -7,7 +7,11 @@
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
+import com.fasterxml.jackson.databind.deser.NullValueProvider;
+import com.fasterxml.jackson.databind.deser.impl.NullsConstantProvider;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
+import com.fasterxml.jackson.databind.util.AccessPattern;
+import com.fasterxml.jackson.databind.util.ClassUtil;
 
 /**
  * Standard deserializer for {@link EnumSet}s.
@@ -29,6 +33,21 @@
     protected JsonDeserializer<Enum<?>> _enumDeserializer;
 
     /**
+     * Handler we need for dealing with nulls.
+     *
+     * @since 2.10.1
+     */
+    protected final NullValueProvider _nullProvider;
+
+    /**
+     * Marker flag set if the <code>_nullProvider</code> indicates that all null
+     * content values should be skipped (instead of being possibly converted).
+     *
+     * @since 2.10.1
+     */
+    protected final boolean _skipNullValues;
+
+    /**
      * Specific override for this instance (from proper, or global per-type overrides)
      * to indicate whether single value may be taken to mean an unwrapped one-element array
      * or not. If null, left to global defaults.
@@ -50,23 +69,37 @@
         _enumType = enumType;
         _enumClass = (Class<Enum>) enumType.getRawClass();
         // sanity check
-        if (!_enumClass.isEnum()) {
+        if (!ClassUtil.isEnumType(_enumClass)) {
             throw new IllegalArgumentException("Type "+enumType+" not Java Enum type");
         }
         _enumDeserializer = (JsonDeserializer<Enum<?>>) deser;
         _unwrapSingle = null;
+        _nullProvider = null;
+        _skipNullValues = false;
     }
 
     /**
      * @since 2.7
+     * @deprecated Since 2.10.1
+     */
+    @Deprecated
+    protected EnumSetDeserializer(EnumSetDeserializer base,
+            JsonDeserializer<?> deser, Boolean unwrapSingle) {
+        this(base, deser, base._nullProvider, unwrapSingle);
+    }
+
+    /**
+     * @since 2.10.1
      */
     @SuppressWarnings("unchecked" )
     protected EnumSetDeserializer(EnumSetDeserializer base,
-            JsonDeserializer<?> deser, Boolean unwrapSingle) {
+            JsonDeserializer<?> deser, NullValueProvider nuller, Boolean unwrapSingle) {
         super(base);
         _enumType = base._enumType;
         _enumClass = base._enumClass;
         _enumDeserializer = (JsonDeserializer<Enum<?>>) deser;
+        _nullProvider = nuller;
+        _skipNullValues = NullsConstantProvider.isSkipper(nuller);
         _unwrapSingle = unwrapSingle;
     }
 
@@ -74,16 +107,31 @@
         if (_enumDeserializer == deser) {
             return this;
         }
-        return new EnumSetDeserializer(this, deser, _unwrapSingle);
+        return new EnumSetDeserializer(this, deser, _nullProvider, _unwrapSingle);
     }
 
+    @Deprecated // since 2.10.1
     public EnumSetDeserializer withResolved(JsonDeserializer<?> deser, Boolean unwrapSingle) {
-        if ((_unwrapSingle == unwrapSingle) && (_enumDeserializer == deser)) {
+        return withResolved(deser, _nullProvider, unwrapSingle);
+    }
+
+    /**
+     * @since 2.10.1
+     */
+    public EnumSetDeserializer withResolved(JsonDeserializer<?> deser, NullValueProvider nuller,
+            Boolean unwrapSingle) {
+        if ((_unwrapSingle == unwrapSingle) && (_enumDeserializer == deser) && (_nullProvider == deser)) {
             return this;
         }
-        return new EnumSetDeserializer(this, deser, unwrapSingle);
+        return new EnumSetDeserializer(this, deser, nuller, unwrapSingle);
     }
 
+    /*
+    /**********************************************************
+    /* Basic metadata
+    /**********************************************************
+     */
+    
     /**
      * Because of costs associated with constructing Enum resolvers,
      * let's cache instances by default.
@@ -102,11 +150,27 @@
         return Boolean.TRUE;
     }
 
+    @Override // since 2.10.1
+    public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException {
+        return constructSet();
+    }
+
+    @Override // since 2.10.1
+    public AccessPattern getEmptyAccessPattern() {
+        return AccessPattern.DYNAMIC;
+    }
+
+    /*
+    /**********************************************************
+    /* Contextualization
+    /**********************************************************
+     */
+
     @Override
     public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
             BeanProperty property) throws JsonMappingException
     {
-        Boolean unwrapSingle = findFormatFeature(ctxt, property, EnumSet.class,
+        final Boolean unwrapSingle = findFormatFeature(ctxt, property, EnumSet.class,
                 JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
         JsonDeserializer<?> deser = _enumDeserializer;
         if (deser == null) {
@@ -114,7 +178,7 @@
         } else { // if directly assigned, probably not yet contextual, so:
             deser = ctxt.handleSecondaryContextualization(deser, property, _enumType);
         }
-        return withResolved(deser, unwrapSingle);
+        return withResolved(deser, findContentNullProvider(ctxt, property, deser), unwrapSingle);
     }
 
     /*
@@ -153,18 +217,18 @@
 
         try {
             while ((t = p.nextToken()) != JsonToken.END_ARRAY) {
-                /* What to do with nulls? Fail or ignore? Fail, for now
-                 * (note: would fail if we passed it to EnumDeserializer, too,
-                 * but in general nulls should never be passed to non-container
-                 * deserializers)
-                 */
+                // What to do with nulls? Fail or ignore? Fail, for now (note: would fail if we
+                // passed it to EnumDeserializer, too, but in general nulls should never be passed
+                // to non-container deserializers)
+                Enum<?> value;
                 if (t == JsonToken.VALUE_NULL) {
-                    return (EnumSet<?>) ctxt.handleUnexpectedToken(_enumClass, p);
+                    if (_skipNullValues) {
+                        continue;
+                    }
+                    value = (Enum<?>) _nullProvider.getNullValue(ctxt);
+                } else {
+                    value = _enumDeserializer.deserialize(p, ctxt);
                 }
-                Enum<?> value = _enumDeserializer.deserialize(p, ctxt);
-                /* 24-Mar-2012, tatu: As per [JACKSON-810], may actually get nulls;
-                 *    but EnumSets don't allow nulls so need to skip.
-                 */
                 if (value != null) { 
                     result.add(value);
                 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/FactoryBasedEnumDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/FactoryBasedEnumDeserializer.java
index 86a68d9..c189eef 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/FactoryBasedEnumDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/FactoryBasedEnumDeserializer.java
@@ -110,7 +110,7 @@
         if (_deser != null) {
             value = _deser.deserialize(p, ctxt);
         } else if (_hasArgs) {
-            JsonToken curr = p.getCurrentToken();
+            JsonToken curr = p.currentToken();
             //There can be a JSON object passed for deserializing an Enum,
             //the below case handles it.
             if (curr == JsonToken.VALUE_STRING || curr == JsonToken.FIELD_NAME) {
@@ -161,7 +161,7 @@
     {
         PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, null);
     
-        JsonToken t = p.getCurrentToken();
+        JsonToken t = p.currentToken();
         for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
             String propName = p.getCurrentName();
             p.nextToken(); // to point to value
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java
index 68187c1..b133835 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/FromStringDeserializer.java
@@ -24,7 +24,7 @@
  * can be coerced into text, like Numbers and Booleans).
  * Simple JSON String values are trimmed using {@link java.lang.String#trim}.
  * Partial deserializer implementation will try to first access current token as
- * a String, calls {@link #_deserialize(String,DeserializationContext)} and
+ * a String, calls {@code _deserialize(String,DeserializationContext)} and
  * returns return value.
  * If this does not work (current token not a simple scalar type), attempts
  * are made so that:
@@ -158,7 +158,7 @@
             throw e;
             // nothing to do here, yet? We'll fail anyway
         }
-        JsonToken t = p.getCurrentToken();
+        JsonToken t = p.currentToken();
         // [databind#381]
         if (t == JsonToken.START_ARRAY) {
             return _deserializeFromArray(p, ctxt);
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java
index be32d08..ac47b1a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonLocationInstantiator.java
@@ -18,6 +18,8 @@
 public class JsonLocationInstantiator
     extends ValueInstantiator.Base
 {
+    private static final long serialVersionUID = 1L;
+
     public JsonLocationInstantiator() {
         super(JsonLocation.class);
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonNodeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonNodeDeserializer.java
index 01937fe..fcc4ab8 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonNodeDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/JsonNodeDeserializer.java
@@ -52,7 +52,7 @@
 
     @Override
     public JsonNode getNullValue(DeserializationContext ctxt) {
-        return NullNode.getInstance();
+        return ctxt.getNodeFactory().nullNode();
     }
 
     /**
@@ -63,7 +63,7 @@
     @Override
     public JsonNode deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
     {
-        switch (p.getCurrentTokenId()) {
+        switch (p.currentTokenId()) {
         case JsonTokenId.ID_START_OBJECT:
             return deserializeObject(p, ctxt, ctxt.getNodeFactory());
         case JsonTokenId.ID_START_ARRAY:
@@ -223,8 +223,11 @@
     {
         // [databind#237]: Report an error if asked to do so:
         if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY)) {
+            // 11-Sep-2019, tatu: Can not pass "property name" because we may be
+            //    missing enclosing JSON content context...
+// ctxt.reportPropertyInputMismatch(JsonNode.class, fieldName,
             ctxt.reportInputMismatch(JsonNode.class,
-                    "Duplicate field '%s' for ObjectNode: not allowed when FAIL_ON_READING_DUP_TREE_KEY enabled",
+"Duplicate field '%s' for `ObjectNode`: not allowed when `DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY` enabled",
                     fieldName);
         }
     }
@@ -508,11 +511,11 @@
             }
         }
     }
-    
+
     protected final JsonNode deserializeAny(JsonParser p, DeserializationContext ctxt,
             final JsonNodeFactory nodeFactory) throws IOException
     {
-        switch (p.getCurrentTokenId()) {
+        switch (p.currentTokenId()) {
         case JsonTokenId.ID_END_OBJECT: // for empty JSON Objects we may point to this?
             return nodeFactory.objectNode();
         case JsonTokenId.ID_FIELD_NAME:
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java
index 5e4bb35..fccdf1a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java
@@ -668,7 +668,11 @@
                 Object old = result.get(key);
                 Object value;
                 if (old != null) {
-                    value = valueDes.deserialize(p, ctxt, old);
+                    if (typeDeser == null) {
+                        value = valueDes.deserialize(p, ctxt, old);
+                    } else {
+                        value = valueDes.deserializeWithType(p, ctxt, typeDeser, old);
+                    }
                 } else if (typeDeser == null) {
                     value = valueDes.deserialize(p, ctxt);
                 } else {
@@ -685,7 +689,7 @@
 
     /**
      * Optimized method used when keys can be deserialized as plain old
-     * {@link java.lang.String}s, and there is no custom deserialized
+     * {@link java.lang.String}s, and there is no custom deserializer
      * specified.
      *
      * @since 2.9
@@ -731,7 +735,11 @@
                 Object old = result.get(key);
                 Object value;
                 if (old != null) {
-                    value = valueDes.deserialize(p, ctxt, old);
+                    if (typeDeser == null) {
+                        value = valueDes.deserialize(p, ctxt, old);
+                    } else {
+                        value = valueDes.deserializeWithType(p, ctxt, typeDeser, old);
+                    }
                 } else if (typeDeser == null) {
                     value = valueDes.deserialize(p, ctxt);
                 } else {
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapEntryDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapEntryDeserializer.java
index 2805c6b..7434013 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapEntryDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapEntryDeserializer.java
@@ -167,7 +167,7 @@
     public Map.Entry<Object,Object> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
     {
         // Ok: must point to START_OBJECT, FIELD_NAME or END_OBJECT
-        JsonToken t = p.getCurrentToken();
+        JsonToken t = p.currentToken();
         if (t != JsonToken.START_OBJECT && t != JsonToken.FIELD_NAME && t != JsonToken.END_OBJECT) {
             // String may be ok however:
             // slightly redundant (since String was passed above), but
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/NullifyingDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/NullifyingDeserializer.java
index bd58ecc..64b337a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/NullifyingDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/NullifyingDeserializer.java
@@ -57,7 +57,7 @@
     {
         // Not sure if we need to bother but:
 
-        switch (p.getCurrentTokenId()) {
+        switch (p.currentTokenId()) {
         case JsonTokenId.ID_START_ARRAY:
         case JsonTokenId.ID_START_OBJECT:
         case JsonTokenId.ID_FIELD_NAME:
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java
index 017317d..09980b1 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ObjectArrayDeserializer.java
@@ -321,18 +321,16 @@
                         ctxt.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY));
         if (!canWrap) {
             // One exception; byte arrays are generally serialized as base64, so that should be handled
-            JsonToken t = p.getCurrentToken();
-            if (t == JsonToken.VALUE_STRING
+            if (p.hasToken(JsonToken.VALUE_STRING)
                     // note: not `byte[]`, but `Byte[]` -- former is primitive array
                     && _elementClass == Byte.class) {
                 return deserializeFromBase64(p, ctxt);
             }
             return (Object[]) ctxt.handleUnexpectedToken(_containerType.getRawClass(), p);
         }
-        JsonToken t = p.getCurrentToken();
+
         Object value;
-        
-        if (t == JsonToken.VALUE_NULL) {
+        if (p.hasToken(JsonToken.VALUE_NULL)) {
             // 03-Feb-2017, tatu: Should this be skipped or not?
             if (_skipNullValues) {
                 return NO_OBJECTS;
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/PrimitiveArrayDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/PrimitiveArrayDeserializers.java
index 175db71..78a8095 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/PrimitiveArrayDeserializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/PrimitiveArrayDeserializers.java
@@ -110,9 +110,11 @@
             nuller = NullsConstantProvider.skipper();
         } else if (nullStyle == Nulls.FAIL) {
             if (property == null) {
-                nuller = NullsFailProvider.constructForRootValue(ctxt.constructType(_valueClass));
+                // 09-Dec-2019, tatu: [databind#2567] need to ensure correct target type
+                nuller = NullsFailProvider.constructForRootValue(ctxt.constructType(_valueClass.getComponentType()));
             } else {
-                nuller = NullsFailProvider.constructForProperty(property);
+                // 09-Dec-2019, tatu: [databind#2567] need to ensure correct target type
+                nuller = NullsFailProvider.constructForProperty(property, property.getType().getContentType());
             }
         }
         if ((unwrapSingle == _unwrapSingle) && (nuller == _nuller)) {
@@ -198,29 +200,7 @@
     /* Helper methods for sub-classes
     /********************************************************
      */
-    
-    /*
-     * Convenience method that constructs a concatenation of two arrays,
-     * with the type they have.
-     *
-     * @since 2.9
-    @SuppressWarnings("unchecked")
-    public static <T> T concatArrays(T array1, T array2)
-    {
-        int len1 = Array.getLength(array1);
-        if (len1 == 0) {
-            return array2;
-        }
-        int len2 = Array.getLength(array2);
-        if (len2 == 0) {
-            return array1;
-        }
-        Object result = Arrays.copyOf((Object[]) array1, len1 + len2);
-        System.arraycopy(array2, 0, result, len1, len2);
-        return (T) result;
-    }
-    */
-    
+
     @SuppressWarnings("unchecked")
     protected T handleNonArray(JsonParser p, DeserializationContext ctxt) throws IOException
     {
@@ -281,8 +261,7 @@
              * convert other tokens to Strings... but let's not bother
              * yet, doesn't seem to make sense)
              */
-            JsonToken t = p.getCurrentToken();
-            if (t == JsonToken.VALUE_STRING) {
+            if (p.hasToken(JsonToken.VALUE_STRING)) {
                 // note: can NOT return shared internal buffer, must copy:
                 char[] buffer = p.getTextCharacters();
                 int offset = p.getTextOffset();
@@ -295,6 +274,7 @@
             if (p.isExpectedStartArrayToken()) {
                 // Let's actually build as a String, then get chars
                 StringBuilder sb = new StringBuilder(64);
+                JsonToken t;
                 while ((t = p.nextToken()) != JsonToken.END_ARRAY) {
                     String str;
                     if (t == JsonToken.VALUE_STRING) {
@@ -319,7 +299,7 @@
                 return sb.toString().toCharArray();
             }
             // or, maybe an embedded object?
-            if (t == JsonToken.VALUE_EMBEDDED_OBJECT) {
+            if (p.hasToken(JsonToken.VALUE_EMBEDDED_OBJECT)) {
                 Object ob = p.getEmbeddedObject();
                 if (ob == null) return null;
                 if (ob instanceof char[]) {
@@ -468,7 +448,7 @@
         @Override
         public byte[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
         {
-            JsonToken t = p.getCurrentToken();
+            JsonToken t = p.currentToken();
             
             // Most likely case: base64 encoded String?
             if (t == JsonToken.VALUE_STRING) {
@@ -538,7 +518,7 @@
                 DeserializationContext ctxt) throws IOException
         {
             byte value;
-            JsonToken t = p.getCurrentToken();
+            JsonToken t = p.currentToken();
             if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) {
                 // should we catch overflow exceptions?
                 value = p.getByteValue();
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ReferenceTypeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ReferenceTypeDeserializer.java
index 34e502d..8c96af3 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ReferenceTypeDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ReferenceTypeDeserializer.java
@@ -218,8 +218,7 @@
     public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
             TypeDeserializer typeDeserializer) throws IOException
     {
-        final JsonToken t = p.getCurrentToken();
-        if (t == JsonToken.VALUE_NULL) { // can this actually happen?
+        if (p.hasToken(JsonToken.VALUE_NULL)) { // can this actually happen?
             return getNullValue(ctxt);
         }
         // 22-Oct-2015, tatu: This handling is probably not needed (or is wrong), but
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StackTraceElementDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StackTraceElementDeserializer.java
index fcfba10..a7b6022 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StackTraceElementDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StackTraceElementDeserializer.java
@@ -18,7 +18,7 @@
     @Override
     public StackTraceElement deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
     {
-        JsonToken t = p.getCurrentToken();
+        JsonToken t = p.currentToken();
         // Must get an Object
         if (t == JsonToken.START_OBJECT) {
             String className = "", methodName = "", fileName = "";
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java
index 9a6f482..dc4f3ae 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdDeserializer.java
@@ -6,6 +6,7 @@
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.Nulls;
 import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.core.exc.InputCoercionException;
 import com.fasterxml.jackson.core.io.NumberInput;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
@@ -40,7 +41,7 @@
      *
      * @since 2.6
      */
-    protected final static int F_MASK_INT_COERCIONS = 
+    protected final static int F_MASK_INT_COERCIONS =
             DeserializationFeature.USE_BIG_INTEGER_FOR_INTS.getMask()
             | DeserializationFeature.USE_LONG_FOR_INTS.getMask();
 
@@ -49,7 +50,7 @@
             DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS.getMask() |
             DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT.getMask();
 
-    
+
     /**
      * Type of values this deserializer handles: sometimes
      * exact types, other time most specific supertype of
@@ -58,23 +59,28 @@
      */
     final protected Class<?> _valueClass;
 
+    final protected JavaType _valueType;
+
     protected StdDeserializer(Class<?> vc) {
         _valueClass = vc;
+        _valueType = null;
     }
 
     protected StdDeserializer(JavaType valueType) {
         // 26-Sep-2017, tatu: [databind#1764] need to add null-check back until 3.x
         _valueClass = (valueType == null) ? Object.class : valueType.getRawClass();
+        _valueType = valueType;
     }
 
     /**
      * Copy-constructor for sub-classes to use, most often when creating
      * new instances for {@link com.fasterxml.jackson.databind.deser.ContextualDeserializer}.
-     * 
+     *
      * @since 2.5
      */
     protected StdDeserializer(StdDeserializer<?> src) {
         _valueClass = src._valueClass;
+        _valueType = src._valueType;
     }
 
     /*
@@ -82,7 +88,7 @@
     /* Accessors
     /**********************************************************
      */
-    
+
     @Override
     public Class<?> handledType() { return _valueClass; }
     
@@ -100,10 +106,28 @@
 
     /**
      * Exact structured type this deserializer handles, if known.
-     *<p>
-     * Default implementation just returns null.
      */
-    public JavaType getValueType() { return null; }
+    public JavaType getValueType() { return _valueType; }
+
+    /**
+     * Convenience method for getting handled type as {@link JavaType}, regardless
+     * of whether deserializer has one already resolved (and accessible via
+     * {@link #getValueType()}) or not: equivalent to:
+     *<pre>
+     *   if (getValueType() != null) {
+     *        return getValueType();
+     *   }
+     *   return ctxt.constructType(handledType());
+     *</pre>
+     * 
+     * @since 2.10
+     */
+    public JavaType getValueType(DeserializationContext ctxt) {
+        if (_valueType != null) {
+            return _valueType;
+        }
+        return ctxt.constructType(_valueClass);
+    }
 
     /**
      * Method that can be called to determine if given deserializer is the default
@@ -124,7 +148,7 @@
     /* Partial JsonDeserializer implementation 
     /**********************************************************
      */
-    
+
     /**
      * Base implementation that does not assume specific type
      * inclusion mechanism. Sub-classes are expected to override
@@ -181,7 +205,7 @@
             p.nextToken();
             final boolean parsed = _parseBooleanPrimitive(p, ctxt);
             _verifyEndArrayForSingle(p, ctxt);
-            return parsed;            
+            return parsed;
         }
         // Otherwise, no can do:
         return ((Boolean) ctxt.handleUnexpectedToken(_valueClass, p)).booleanValue();
@@ -253,7 +277,7 @@
                 p.nextToken();
                 final int parsed = _parseIntPrimitive(p, ctxt);
                 _verifyEndArrayForSingle(p, ctxt);
-                return parsed;            
+                return parsed;
             }
             break;
         default:
@@ -285,7 +309,7 @@
             return _nonNullNumber(v).intValue();
         }
     }
-    
+
     protected final long _parseLongPrimitive(JsonParser p, DeserializationContext ctxt)
         throws IOException
     {
@@ -359,7 +383,7 @@
                 p.nextToken();
                 final float parsed = _parseFloatPrimitive(p, ctxt);
                 _verifyEndArrayForSingle(p, ctxt);
-                return parsed;            
+                return parsed;
             }
             break;
         }
@@ -420,7 +444,7 @@
                 p.nextToken();
                 final double parsed = _parseDoublePrimitive(p, ctxt);
                 _verifyEndArrayForSingle(p, ctxt);
-                return parsed;            
+                return parsed;
             }
             break;
         }
@@ -454,7 +478,7 @@
         try {
             return parseDouble(text);
         } catch (IllegalArgumentException iae) { }
-        Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text, 
+        Number v = (Number) ctxt.handleWeirdStringValue(_valueClass, text,
                 "not a valid double value (as String to convert)");
         return _nonNullNumber(v).doubleValue();
     }
@@ -470,7 +494,9 @@
                 long ts;
                 try {
                     ts = p.getLongValue();
-                } catch (JsonParseException e) {
+                // 16-Jan-2019, tatu: 2.10 uses InputCoercionException, earlier JsonParseException
+                //     (but leave both until 3.0)
+                } catch (JsonParseException | InputCoercionException e) {
                     Number v = (Number) ctxt.handleWeirdNumberValue(_valueClass, p.getNumberValue(),
                             "not a valid 64-bit long for creating `java.util.Date`");
                     ts = v.longValue();
@@ -500,7 +526,7 @@
             if (ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)) {
                 final Date parsed = _parseDate(p, ctxt);
                 _verifyEndArrayForSingle(p, ctxt);
-                return parsed;            
+                return parsed;
             }
         } else {
             t = p.getCurrentToken();
@@ -539,11 +565,11 @@
         }
         return Double.parseDouble(numStr);
     }
-    
+
     /**
      * Helper method used for accessing String value, if possible, doing
      * necessary conversion or throwing exception as necessary.
-     * 
+     *
      * @since 2.1
      */
     protected final String _parseString(JsonParser p, DeserializationContext ctxt) throws IOException
@@ -552,6 +578,19 @@
         if (t == JsonToken.VALUE_STRING) {
             return p.getText();
         }
+        // 07-Nov-2019, tatu: [databind#2535] Need to support byte[]->Base64 same as `StringDeserializer`
+        if (t == JsonToken.VALUE_EMBEDDED_OBJECT) {
+            Object ob = p.getEmbeddedObject();
+            if (ob instanceof byte[]) {
+                return ctxt.getBase64Variant().encode((byte[]) ob, false);
+            }
+            if (ob == null) {
+                return null;
+            }
+            // otherwise, try conversion using toString()...
+            return ob.toString();
+        }
+
         // 07-Nov-2016, tatu: Caller should take care of unwrapping and there shouldn't
         //    be need for extra pass here...
         /*
@@ -573,7 +612,7 @@
     /**
      * Helper method that may be used to support fallback for Empty String / Empty Array
      * non-standard representations; usually for things serialized as JSON Objects.
-     * 
+     *
      * @since 2.5
      */
     @SuppressWarnings("unchecked")
@@ -604,7 +643,7 @@
      * Helper method called to determine if we are seeing String value of
      * "null", and, further, that it should be coerced to null just like
      * null token.
-     * 
+     *
      * @since 2.3
      */
     protected boolean _hasTextualNull(String value) {
@@ -617,7 +656,7 @@
     protected boolean _isEmptyOrTextualNull(String value) {
         return value.isEmpty() || "null".equals(value);
     }
-    
+
     protected final boolean _isNegInf(String text) {
         return "-Infinity".equals(text) || "-INF".equals(text);
     }
@@ -666,13 +705,13 @@
                 if (p.nextToken() != JsonToken.END_ARRAY) {
                     handleMissingEndArrayForSingle(p, ctxt);
                 }
-                return parsed;            
+                return parsed;
             }
         } else {
             t = p.getCurrentToken();
         }
         @SuppressWarnings("unchecked")
-        T result = (T) ctxt.handleUnexpectedToken(_valueClass, t, p, null);
+        T result = (T) ctxt.handleUnexpectedToken(getValueType(ctxt), p.getCurrentToken(), p, null);
         return result;
     }
 
@@ -694,7 +733,7 @@
                     ClassUtil.nameOf(_valueClass), JsonToken.START_ARRAY,
                     "DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS");
             @SuppressWarnings("unchecked")
-            T result = (T) ctxt.handleUnexpectedToken(_valueClass, p.getCurrentToken(), p, msg);
+            T result = (T) ctxt.handleUnexpectedToken(getValueType(ctxt), p.getCurrentToken(), p, msg);
             return result;
         }
         return (T) deserialize(p, ctxt);
@@ -719,7 +758,7 @@
      * config settings suggest that a coercion may be needed to "upgrade"
      * {@link java.lang.Number} into "bigger" type like {@link java.lang.Long} or
      * {@link java.math.BigInteger}
-     * 
+     *
      * @see DeserializationFeature#USE_BIG_INTEGER_FOR_INTS
      * @see DeserializationFeature#USE_LONG_FOR_INTS
      *
@@ -859,7 +898,7 @@
                 valueDesc, _coercedTypeDesc(), feat.getClass().getSimpleName(), feat.name());
         }
     }
-    
+
     protected void _reportFailedNullCoerce(DeserializationContext ctxt, boolean state, Enum<?> feature,
             String inputDesc) throws JsonMappingException
     {
@@ -867,7 +906,7 @@
         ctxt.reportInputMismatch(this, "Cannot coerce %s to Null value %s (%s `%s.%s` to allow)",
             inputDesc, _coercedTypeDesc(), enableDesc, feature.getClass().getSimpleName(), feature.name());
     }
-    
+
     /**
      * Helper method called to get a description of type into which a scalar value coercion
      * is (most likely) being applied, to be used for constructing exception messages
@@ -908,7 +947,7 @@
      * Helper method used to locate deserializers for properties the
      * type this deserializer handles contains (usually for properties of
      * bean types)
-     * 
+     *
      * @param type Type of property to deserialize
      * @param property Actual property object (field, method, constuctor parameter) used
      *     for passing deserialized values; provided so deserializer can be contextualized if necessary
@@ -952,10 +991,10 @@
      * Helper method that can be used to see if specified property has annotation
      * indicating that a converter is to be used for contained values (contents
      * of structured types; array/List/Map values)
-     * 
+     *
      * @param existingDeserializer (optional) configured content
      *    serializer if one already exists.
-     * 
+     *
      * @since 2.2
      */
     protected JsonDeserializer<?> findConvertingContentDeserializer(DeserializationContext ctxt,
@@ -985,7 +1024,7 @@
     /* Helper methods for: accessing contextual config settings
     /**********************************************************
      */
-    
+
     /**
      * Helper method that may be used to find if this deserializer has specific
      * {@link JsonFormat} settings, either via property, or through type-specific
@@ -1010,7 +1049,7 @@
      * defaults and/of overrides, and then calls
      * <code>JsonFormat.Value.getFeature(feat)</code>
      * to find whether that feature has been specifically marked as enabled or disabled.
-     * 
+     *
      * @param typeForDefaults Type (erased) used for finding default format settings, if any
      *
      * @since 2.7
@@ -1059,6 +1098,20 @@
         if (nulls == Nulls.SKIP) {
             return NullsConstantProvider.skipper();
         }
+        // 09-Dec-2019, tatu: [databind#2567] need to ensure correct target type (element,
+        //    not container), so inlined here before calling _findNullProvider
+        if (nulls == Nulls.FAIL) {
+            if (prop == null) {
+                JavaType type = ctxt.constructType(valueDeser.handledType());
+                // should always be container? But let's double-check just in case:
+                if (type.isContainerType()) {
+                    type = type.getContentType();
+                }
+                return NullsFailProvider.constructForRootValue(type);
+            }
+            return NullsFailProvider.constructForProperty(prop, prop.getType().getContentType());
+        }
+
         NullValueProvider prov = _findNullProvider(ctxt, prop, nulls, valueDeser);
         if (prov != null) {
             return prov;
@@ -1162,7 +1215,7 @@
     protected void handleMissingEndArrayForSingle(JsonParser p, DeserializationContext ctxt)
         throws IOException
     {
-        ctxt.reportWrongTokenException(this, JsonToken.END_ARRAY, 
+        ctxt.reportWrongTokenException(this, JsonToken.END_ARRAY,
 "Attempted to unwrap '%s' value from an array (with `DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS`) but it contains more than one value",
 handledType().getName());
         // 05-May-2016, tatu: Should recover somehow (maybe skip until END_ARRAY);
@@ -1174,7 +1227,7 @@
         JsonToken t = p.nextToken();
         if (t != JsonToken.END_ARRAY) {
             handleMissingEndArrayForSingle(p, ctxt);
-        }            
+        }
     }
 
     /*
@@ -1198,7 +1251,7 @@
         //    as Java signed range since that's relatively common usage
         return (value < Byte.MIN_VALUE || value > 255);
     }
-    
+
     /**
      * @since 2.9
      */
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializer.java
index 862545b..0293388 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializer.java
@@ -1,6 +1,7 @@
 package com.fasterxml.jackson.databind.deser.std;
 
 import java.io.IOException;
+import java.io.Serializable;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.net.MalformedURLException;
@@ -72,9 +73,13 @@
         int kind;
 
         // first common types:
-        if (raw == String.class || raw == Object.class || raw == CharSequence.class) {
+        if (raw == String.class || raw == Object.class
+                || raw == CharSequence.class
+                // see [databind#2115]:
+                || raw == Serializable.class) {
             return StringKD.forType(raw);
-        } else if (raw == UUID.class) {
+        }
+        if (raw == UUID.class) {
             kind = TYPE_UUID;
         } else if (raw == Integer.class) {
             kind = TYPE_INT;
@@ -134,7 +139,8 @@
                     re.getClass().getName(),
                     ClassUtil.exceptionMessage(re));
         }
-        if (_keyClass.isEnum() && ctxt.getConfig().isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
+        if (ClassUtil.isEnumType(_keyClass)
+                && ctxt.getConfig().isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
             return null;
         }
         return ctxt.handleWeirdKey(_keyClass, key, "not a valid representation");
@@ -391,7 +397,7 @@
                         && ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE)) {
                     e = _enumDefaultValue;
                 } else if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
-                    return ctxt.handleWeirdKey(_keyClass, key, "not one of values excepted for Enum class: %s",
+                    return ctxt.handleWeirdKey(_keyClass, key, "not one of the values accepted for Enum class: %s",
                         res.getEnumIds());
                 }
                 // fall-through if problems are collected, not immediately thrown
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java
index d31fb0c..b43114a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java
@@ -48,9 +48,7 @@
     public static KeyDeserializer findStringBasedKeyDeserializer(DeserializationConfig config,
             JavaType type)
     {
-        /* We don't need full deserialization information, just need to
-         * know creators.
-         */
+        // We don't need full deserialization information, just need to know creators.
         BeanDescription beanDesc = config.introspect(type);
         // Ok, so: can we find T(String) constructor?
         Constructor<?> ctor = beanDesc.findSingleArgConstructor(String.class);
@@ -60,9 +58,8 @@
             }
             return new StdKeyDeserializer.StringCtorKeyDeserializer(ctor);
         }
-        /* or if not, "static T valueOf(String)" (or equivalent marked
-         * with @JsonCreator annotation?)
-         */
+        // or if not, "static T valueOf(String)" (or equivalent marked
+        // with @JsonCreator annotation?)
         Method m = beanDesc.findFactoryMethod(String.class);
         if (m != null){
             if (config.canOverrideAccessModifiers()) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdScalarDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdScalarDeserializer.java
index 1e719e4..62f27ab 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdScalarDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdScalarDeserializer.java
@@ -33,8 +33,8 @@
     @Override // since 2.9
     public T deserialize(JsonParser p, DeserializationContext ctxt, T intoValue) throws IOException {
         // 25-Oct-2016, tatu: And if attempt is made, see if we are to complain...
-        ctxt.reportBadMerge(this);
-        // except that it is possible to suppress this; and if so...
+        ctxt.handleBadMerge(this);
+        // if that does not report an exception we can just delegate
         return deserialize(p, ctxt);
     }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.java
index 919c963..e4ac0fd 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdValueInstantiator.java
@@ -439,7 +439,7 @@
      */
 
     /**
-     * @deprecated Since 2.7 call either {@link #unwrapAndWrapException} or
+     * @deprecated Since 2.7 call either {@link #rewrapCtorProblem} or
      *  {@link #wrapAsJsonMappingException}
      */
     @Deprecated // since 2.7
@@ -457,8 +457,10 @@
     }
 
     /**
-     * @since 2.7
+     * @deprecated Since 2.7 call either {@link #rewrapCtorProblem} or
+     *  {@link #wrapAsJsonMappingException}
      */
+    @Deprecated // since 2.10
     protected JsonMappingException unwrapAndWrapException(DeserializationContext ctxt, Throwable t)
     {
         // 05-Nov-2015, tatu: This used to always unwrap the whole exception, but now only
@@ -472,6 +474,11 @@
     }
 
     /**
+     * Helper method that will return given {@link Throwable} case as
+     * a {@link JsonMappingException} (if it is of that type), or call
+     * {@link DeserializationContext#instantiationException(Class, Throwable)} to
+     * produce and return suitable {@link JsonMappingException}.
+     *
      * @since 2.7
      */
     protected JsonMappingException wrapAsJsonMappingException(DeserializationContext ctxt,
@@ -485,6 +492,10 @@
     }
 
     /**
+     * Method that subclasses may call for standard handling of an exception thrown when
+     * calling constructor or factory method. Will unwrap {@link ExceptionInInitializerError}
+     * and {@link InvocationTargetException}s, then call {@link #wrapAsJsonMappingException}.
+     *
      * @since 2.7
      */
     protected JsonMappingException rewrapCtorProblem(DeserializationContext ctxt,
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java
index 0bf2e12..101d03b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringCollectionDeserializer.java
@@ -217,35 +217,39 @@
     private Collection<String> deserializeUsingCustom(JsonParser p, DeserializationContext ctxt,
             Collection<String> result, final JsonDeserializer<String> deser) throws IOException
     {
-        while (true) {
-            /* 30-Dec-2014, tatu: This may look odd, but let's actually call method
-             *   that suggest we are expecting a String; this helps with some formats,
-             *   notably XML. Note, however, that while we can get String, we can't
-             *   assume that's what we use due to custom deserializer
-             */
-            String value;
-            if (p.nextTextValue() == null) {
-                JsonToken t = p.getCurrentToken();
-                if (t == JsonToken.END_ARRAY) {
-                    break;
-                }
-                // Ok: no need to convert Strings, but must recognize nulls
-                if (t == JsonToken.VALUE_NULL) {
-                    if (_skipNullValues) {
-                        continue;
+        try {
+            while (true) {
+                /* 30-Dec-2014, tatu: This may look odd, but let's actually call method
+                 *   that suggest we are expecting a String; this helps with some formats,
+                 *   notably XML. Note, however, that while we can get String, we can't
+                 *   assume that's what we use due to custom deserializer
+                 */
+                String value;
+                if (p.nextTextValue() == null) {
+                    JsonToken t = p.getCurrentToken();
+                    if (t == JsonToken.END_ARRAY) {
+                        break;
                     }
-                    value = (String) _nullProvider.getNullValue(ctxt);
+                    // Ok: no need to convert Strings, but must recognize nulls
+                    if (t == JsonToken.VALUE_NULL) {
+                        if (_skipNullValues) {
+                            continue;
+                        }
+                        value = (String) _nullProvider.getNullValue(ctxt);
+                    } else {
+                        value = deser.deserialize(p, ctxt);
+                    }
                 } else {
                     value = deser.deserialize(p, ctxt);
                 }
-            } else {
-                value = deser.deserialize(p, ctxt);
+                result.add(value);
             }
-            result.add(value);
+        } catch (Exception e) {
+            throw JsonMappingException.wrapWithPath(e, result, result.size());
         }
         return result;
     }
-    
+
     @Override
     public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
             TypeDeserializer typeDeserializer) throws IOException {
@@ -282,7 +286,11 @@
             }
             value = (String) _nullProvider.getNullValue(ctxt);
         } else {
-            value = (valueDes == null) ? _parseString(p, ctxt) : valueDes.deserialize(p, ctxt);
+            try {
+                value = (valueDes == null) ? _parseString(p, ctxt) : valueDes.deserialize(p, ctxt);
+            } catch (Exception e) {
+                throw JsonMappingException.wrapWithPath(e, result, result.size());
+            }
         }
         result.add(value);
         return result;
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringDeserializer.java
index c563f4b..a4b25c0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StringDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StringDeserializer.java
@@ -34,7 +34,7 @@
         if (p.hasToken(JsonToken.VALUE_STRING)) {
             return p.getText();
         }
-        JsonToken t = p.getCurrentToken();
+        JsonToken t = p.currentToken();
         // [databind#381]
         if (t == JsonToken.START_ARRAY) {
             return _deserializeFromArray(p, ctxt);
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/ThrowableDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/ThrowableDeserializer.java
index d2e8c67..0878956 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/std/ThrowableDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/ThrowableDeserializer.java
@@ -77,14 +77,14 @@
         // and finally, verify we do have single-String arg constructor (if no @JsonCreator)
         if (!hasStringCreator && !hasDefaultCtor) {
             return ctxt.handleMissingInstantiator(handledType(), getValueInstantiator(), p,
-                    "Throwable needs a default contructor, a single-String-arg constructor; or explicit @JsonCreator");
+                    "Throwable needs a default constructor, a single-String-arg constructor; or explicit @JsonCreator");
         }
         
         Object throwable = null;
         Object[] pending = null;
         int pendingIx = 0;
 
-        for (; p.getCurrentToken() != JsonToken.END_OBJECT; p.nextToken()) {
+        for (; !p.hasToken(JsonToken.END_OBJECT); p.nextToken()) {
             String propName = p.getCurrentName();
             SettableBeanProperty prop = _beanProperties.find(propName);
             p.nextToken(); // to point to field value
diff --git a/src/main/java/com/fasterxml/jackson/databind/exc/ValueInstantiationException.java b/src/main/java/com/fasterxml/jackson/databind/exc/ValueInstantiationException.java
new file mode 100644
index 0000000..72dc8e8
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/exc/ValueInstantiationException.java
@@ -0,0 +1,57 @@
+package com.fasterxml.jackson.databind.exc;
+
+import com.fasterxml.jackson.core.JsonParser;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
+/**
+ * Exception type used for generic failures during processing by
+ * {@link com.fasterxml.jackson.databind.deser.ValueInstantiator}:
+ * commonly used to wrap exceptions thrown by constructor or factory
+ * method.
+ *<p>
+ * Note that this type is sibling of {@link MismatchedInputException} and
+ * {@link InvalidDefinitionException} since it is not clear if problem is
+ * with input, or type definition (or possibly neither).
+ * It is recommended that if either specific input, or type definition problem
+ * is known, a more accurate exception is used instead.
+ *
+ * @since 2.10
+ */
+@SuppressWarnings("serial")
+public class ValueInstantiationException
+    extends JsonMappingException
+{
+    protected final JavaType _type;
+
+    protected ValueInstantiationException(JsonParser p, String msg,
+            JavaType type, Throwable cause) {
+        super(p, msg, cause);
+        _type = type;
+    }
+
+    protected ValueInstantiationException(JsonParser p, String msg,
+            JavaType type) {
+        super(p, msg);
+        _type = type;
+    }
+
+    public static ValueInstantiationException from(JsonParser p, String msg,
+            JavaType type) {
+        return new ValueInstantiationException(p, msg, type);
+    }
+
+    public static ValueInstantiationException from(JsonParser p, String msg,
+            JavaType type, Throwable cause) {
+        return new ValueInstantiationException(p, msg, type, cause);
+    }
+
+    /**
+     * Accessor for type fully resolved type that had the problem; this should always
+     * known and available, never <code>null</code>
+     */
+    public JavaType getType() {
+        return _type;
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/Java7Handlers.java b/src/main/java/com/fasterxml/jackson/databind/ext/Java7Handlers.java
new file mode 100644
index 0000000..9391118
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/ext/Java7Handlers.java
@@ -0,0 +1,43 @@
+package com.fasterxml.jackson.databind.ext;
+
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.util.ClassUtil;
+
+/**
+ * To support Java7-incomplete platforms, we will offer support for JDK 7
+ * datatype(s) (that is, {@link java.nio.file.Path} through this class, loaded
+ * dynamically; if loading fails, support will be missing.
+ * This class is the non-JDK-7-dependent API, and {@link Java7HandlersImpl} is
+ * JDK7-dependent implementation of functionality.
+ *
+ * @since 2.10 (cleaved off of {@link Java7Support})
+ */
+public abstract class Java7Handlers
+{
+    private final static Java7Handlers IMPL;
+
+    static {
+        Java7Handlers impl = null;
+        try {
+            Class<?> cls = Class.forName("com.fasterxml.jackson.databind.ext.Java7HandlersImpl");
+            impl = (Java7Handlers) ClassUtil.createInstance(cls, false);
+        } catch (Throwable t) {
+            // 09-Sep-2019, tatu: Could choose not to log this, but since this is less likely
+            //    to miss (than annotations), do it
+            java.util.logging.Logger.getLogger(Java7Handlers.class.getName())
+                .warning("Unable to load JDK7 types (java.nio.file.Path): no Java7 type support added");
+        }
+        IMPL = impl;
+    }
+
+    public static Java7Handlers instance() {
+        return IMPL;
+    }
+
+    public abstract Class<?> getClassJavaNioFilePath();
+
+    public abstract JsonDeserializer<?> getDeserializerForJavaNioFilePath(Class<?> rawType);
+
+    public abstract JsonSerializer<?> getSerializerForJavaNioFilePath(Class<?> rawType);
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/Java7HandlersImpl.java b/src/main/java/com/fasterxml/jackson/databind/ext/Java7HandlersImpl.java
new file mode 100644
index 0000000..b69c9e1
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/ext/Java7HandlersImpl.java
@@ -0,0 +1,41 @@
+package com.fasterxml.jackson.databind.ext;
+
+import java.nio.file.Path;
+
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonSerializer;
+
+/**
+ * @since 2.10
+ */
+public class Java7HandlersImpl extends Java7Handlers
+{
+    private final Class<?> _pathClass;
+    
+    public Java7HandlersImpl() {
+        // 19-Sep-2019, tatu: Important to do this here, because otherwise
+        //    we get [databind#2466]
+        _pathClass = Path.class;
+    }
+    
+    @Override
+    public Class<?> getClassJavaNioFilePath() {
+        return _pathClass;
+    }
+
+    @Override
+    public JsonDeserializer<?> getDeserializerForJavaNioFilePath(Class<?> rawType) {
+        if (rawType == _pathClass) {
+            return new NioPathDeserializer();
+        }
+        return null;
+    }
+
+    @Override
+    public JsonSerializer<?> getSerializerForJavaNioFilePath(Class<?> rawType) {
+        if (_pathClass.isAssignableFrom(rawType)) {
+            return new NioPathSerializer();
+        }
+        return null;
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/Java7Support.java b/src/main/java/com/fasterxml/jackson/databind/ext/Java7Support.java
index 051f570..9c44420 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ext/Java7Support.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ext/Java7Support.java
@@ -1,7 +1,5 @@
 package com.fasterxml.jackson.databind.ext;
 
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.PropertyName;
 import com.fasterxml.jackson.databind.introspect.Annotated;
 import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
@@ -17,16 +15,16 @@
 public abstract class Java7Support
 {
     private final static Java7Support IMPL;
-    
+
     static {
         Java7Support impl = null;
         try {
             Class<?> cls = Class.forName("com.fasterxml.jackson.databind.ext.Java7SupportImpl");
             impl = (Java7Support) ClassUtil.createInstance(cls, false);
         } catch (Throwable t) {
-            // 24-Nov-2015, tatu: Should we log or not?
-            java.util.logging.Logger.getLogger(Java7Support.class.getName())
-                .warning("Unable to load JDK7 types (annotations, java.nio.file.Path): no Java7 support added");
+            // 09-Sep-2019, tatu: Used to log earlier, but with 2.10.0 let's not log
+//            java.util.logging.Logger.getLogger(Java7Support.class.getName())
+//                .warning("Unable to load JDK7 annotations (@ConstructorProperties, @Transient): no Java7 annotation support added");
         }
         IMPL = impl;
     }
@@ -40,10 +38,4 @@
     public abstract Boolean hasCreatorAnnotation(Annotated a);
 
     public abstract PropertyName findConstructorName(AnnotatedParameter p);
-
-    public abstract Class<?> getClassJavaNioFilePath();
-
-    public abstract JsonDeserializer<?> getDeserializerForJavaNioFilePath(Class<?> rawType);
-
-    public abstract JsonSerializer<?> getSerializerForJavaNioFilePath(Class<?> rawType);
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/Java7SupportImpl.java b/src/main/java/com/fasterxml/jackson/databind/ext/Java7SupportImpl.java
index 4546d03..660c23c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ext/Java7SupportImpl.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ext/Java7SupportImpl.java
@@ -2,10 +2,7 @@
 
 import java.beans.ConstructorProperties;
 import java.beans.Transient;
-import java.nio.file.Path;
 
-import com.fasterxml.jackson.databind.JsonDeserializer;
-import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.PropertyName;
 import com.fasterxml.jackson.databind.introspect.Annotated;
 import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
@@ -20,34 +17,14 @@
     private final Class<?> _bogus;
 
     public Java7SupportImpl() {
-        // Trigger loading of annotations that only JDK 7 has...
+        // Trigger loading of annotations that only JDK 7 has, to trigger
+        // early fail (see [databind#2466])
         Class<?> cls = Transient.class;
         cls = ConstructorProperties.class;
         _bogus = cls;
     }
 
     @Override
-    public Class<?> getClassJavaNioFilePath() {
-        return Path.class;
-    }
-
-    @Override
-    public JsonDeserializer<?> getDeserializerForJavaNioFilePath(Class<?> rawType) {
-        if (rawType == Path.class) {
-            return new NioPathDeserializer();
-        }
-        return null;
-    }
-
-    @Override
-    public JsonSerializer<?> getSerializerForJavaNioFilePath(Class<?> rawType) {
-        if (Path.class.isAssignableFrom(rawType)) {
-            return new NioPathSerializer();
-        }
-        return null;
-    }
-
-    @Override
     public Boolean findTransient(Annotated a) {
         Transient t = a.getAnnotation(Transient.class);
         if (t != null) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ext/OptionalHandlerFactory.java b/src/main/java/com/fasterxml/jackson/databind/ext/OptionalHandlerFactory.java
index f22e8d5..be5d569 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ext/OptionalHandlerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ext/OptionalHandlerFactory.java
@@ -64,11 +64,11 @@
     // // (note: also assume it comes from JDK so that ClassLoader issues with OSGi
     // // can, I hope, be avoided?)
 
-    private static final Java7Support _jdk7Helper;
+    private static final Java7Handlers _jdk7Helper;
     static {
-        Java7Support x = null;
+        Java7Handlers x = null;
         try {
-            x = Java7Support.instance();
+            x = Java7Handlers.instance();
         } catch (Throwable t) { }
         _jdk7Helper = x;
     }
@@ -88,15 +88,17 @@
     {
         final Class<?> rawType = type.getRawClass();
 
+        if ((CLASS_DOM_NODE != null) && CLASS_DOM_NODE.isAssignableFrom(rawType)) {
+            return (JsonSerializer<?>) instantiate(SERIALIZER_FOR_DOM_NODE);
+        }
+
         if (_jdk7Helper != null) {
             JsonSerializer<?> ser = _jdk7Helper.getSerializerForJavaNioFilePath(rawType);
             if (ser != null) {
                 return ser;
             }
         }
-        if ((CLASS_DOM_NODE != null) && CLASS_DOM_NODE.isAssignableFrom(rawType)) {
-            return (JsonSerializer<?>) instantiate(SERIALIZER_FOR_DOM_NODE);
-        }
+
         String className = rawType.getName();
         String factoryName;
         if (className.startsWith(PACKAGE_PREFIX_JAVAX_XML) || hasSuperClassStartingWith(rawType, PACKAGE_PREFIX_JAVAX_XML)) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedCreatorCollector.java b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedCreatorCollector.java
index 0ec6d66..d4bbce5 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedCreatorCollector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/AnnotatedCreatorCollector.java
@@ -242,8 +242,8 @@
         }
         return new AnnotatedConstructor(_typeContext, ctor.getConstructor(),
                 collectAnnotations(ctor, mixin),
-                collectAnnotations(ctor.getConstructor().getParameterAnnotations(),
-                        (mixin == null) ? null : mixin.getConstructor().getParameterAnnotations()));
+                // 16-Jun-2019, tatu: default is zero-args, so can't have parameter annotations
+                NO_ANNOTATION_MAPS);
     }
 
     protected AnnotatedConstructor constructNonDefaultConstructor(ClassUtil.Ctor ctor,
@@ -274,7 +274,7 @@
             resolvedAnnotations = null;
             Class<?> dc = ctor.getDeclaringClass();
             // (a) is enum, which have two extra hidden params (name, index)
-            if (dc.isEnum() && (paramCount == paramAnns.length + 2)) {
+            if (ClassUtil.isEnumType(dc) && (paramCount == paramAnns.length + 2)) {
                 Annotation[][] old = paramAnns;
                 paramAnns = new Annotation[old.length+2][];
                 System.arraycopy(old, 0, paramAnns, 2, old.length);
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.java b/src/main/java/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.java
index f511efb..abba14f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/BasicClassIntrospector.java
@@ -137,8 +137,7 @@
     {
         BasicBeanDescription desc = _findStdTypeDesc(type);
         if (desc == null) {
-
-            // As per [Databind#550], skip full introspection for some of standard
+            // As per [databind#550], skip full introspection for some of standard
             // structured types as well
             desc = _findStdJdkCollectionDesc(cfg, type);
             if (desc == null) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/ConcreteBeanPropertyBase.java b/src/main/java/com/fasterxml/jackson/databind/introspect/ConcreteBeanPropertyBase.java
index 7d2bc48..98a9bb7 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/ConcreteBeanPropertyBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/ConcreteBeanPropertyBase.java
@@ -30,13 +30,6 @@
     protected final PropertyMetadata _metadata;
 
     /**
-     * Lazily accessed value for per-property format override definition.
-     * 
-     * @since 2.8
-     */
-    protected transient JsonFormat.Value _propertyFormat;
-
-    /**
      * @since 2.9
      */
     protected transient List<PropertyName> _aliases;
@@ -47,7 +40,6 @@
 
     protected ConcreteBeanPropertyBase(ConcreteBeanPropertyBase src) {
         _metadata = src._metadata;
-        _propertyFormat = src._propertyFormat;
     }
 
     @Override
@@ -78,27 +70,19 @@
     @Override
     public JsonFormat.Value findPropertyFormat(MapperConfig<?> config, Class<?> baseType)
     {
-        // 15-Apr-2016, tatu: Let's calculate lazily, retain; assumption being however that
-        //    baseType is always the same
-        JsonFormat.Value v = _propertyFormat;
-        if (v == null) {
-            JsonFormat.Value v1 = config.getDefaultPropertyFormat(baseType);
-            JsonFormat.Value v2 = null;
-            AnnotationIntrospector intr = config.getAnnotationIntrospector();
-            if (intr != null) {
-                AnnotatedMember member = getMember();
-                if (member != null) {
-                    v2 = intr.findFormat(member);
-                }
+        JsonFormat.Value v1 = config.getDefaultPropertyFormat(baseType);
+        JsonFormat.Value v2 = null;
+        AnnotationIntrospector intr = config.getAnnotationIntrospector();
+        if (intr != null) {
+            AnnotatedMember member = getMember();
+            if (member != null) {
+                v2 = intr.findFormat(member);
             }
-            if (v1 == null) {
-                v = (v2 == null) ? EMPTY_FORMAT : v2;
-            } else {
-                v = (v2 == null) ? v1 : v1.withOverrides(v2);
-            }
-            _propertyFormat = v;
         }
-        return v;
+        if (v1 == null) {
+            return (v2 == null) ? EMPTY_FORMAT : v2;
+        }
+        return (v2 == null) ? v1 : v1.withOverrides(v2);
     }
 
     @Override
@@ -128,7 +112,10 @@
         if (aliases == null) {
             AnnotationIntrospector intr = config.getAnnotationIntrospector();
             if (intr != null) {
-                aliases = intr.findPropertyAliases(getMember());
+                final AnnotatedMember member = getMember();
+                if (member != null) {
+                    aliases = intr.findPropertyAliases(member);
+                }
             }
             if (aliases == null) {
                 aliases = Collections.emptyList();
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java b/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
index 823deb6..55c11d1 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java
@@ -1413,10 +1413,8 @@
             if (info == null) {
                 return null;
             }
-            /* let's not try to force access override (would need to pass
-             * settings through if we did, since that's not doable on some
-             * platforms)
-             */
+            // let's not try to force access override (would need to pass
+            // settings through if we did, since that's not doable on some platforms)
             b = config.typeResolverBuilderInstance(ann, resAnn.value());
         } else { // if not, use standard one, if indicated by annotations
             if (info == null) {
@@ -1436,10 +1434,9 @@
             idRes.init(baseType);
         }
         b = b.init(info.use(), idRes);
-        /* 13-Aug-2011, tatu: One complication; external id
-         *   only works for properties; so if declared for a Class, we will need
-         *   to map it to "PROPERTY" instead of "EXTERNAL_PROPERTY"
-         */
+        // 13-Aug-2011, tatu: One complication; external id only works for properties;
+        //    so if declared for a Class, we will need to map it to "PROPERTY"
+        //    instead of "EXTERNAL_PROPERTY"
         JsonTypeInfo.As inclusion = info.include();
         if (inclusion == JsonTypeInfo.As.EXTERNAL_PROPERTY && (ann instanceof AnnotatedClass)) {
             inclusion = JsonTypeInfo.As.PROPERTY;
diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/SimpleMixInResolver.java b/src/main/java/com/fasterxml/jackson/databind/introspect/SimpleMixInResolver.java
index a3c630a..2e9560b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/introspect/SimpleMixInResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/introspect/SimpleMixInResolver.java
@@ -99,4 +99,33 @@
     public int localSize() {
         return (_localMixIns == null) ? 0 : _localMixIns.size();
     }
+
+    /**
+     * Method that may be called for optimization purposes, to see if calls to
+     * mix-in resolver may be avoided. Return value of {@code true} means that
+     * it is possible that a mix-in class will be found; {@code false} that no
+     * mix-in will ever be found. In latter case caller can avoid calls altogether.
+     *<p>
+     * Note that the reason for "empty" resolvers is to use "null object" for simplifying
+     * code.
+     *
+     * @return True, if this resolver MAY have mix-ins to apply; false if not (it
+     *   is "empty")
+     *
+     * @since 2.10.1
+     */
+    public boolean hasMixIns() {
+        if (_localMixIns == null) {
+            // if neither local mix-ins nor overrides, no mix-ins
+            if (_overrides == null) {
+                return false;
+            }
+            // or, if no local mix-ins and can delegate to resolver
+            if (_overrides instanceof SimpleMixInResolver) {
+                return ((SimpleMixInResolver) _overrides).hasMixIns();
+            }
+        }
+        // cannot rule out the possibility, so...
+        return true;
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/json/JsonMapper.java b/src/main/java/com/fasterxml/jackson/databind/json/JsonMapper.java
new file mode 100644
index 0000000..2a77252
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/json/JsonMapper.java
@@ -0,0 +1,159 @@
+package com.fasterxml.jackson.databind.json;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.core.json.JsonReadFeature;
+import com.fasterxml.jackson.core.json.JsonWriteFeature;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.cfg.MapperBuilder;
+import com.fasterxml.jackson.databind.cfg.PackageVersion;
+
+/**
+ * JSON-format specific {@link ObjectMapper} implementation.
+ *
+ * @since 2.10
+ */
+public class JsonMapper extends ObjectMapper
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Base implementation for "Vanilla" {@link ObjectMapper}, used with
+     * JSON dataformat backend.
+     *
+     * @since 2.10
+     */
+    public static class Builder extends MapperBuilder<JsonMapper, Builder>
+    {
+        public Builder(JsonMapper m) {
+            super(m);
+        }
+
+        public Builder enable(JsonReadFeature... features)  {
+            for (JsonReadFeature f : features) {
+                _mapper.enable(f.mappedFeature());
+            }
+            return this;
+        }
+
+        public Builder disable(JsonReadFeature... features) {
+            for (JsonReadFeature f : features) {
+                _mapper.disable(f.mappedFeature());
+            }
+            return this;
+        }
+
+        public Builder configure(JsonReadFeature f, boolean state)
+        {
+            if (state) {
+                _mapper.enable(f.mappedFeature());
+            } else {
+                _mapper.disable(f.mappedFeature());
+            }
+            return this;
+        }
+
+        public Builder enable(JsonWriteFeature... features)  {
+            for (JsonWriteFeature f : features) {
+                _mapper.enable(f.mappedFeature());
+            }
+            return this;
+        }
+
+        public Builder disable(JsonWriteFeature... features) {
+            for (JsonWriteFeature f : features) {
+                _mapper.disable(f.mappedFeature());
+            }
+            return this;
+        }
+
+        public Builder configure(JsonWriteFeature f, boolean state)
+        {
+            if (state) {
+                _mapper.enable(f.mappedFeature());
+            } else {
+                _mapper.disable(f.mappedFeature());
+            }
+            return this;
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Life-cycle, constructors
+    /**********************************************************
+     */
+
+    public JsonMapper() {
+        this(new JsonFactory());
+    }
+
+    public JsonMapper(JsonFactory f) {
+        super(f);
+    }
+
+    protected JsonMapper(JsonMapper src) {
+        super(src);
+    }
+
+    @Override
+    public JsonMapper copy()
+    {
+        _checkInvalidCopy(JsonMapper.class);
+        return new JsonMapper(this);
+    }
+
+    /*
+    /**********************************************************
+    /* Life-cycle, builders
+    /**********************************************************
+     */
+
+    public static JsonMapper.Builder builder() {
+        return new Builder(new JsonMapper());
+    }
+
+    public static Builder builder(JsonFactory streamFactory) {
+        return new Builder(new JsonMapper(streamFactory));
+    }
+
+    public JsonMapper.Builder  rebuild() {
+        // 09-Dec-2018, tatu: Not as good as what 3.0 has wrt immutability, but best approximation
+        //     we have for 2.x
+        return new Builder(this.copy());
+    }
+
+    /*
+    /**********************************************************
+    /* Standard method overrides
+    /**********************************************************
+     */
+
+    @Override
+    public Version version() {
+        return PackageVersion.VERSION;
+    }
+
+    @Override
+    public JsonFactory getFactory() {
+        return _jsonFactory;
+    }
+
+    /*
+    /**********************************************************
+    /* JSON-specific accessors, mutators
+    /**********************************************************
+     */
+
+    // // // 25-Oct-2018, tatu: Since for 2.x these will simply map to legacy settings,
+    // // //   we will fake them
+    
+    public boolean isEnabled(JsonReadFeature f) {
+        return isEnabled(f.mappedFeature());
+    }
+
+    public boolean isEnabled(JsonWriteFeature f) {
+        return isEnabled(f.mappedFeature());
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitors/JsonValueFormat.java b/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitors/JsonValueFormat.java
index 7ba4698..a645e03 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitors/JsonValueFormat.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsonFormatVisitors/JsonValueFormat.java
@@ -74,7 +74,7 @@
     TIME("time"),
 
     /**
-     * This value SHOULD be a URI..
+     * This value SHOULD be a URI.
      */
     URI("uri"),
 
@@ -85,6 +85,13 @@
       float).
      */
     UTC_MILLISEC("utc-millisec"),
+
+    /**
+     * Value should be valid <a href="https://en.wikipedia.org/wiki/Universally_unique_identifier">UUID</a>
+     *
+     * @since 2.10
+     */
+    UUID("uuid")
     ;
 
     private final String _desc;
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/BasicPolymorphicTypeValidator.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/BasicPolymorphicTypeValidator.java
new file mode 100644
index 0000000..7518805
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/BasicPolymorphicTypeValidator.java
@@ -0,0 +1,393 @@
+package com.fasterxml.jackson.databind.jsontype;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.cfg.MapperConfig;
+
+/**
+ * Standard {@link BasicPolymorphicTypeValidator} implementation that users may want
+ * to use for constructing validators based on simple class hierarchy and/or name patterns
+ * to allow and/or deny certain subtypes.
+ *<p>
+ * Most commonly this is used to allow known safe subtypes based on common super type
+ * or Java package name.
+ *<br>
+ * For example:
+ *<pre>
+ *</pre>
+ *
+ * @since 2.10
+ */
+public class BasicPolymorphicTypeValidator
+    extends PolymorphicTypeValidator.Base
+    implements java.io.Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /*
+    /**********************************************************
+    /* Helper classes: matchers
+    /**********************************************************
+     */
+
+    /**
+     * General matcher interface (predicate) for validating class values
+     * (base type or resolved subtype)
+     */
+    protected abstract static class TypeMatcher {
+        public abstract boolean match(Class<?> clazz);
+    }
+
+    /**
+     * General matcher interface (predicate) for validating unresolved
+     * subclass class name.
+     */
+    protected abstract static class NameMatcher {
+        public abstract boolean match(String clazzName);
+    }
+    
+    /*
+    /**********************************************************
+    /* Builder class for configuring instances
+    /**********************************************************
+     */
+
+    /**
+     * Builder class for configuring and constructing immutable
+     * {@link BasicPolymorphicTypeValidator} instances. Criteria for allowing
+     * polymorphic subtypes is specified by adding rules in priority order, starting
+     * with the rules to evaluate first: when a matching rule is found, its status
+     * ({@link PolymorphicTypeValidator.Validity#ALLOWED} or {@link PolymorphicTypeValidator.Validity#DENIED}) is used and no further
+     * rules are checked.
+     */
+    public static class Builder {
+        protected Set<Class<?>> _invalidBaseTypes;
+
+        /**
+         * Collected matchers for base types to allow.
+         */
+        protected List<TypeMatcher> _baseTypeMatchers;
+
+        /**
+         * Collected name-based matchers for sub types to allow.
+         */
+        protected List<NameMatcher> _subTypeNameMatchers;
+
+        /**
+         * Collected Class-based matchers for sub types to allow.
+         */
+        protected List<TypeMatcher> _subTypeClassMatchers;
+
+        protected Builder() { }
+
+        // // Methods for checking solely by base type (before subtype even considered)
+
+        /**
+         * Method for appending matcher that will allow all subtypes in cases where
+         * nominal base type is specified class, or one of its subtypes.
+         * For example, call to
+         *<pre>
+         *    builder.allowIfBaseType(MyBaseType.class)
+         *</pre>
+         * would indicate that any polymorphic properties where declared base type
+         * is {@code MyBaseType} (or subclass thereof) would allow all legal (assignment-compatible)
+         * subtypes.
+         */
+        public Builder allowIfBaseType(final Class<?> baseOfBase) {
+            return _appendBaseMatcher(new TypeMatcher() {
+                @Override
+                public boolean match(Class<?> clazz) {
+                    return baseOfBase.isAssignableFrom(clazz);
+                }
+            });
+        }
+
+        /**
+         * Method for appending matcher that will allow all subtypes in cases where
+         * nominal base type's class name matches given {@link Pattern}
+         * For example, call to
+         *<pre>
+         *    builder.allowIfBaseType(Pattern.compile("com\\.mycompany\\..*")
+         *</pre>
+         * would indicate that any polymorphic properties where declared base type
+         * is in package {@code com.mycompany} would allow all legal (assignment-compatible)
+         * subtypes.
+         *<p>
+         * NOTE! {@link Pattern} match is applied using
+         *<code>
+         *   if (patternForBase.matcher(typeId).matches()) { }
+         *</code>
+         * that is, it must match the whole class name, not just part.
+         */
+        public Builder allowIfBaseType(final Pattern patternForBase) {
+            return _appendBaseMatcher(new TypeMatcher() {
+                @Override
+                public boolean match(Class<?> clazz) {
+                    return patternForBase.matcher(clazz.getName()).matches();
+                }
+            });
+        }
+
+        /**
+         * Method for appending matcher that will allow all subtypes in cases where
+         * nominal base type's class name starts with specific prefix.
+         * For example, call to
+         *<pre>
+         *    builder.allowIfBaseType("com.mycompany.")
+         *</pre>
+         * would indicate that any polymorphic properties where declared base type
+         * is in package {@code com.mycompany} would allow all legal (assignment-compatible)
+         * subtypes.
+         */
+        public Builder allowIfBaseType(final String prefixForBase) {
+            return _appendBaseMatcher(new TypeMatcher() {
+                @Override
+                public boolean match(Class<?> clazz) {
+                    return clazz.getName().startsWith(prefixForBase);
+                }
+            });
+        }
+
+        /**
+         * Method for appending matcher that will mark any polymorphic properties with exact
+         * specific class to be invalid.
+         * For example, call to
+         *<pre>
+         *    builder.denyforExactBaseType(Object.class)
+         *</pre>
+         * would indicate that any polymorphic properties where declared base type
+         * is {@code java.lang.Object}
+         * would be deemed invalid, and attempt to deserialize values of such types
+         * should result in an exception.
+         */
+        public Builder denyForExactBaseType(final Class<?> baseTypeToDeny) {
+            if (_invalidBaseTypes == null) {
+                _invalidBaseTypes = new HashSet<>();
+            }
+            _invalidBaseTypes.add(baseTypeToDeny);
+            return this;
+        }
+
+        // // Methods for considering subtype (base type was not enough)
+
+        /**
+         * Method for appending matcher that will allow specific subtype (regardless
+         * of declared base type) if it is {@code subTypeBase} or its subtype.
+         * For example, call to
+         *<pre>
+         *    builder.allowIfSubType(MyImplType.class)
+         *</pre>
+         * would indicate that any polymorphic values with type of
+         * is {@code MyImplType} (or subclass thereof)
+         * would be allowed.
+         */
+        public Builder allowIfSubType(final Class<?> subTypeBase) {
+            return _appendSubClassMatcher(new TypeMatcher() {
+                @Override
+                public boolean match(Class<?> clazz) {
+                    return subTypeBase.isAssignableFrom(clazz);
+                }
+            });
+        }
+
+        /**
+         * Method for appending matcher that will allow specific subtype (regardless
+         * of declared base type) in cases where subclass name matches given {@link Pattern}.
+         * For example, call to
+         *<pre>
+         *    builder.allowIfSubType(Pattern.compile("com\\.mycompany\\.")
+         *</pre>
+         * would indicate that any polymorphic values in package {@code com.mycompany}
+         * would be allowed.
+         *<p>
+         * NOTE! {@link Pattern} match is applied using
+         *<code>
+         *   if (patternForSubType.matcher(typeId).matches()) { }
+         *</code>
+         * that is, it must match the whole class name, not just part.
+         */
+        public Builder allowIfSubType(final Pattern patternForSubType) {
+            return _appendSubNameMatcher(new NameMatcher() {
+                @Override
+                public boolean match(String clazzName) {
+                    return patternForSubType.matcher(clazzName).matches();
+                }
+            });
+        }
+
+        /**
+         * Method for appending matcher that will allow specific subtype (regardless
+         * of declared base type)
+         * in cases where subclass name starts with specified prefix
+         * For example, call to
+         *<pre>
+         *    builder.allowIfSubType("com.mycompany.")
+         *</pre>
+         * would indicate that any polymorphic values in package {@code com.mycompany}
+         * would be allowed.
+         */
+        public Builder allowIfSubType(final String prefixForSubType) {
+            return _appendSubNameMatcher(new NameMatcher() {
+                @Override
+                public boolean match(String clazzName) {
+                    return clazzName.startsWith(prefixForSubType);
+                }
+            });
+        }
+
+        /**
+         * Method for appending matcher that will allow all subtypes that are Java arrays
+         * (regardless of element type). Note that this does NOT validate element type
+         * itself as long as Polymorphic Type handling is enabled for element type: this
+         * is the case with all standard "Default Typing" inclusion criteria as well as for
+         * annotation ({@code @JsonTypeInfo}) use case (since annotation only applies to element
+         * types, not container).
+         *<p>
+         * NOTE: not used with other Java collection types ({@link java.util.List}s,
+         *    {@link java.util.Collection}s), mostly since use of generic types as polymorphic
+         *    values is not (well) supported.
+         *
+         * @since 2.10.1
+         */
+        public Builder allowIfSubTypeIsArray() {
+            return _appendSubClassMatcher(new TypeMatcher() {
+                @Override
+                public boolean match(Class<?> clazz) {
+                    return clazz.isArray();
+                }
+            });
+        }
+        
+        public BasicPolymorphicTypeValidator build() {
+            return new BasicPolymorphicTypeValidator(_invalidBaseTypes,
+                    (_baseTypeMatchers == null) ? null : _baseTypeMatchers.toArray(new TypeMatcher[0]),
+                    (_subTypeNameMatchers == null) ? null : _subTypeNameMatchers.toArray(new NameMatcher[0]),
+                    (_subTypeClassMatchers == null) ? null : _subTypeClassMatchers.toArray(new TypeMatcher[0])
+            );
+        }
+
+        protected Builder _appendBaseMatcher(TypeMatcher matcher) {
+            if (_baseTypeMatchers == null) {
+                _baseTypeMatchers = new ArrayList<>();
+            }
+            _baseTypeMatchers.add(matcher);
+            return this;
+        }
+
+        protected Builder _appendSubNameMatcher(NameMatcher matcher) {
+            if (_subTypeNameMatchers == null) {
+                _subTypeNameMatchers = new ArrayList<>();
+            }
+            _subTypeNameMatchers.add(matcher);
+            return this;
+        }
+
+        protected Builder _appendSubClassMatcher(TypeMatcher matcher) {
+            if (_subTypeClassMatchers == null) {
+                _subTypeClassMatchers = new ArrayList<>();
+            }
+            _subTypeClassMatchers.add(matcher);
+            return this;
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Actual implementation
+    /**********************************************************
+     */
+
+    /**
+     * Set of specifically denied base types to indicate that use of specific
+     * base types is not allowed: most commonly used to fully block use of
+     * {@link java.lang.Object} as the base type.
+     */
+    protected final Set<Class<?>> _invalidBaseTypes;
+
+    /**
+     * Set of matchers that can validate all values of polymorphic properties
+     * that match specified allowed base types.
+     */
+    protected final TypeMatcher[] _baseTypeMatchers;
+
+    /**
+     * Set of matchers that can validate specific values of polymorphic properties
+     * that match subtype class name criteria.
+     */
+    protected final NameMatcher[] _subTypeNameMatchers;
+
+    /**
+     * Set of matchers that can validate specific values of polymorphic properties
+     * that match subtype class criteria.
+     */
+    protected final TypeMatcher[] _subClassMatchers;
+    
+    protected BasicPolymorphicTypeValidator(Set<Class<?>> invalidBaseTypes,
+            TypeMatcher[] baseTypeMatchers,
+            NameMatcher[] subTypeNameMatchers, TypeMatcher[] subClassMatchers) {
+        _invalidBaseTypes = invalidBaseTypes;
+        _baseTypeMatchers = baseTypeMatchers;
+        _subTypeNameMatchers = subTypeNameMatchers;
+        _subClassMatchers = subClassMatchers;
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    @Override
+    public Validity validateBaseType(MapperConfig<?> ctxt, JavaType baseType) {
+//System.err.println("validateBaseType("+baseType+")");
+        final Class<?> rawBase = baseType.getRawClass();
+        if (_invalidBaseTypes != null) {
+            if (_invalidBaseTypes.contains(rawBase)) {
+                return Validity.DENIED;
+            }
+        }
+        if (_baseTypeMatchers != null) {
+            for (TypeMatcher m : _baseTypeMatchers) {
+                if (m.match(rawBase)) {
+                    return Validity.ALLOWED;
+                }
+            }
+        }
+        return Validity.INDETERMINATE;
+    }
+
+    @Override
+    public Validity validateSubClassName(MapperConfig<?> ctxt, JavaType baseType,
+            String subClassName)
+        throws JsonMappingException
+    {
+//System.err.println("validateSubClassName('"+subClassName+"')");
+        if (_subTypeNameMatchers != null)  {
+            for (NameMatcher m : _subTypeNameMatchers) {
+                if (m.match(subClassName)) {
+                    return Validity.ALLOWED;
+                }
+            }
+        }
+        // could not yet decide, so:
+        return Validity.INDETERMINATE;
+    }
+
+    @Override
+    public Validity validateSubType(MapperConfig<?> ctxt, JavaType baseType, JavaType subType)
+            throws JsonMappingException
+    {
+//System.err.println("validateSubType("+subType+")");
+        if (_subClassMatchers != null)  {
+            final Class<?> subClass = subType.getRawClass();
+            for (TypeMatcher m : _subClassMatchers) {
+                if (m.match(subClass)) {
+                    return Validity.ALLOWED;
+                }
+            }
+        }
+        // could not decide, callers gets to decide; usually will deny
+        return Validity.INDETERMINATE;
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/PolymorphicTypeValidator.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/PolymorphicTypeValidator.java
new file mode 100644
index 0000000..f6e093f
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/PolymorphicTypeValidator.java
@@ -0,0 +1,172 @@
+package com.fasterxml.jackson.databind.jsontype;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.cfg.MapperConfig;
+
+/**
+ * Interface for classes that handle validation of class-name - based subtypes used
+ * with Polymorphic Deserialization: both via "default typing" and explicit
+ * {@code @JsonTypeInfo} when using Java Class name as Type Identifier.
+ * The main purpose, initially, is to allow pluggable allow lists to avoid
+ * security problems that occur with unlimited class names
+ * (See <a href="https://medium.com/@cowtowncoder/on-jackson-cves-dont-panic-here-is-what-you-need-to-know-54cd0d6e8062">
+ * this article</a> for full explanation).
+ *<p>
+ * Calls to methods are done as follows:
+ * <ol>
+ *  <li>When a deserializer is needed for a polymorphic property (including root values) -- either
+ *     for explicitly annotated polymorphic type, or "default typing" -- {@link #validateBaseType}
+ *     is called to see if validity can be determined for all possible types: if 
+ *     {@link Validity#ALLOWED} is returned no futher checks are made for any subtypes; of
+ *     {@link Validity#DENIED} is returned, an exception will be thrown to indicate invalid polymorphic
+ *     property
+ *   </li>
+ *  <li>If neither deny nor allowed was returned for property with specific base type, first time
+ *     specific Type Id (Class Name) is encountered, method {@link #validateSubClassName} is called
+ *     with resolved class name: it may indicate allowed/denied, resulting in either allowed use or
+ *     denial with exception
+ *   </li>
+ *  <li>If no denial/allowance indicated, class name is resolved to actual {@link Class}, and
+ *  {@link #validateSubType(MapperConfig, JavaType, JavaType)} is called: if
+ *  {@link Validity#ALLOWED} is returned, usage is accepted; otherwise (denied or indeterminate)
+ *  usage is not allowed and exception is thrown
+ *   </li>
+ * </ol>
+ *<p>
+ * Notes on implementations: implementations must be thread-safe and shareable (usually meaning they
+ * are stateless). Determinations for validity are usually effectively cached on per-property
+ * basis (by virtue of subtype deserializers being cached by polymorphic deserializers) so
+ * caching at validator level is usually not needed. If caching is used, however, it must be done
+ * in thread-safe manner as validators are shared within {@link ObjectMapper} as well as possible
+ * across mappers (in case of default/standard validator).
+ *<p>
+ * Also note that it is strongly recommended that all implementations are based on provided
+ * abstract base class, {@link PolymorphicTypeValidator.Base} which contains helper methods
+ * and default implementations for returning {@link Validity#INDETERMINATE} for validation
+ * methods (to allow only overriding relevant methods implementation cares about)
+ *
+ * @since 2.10
+ */
+public abstract class PolymorphicTypeValidator
+    implements java.io.Serializable
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Definition of return values to indicate determination regarding validity.
+     */
+    public enum Validity {
+        /**
+         * Value that indicates that Class name or Class is allowed for use without further checking
+         */
+        ALLOWED,
+        /**
+         * Value that indicates that Class name or Class is NOT allowed and no further checks are
+         * needed or allowed
+         */
+        DENIED,
+
+        /**
+         * Value that indicates that Class name or Class validity can not be confirmed by validator
+         * and further checks are needed.
+         *<p>
+         * Typically if validator can not establish validity from Type Id or Class (name), eventual
+         * determination will be {@code DENIED}, for safety reasons.
+         */
+        INDETERMINATE
+        ;
+    }
+
+    /**
+     * Method called when a property with polymorphic value is encountered, and a
+     * {@code TypeResolverBuilder} is needed. Intent is to allow early determination
+     * of cases where subtyping is completely denied (for example for security reasons),
+     * or, conversely, allowed for allow subtypes (when base type guarantees that all subtypes
+     * are known to be safe). Check can be thought of as both optimization (for latter case)
+     * and eager-fail (for former case) to give better feedback.
+     * 
+     * @param config Configuration for resolution: typically will be {@code DeserializationConfig}
+     * @param baseType Nominal base type used for polymorphic handling: subtypes MUST be instances
+     *   of this type and assignment compatibility is verified by Jackson core
+     *
+     * @return Determination of general validity of all subtypes of given base type; if
+     *    {@link Validity#ALLOWED} returned, all subtypes will automatically be accepted without
+     *    further checks; is {@link Validity#DENIED} returned no subtyping allowed at all
+     *    (caller will usually throw an exception); otherwise (return {@link Validity#INDETERMINATE})
+     *    per sub-type validation calls are made for each new subclass encountered.
+     */
+    public abstract Validity validateBaseType(MapperConfig<?> config, JavaType baseType);
+
+    /**
+     * Method called after intended class name for subtype has been read (and in case of minimal
+     * class name, expanded to fully-qualified class name) but before attempt is made to
+     * look up actual {@link java.lang.Class} or {@link JavaType}.
+     * Validator may be able to
+     * determine validity of eventual type (and return {@link Validity#ALLOWED} or
+     * {@link Validity#DENIED}) or, if not able to, can defer validation to actual
+     * resolved type by returning {@link Validity#INDETERMINATE}.
+     *<p>
+     * Validator may also choose to indicate denial by throwing a {@link JsonMappingException}
+     * (such as {@link com.fasterxml.jackson.databind.exc.InvalidTypeIdException})
+     *
+     * @param config Configuration for resolution: typically will be {@code DeserializationConfig}
+     * @param baseType Nominal base type used for polymorphic handling: subtypes MUST be instances
+     *   of this type and assignment compatibility is verified by Jackson core
+     * @param subClassName Name of class that will be resolved to {@link java.lang.Class} if
+     *   (and only if) validity check is not denied.
+     *
+     * @return Determination of validity of given class name, as a subtype of given base type:
+     *   should NOT return {@code null}
+     */
+    public abstract Validity validateSubClassName(MapperConfig<?> config, JavaType baseType,
+            String subClassName) throws JsonMappingException;
+
+    /**
+     * Method called after class name has been resolved to actual type, in cases where previous
+     * call to {@link #validateSubClassName} returned {@link Validity#INDETERMINATE}.
+     * Validator should be able to determine validity and return appropriate {@link Validity}
+     * value, although it may also
+     *<p>
+     * Validator may also choose to indicate denial by throwing a {@link JsonMappingException}
+     * (such as {@link com.fasterxml.jackson.databind.exc.InvalidTypeIdException})
+     *
+     * @param config Configuration for resolution: typically will be {@code DeserializationConfig}
+     * @param baseType Nominal base type used for polymorphic handling: subtypes MUST be instances
+     *   of this type and assignment compatibility has been verified by Jackson core
+     * @param subType Resolved subtype to validate
+     *
+     * @return Determination of validity of given class name, as a subtype of given base type:
+     *   should NOT return {@code null}
+     */
+    public abstract Validity validateSubType(MapperConfig<?> config, JavaType baseType,
+            JavaType subType) throws JsonMappingException;
+
+    /**
+     * Shared base class with partial implementation (with all validation calls returning
+     * {@link Validity#INDETERMINATE}) and convenience methods for indicating failure reasons.
+     * Use of this base class is strongly recommended over directly implement
+     */
+    public abstract static class Base
+        extends PolymorphicTypeValidator
+        implements java.io.Serializable
+    {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public Validity validateBaseType(MapperConfig<?> config, JavaType baseType) {
+            return Validity.INDETERMINATE;
+        }
+    
+        @Override
+        public Validity validateSubClassName(MapperConfig<?> config, JavaType baseType, String subClassName)
+                throws JsonMappingException {
+            return Validity.INDETERMINATE;
+        }
+    
+        @Override
+        public Validity validateSubType(MapperConfig<?> config, JavaType baseType, JavaType subType)
+                throws JsonMappingException {
+            return Validity.INDETERMINATE;
+        }
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeDeserializer.java
index b5e265f..5173845 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeDeserializer.java
@@ -141,7 +141,7 @@
     public static Object deserializeIfNatural(JsonParser p, DeserializationContext ctxt,
             Class<?> base) throws IOException
     {
-        JsonToken t = p.getCurrentToken();
+        final JsonToken t = p.currentToken();
         if (t == null) {
             return null;
         }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsArrayTypeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsArrayTypeDeserializer.java
index 250db2b..2f53079 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsArrayTypeDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsArrayTypeDeserializer.java
@@ -101,7 +101,7 @@
                 //   internal and external properties
                 //  TODO: but does it need to be injected in external case? Why not?
                 && !_usesExternalId()
-                && p.getCurrentToken() == JsonToken.START_OBJECT) {
+                && p.hasToken(JsonToken.START_OBJECT)) {
             // but what if there's nowhere to add it in? Error? Or skip? For now, skip.
             TokenBuffer tb = new TokenBuffer(null, false);
             tb.writeStartObject(); // recreate START_OBJECT
@@ -113,6 +113,10 @@
             p = JsonParserSequence.createFlattened(false, tb.asParser(p), p);
             p.nextToken();
         }
+        // [databind#2467] (2.10): Allow missing value to be taken as "just use null value"
+        if (hadStartArray && p.currentToken() == JsonToken.END_ARRAY) {
+            return deser.getNullValue(ctxt);
+        }
         Object value = deser.deserialize(p, ctxt);
         // And then need the closing END_ARRAY
         if (hadStartArray && p.nextToken() != JsonToken.END_ARRAY) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsPropertyTypeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsPropertyTypeDeserializer.java
index 9bfab80..47017f9 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsPropertyTypeDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsPropertyTypeDeserializer.java
@@ -74,7 +74,7 @@
         }
         
         // but first, sanity check to ensure we have START_OBJECT or FIELD_NAME
-        JsonToken t = p.getCurrentToken();
+        JsonToken t = p.currentToken();
         if (t == JsonToken.START_OBJECT) {
             t = p.nextToken();
         } else if (/*t == JsonToken.START_ARRAY ||*/ t != JsonToken.FIELD_NAME) {
@@ -187,12 +187,12 @@
         /* Sometimes, however, we get an array wrapper; specifically
          * when an array or list has been serialized with type information.
          */
-        if (p.getCurrentToken() == JsonToken.START_ARRAY) {
+        if (p.hasToken(JsonToken.START_ARRAY)) {
             return super.deserializeTypedFromArray(p, ctxt);
         }
         return deserializeTypedFromObject(p, ctxt);
     }    
-    
+
     // These are fine from base class:
     //public Object deserializeTypedFromArray(JsonParser jp, DeserializationContext ctxt)
     //public Object deserializeTypedFromScalar(JsonParser jp, DeserializationContext ctxt)    
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsWrapperTypeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsWrapperTypeDeserializer.java
index 643f921..7594023 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsWrapperTypeDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsWrapperTypeDeserializer.java
@@ -89,7 +89,7 @@
             }
         }
         // first, sanity checks
-        JsonToken t = p.getCurrentToken();
+        JsonToken t = p.currentToken();
         if (t == JsonToken.START_OBJECT) {
             // should always get field name, but just in case...
             if (p.nextToken() != JsonToken.FIELD_NAME) {
@@ -105,7 +105,7 @@
         p.nextToken();
 
         // Minor complication: we may need to merge type id in?
-        if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) {
+        if (_typeIdVisible && p.hasToken(JsonToken.START_OBJECT)) {
             // but what if there's nowhere to add it in? Error? Or skip? For now, skip.
             TokenBuffer tb = new TokenBuffer(null, false);
             tb.writeStartObject(); // recreate START_OBJECT
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java
index 934cdd3..db9b089 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java
@@ -5,6 +5,8 @@
 
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.cfg.MapperConfig;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 
@@ -18,8 +20,28 @@
 {
     private final static String JAVA_UTIL_PKG = "java.util.";
 
-    public ClassNameIdResolver(JavaType baseType, TypeFactory typeFactory) {
+    protected final PolymorphicTypeValidator _subTypeValidator;
+
+    /**
+     * @deprecated Since 2.10 use variant that takes {@link PolymorphicTypeValidator}
+     */
+    @Deprecated
+    protected ClassNameIdResolver(JavaType baseType, TypeFactory typeFactory) {
+        this(baseType, typeFactory, LaissezFaireSubTypeValidator.instance);
+    }
+
+    /**
+     * @since 2.10
+     */
+    public ClassNameIdResolver(JavaType baseType, TypeFactory typeFactory,
+            PolymorphicTypeValidator ptv) {
         super(baseType, typeFactory);
+        _subTypeValidator = ptv;
+    }
+
+    public static ClassNameIdResolver construct(JavaType baseType, MapperConfig<?> config,
+            PolymorphicTypeValidator ptv) {
+        return new ClassNameIdResolver(baseType, config.getTypeFactory(), ptv);
     }
 
     @Override
@@ -46,7 +68,8 @@
 
     protected JavaType _typeFromId(String id, DatabindContext ctxt) throws IOException
     {
-        JavaType t = ctxt.resolveSubType(_baseType, id);
+        // 24-Apr-2019, tatu: [databind#2195] validate as well as resolve:
+        JavaType t = ctxt.resolveAndValidateSubType(_baseType, id, _subTypeValidator);
         if (t == null) {
             if (ctxt instanceof DeserializationContext) {
                 // First: we may have problem handlers that can deal with it?
@@ -66,8 +89,13 @@
     protected String _idFrom(Object value, Class<?> cls, TypeFactory typeFactory)
     {
         // Need to ensure that "enum subtypes" work too
-        if (Enum.class.isAssignableFrom(cls)) {
-            if (!cls.isEnum()) { // means that it's sub-class of base enum, so:
+        if (ClassUtil.isEnumType(cls)) {
+            // 29-Sep-2019, tatu: `Class.isEnum()` only returns true for main declaration,
+            //   but NOT from sub-class thereof (extending individual values). This
+            //   is why additional resolution is needed: we want class that contains
+            //   enumeration instances.
+            if (!cls.isEnum()) {
+                // and this parent would then have `Enum.class` as its parent:
                 cls = cls.getSuperclass();
             }
         }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/LaissezFaireSubTypeValidator.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/LaissezFaireSubTypeValidator.java
new file mode 100644
index 0000000..cfc1816
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/LaissezFaireSubTypeValidator.java
@@ -0,0 +1,38 @@
+package com.fasterxml.jackson.databind.jsontype.impl;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.cfg.MapperConfig;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
+
+/**
+ * Default {@link PolymorphicTypeValidator} used unless explicit one is constructed.
+ * Does not do any validation, allows all subtypes. Only used for backwards-compatibility
+ * reasons: users should not usually use such a permissive implementation but use
+ * allow-list/criteria - based implementation.
+ *
+ * @since 2.10
+ */
+public final class LaissezFaireSubTypeValidator
+    extends PolymorphicTypeValidator.Base
+{
+    private static final long serialVersionUID = 1L;
+
+    public final static LaissezFaireSubTypeValidator instance = new LaissezFaireSubTypeValidator(); 
+
+    @Override
+    public Validity validateBaseType(MapperConfig<?> ctxt, JavaType baseType) {
+        return Validity.INDETERMINATE;
+    }
+
+    @Override
+    public Validity validateSubClassName(MapperConfig<?> ctxt,
+            JavaType baseType, String subClassName) {
+        return Validity.ALLOWED;
+    }
+
+    @Override
+    public Validity validateSubType(MapperConfig<?> ctxt, JavaType baseType,
+            JavaType subType) {
+        return Validity.ALLOWED;
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/MinimalClassNameIdResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/MinimalClassNameIdResolver.java
index d208c30..dc7dfb3 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/MinimalClassNameIdResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/MinimalClassNameIdResolver.java
@@ -5,6 +5,8 @@
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.databind.DatabindContext;
 import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.cfg.MapperConfig;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
 public class MinimalClassNameIdResolver
@@ -22,9 +24,10 @@
      */
     protected final String _basePackagePrefix;
 
-    protected MinimalClassNameIdResolver(JavaType baseType, TypeFactory typeFactory)
+    protected MinimalClassNameIdResolver(JavaType baseType, TypeFactory typeFactory,
+            PolymorphicTypeValidator ptv)
     {
-        super(baseType, typeFactory);
+        super(baseType, typeFactory, ptv);
         String base = baseType.getRawClass().getName();
         int ix = base.lastIndexOf('.');
         if (ix < 0) { // can this ever occur?
@@ -36,6 +39,11 @@
         }
     }
 
+    public static MinimalClassNameIdResolver construct(JavaType baseType, MapperConfig<?> config,
+            PolymorphicTypeValidator ptv) {
+        return new MinimalClassNameIdResolver(baseType, config.getTypeFactory(), ptv);
+    }
+
     @Override
     public JsonTypeInfo.Id getMechanism() { return JsonTypeInfo.Id.MINIMAL_CLASS; }
     
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder.java
index 98e9f90..5f30bc2 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder.java
@@ -8,6 +8,8 @@
 import com.fasterxml.jackson.databind.annotation.NoClass;
 import com.fasterxml.jackson.databind.cfg.MapperConfig;
 import com.fasterxml.jackson.databind.jsontype.*;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator.Validity;
+import com.fasterxml.jackson.databind.util.ClassUtil;
 
 /**
  * Default {@link TypeResolverBuilder} implementation.
@@ -84,7 +86,8 @@
         if (baseType.isPrimitive()) {
             return null;
         }
-        TypeIdResolver idRes = idResolver(config, baseType, subtypes, true, false);
+        TypeIdResolver idRes = idResolver(config, baseType, subTypeValidator(config),
+                subtypes, true, false);
         switch (_includeAs) {
         case WRAPPER_ARRAY:
             return new AsArrayTypeSerializer(idRes, null);
@@ -118,7 +121,11 @@
             return null;
         }
 
-        TypeIdResolver idRes = idResolver(config, baseType, subtypes, false, true);
+        // 27-Apr-2019, tatu: Part of [databind#2195]; must first check whether any subtypes
+        //    of basetypes might be denied or allowed
+        final PolymorphicTypeValidator subTypeValidator = verifyBaseTypeValidity(config, baseType);
+
+        TypeIdResolver idRes = idResolver(config, baseType, subTypeValidator, subtypes, false, true);
 
         JavaType defaultImpl = defineDefaultImpl(config, baseType);
 
@@ -236,29 +243,30 @@
 
     public String getTypeProperty() { return _typeProperty; }
     public boolean isTypeIdVisible() { return _typeIdVisible; }
-    
+
     /*
     /**********************************************************
-    /* Internal methods
+    /* Internal/subtype factory methods
     /**********************************************************
      */
-    
+
     /**
      * Helper method that will either return configured custom
      * type id resolver, or construct a standard resolver
      * given configuration.
      */
     protected TypeIdResolver idResolver(MapperConfig<?> config,
-            JavaType baseType, Collection<NamedType> subtypes, boolean forSer, boolean forDeser)
+            JavaType baseType, PolymorphicTypeValidator subtypeValidator,
+            Collection<NamedType> subtypes, boolean forSer, boolean forDeser)
     {
         // Custom id resolver?
         if (_customIdResolver != null) { return _customIdResolver; }
         if (_idType == null) throw new IllegalStateException("Cannot build, 'init()' not yet called");
         switch (_idType) {
         case CLASS:
-            return new ClassNameIdResolver(baseType, config.getTypeFactory());
+            return ClassNameIdResolver.construct(baseType, config, subtypeValidator);
         case MINIMAL_CLASS:
-            return new MinimalClassNameIdResolver(baseType, config.getTypeFactory());
+            return MinimalClassNameIdResolver.construct(baseType, config, subtypeValidator);
         case NAME:
             return TypeNameIdResolver.construct(config, baseType, subtypes, forSer, forDeser);
         case NONE: // hmmh. should never get this far with 'none'
@@ -267,4 +275,61 @@
         }
         throw new IllegalStateException("Do not know how to construct standard type id resolver for idType: "+_idType);
     }
+
+    /*
+    /**********************************************************
+    /* Internal/subtype factory methods
+    /**********************************************************
+     */
+
+    /**
+     * Overridable helper method for determining actual validator to use when constructing
+     * type serializers and type deserializers.
+     *<p>
+     * Default implementation simply uses one configured and accessible using
+     * {@link MapperConfig#getPolymorphicTypeValidator()}.
+     *
+     * @since 2.10
+     */
+    public PolymorphicTypeValidator subTypeValidator(MapperConfig<?> config) {
+        return config.getPolymorphicTypeValidator();
+    }
+    
+    /**
+     * Helper method called to check that base type is valid regarding possible constraints
+     * on basetype/subtype combinations allowed for polymorphic type handling.
+     * Currently limits are verified for class name - based methods only.
+     *
+     * @since 2.10
+     */
+    protected PolymorphicTypeValidator verifyBaseTypeValidity(MapperConfig<?> config,
+            JavaType baseType)
+    {
+        final PolymorphicTypeValidator ptv = subTypeValidator(config);
+        if (_idType == JsonTypeInfo.Id.CLASS || _idType == JsonTypeInfo.Id.MINIMAL_CLASS) {
+            final Validity validity = ptv.validateBaseType(config, baseType);
+            // If no subtypes are legal (that is, base type itself is invalid), indicate problem
+            if (validity == Validity.DENIED) {
+                return reportInvalidBaseType(config, baseType, ptv);
+            }
+            // If there's indication that any and all subtypes are fine, replace validator itself:
+            if (validity == Validity.ALLOWED) {
+                return LaissezFaireSubTypeValidator.instance;
+            }
+            // otherwise just return validator, is to be called for each distinct type
+        }
+        return ptv;
+    }
+
+    /**
+     * @since 2.10
+     */
+    protected PolymorphicTypeValidator reportInvalidBaseType(MapperConfig<?> config,
+            JavaType baseType, PolymorphicTypeValidator ptv)
+    {
+        throw new IllegalArgumentException(String.format(
+"Configured `PolymorphicTypeValidator` (of type %s) denied resolution of all subtypes of base type %s",
+                        ClassUtil.classNameOf(ptv), ClassUtil.classNameOf(baseType.getRawClass()))
+        );
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java
index 64c6c76..807757e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/SubTypeValidator.java
@@ -13,7 +13,7 @@
  * Helper class used to encapsulate rules that determine subtypes that
  * are invalid to use, even with default typing, mostly due to security
  * concerns.
- * Used by <code>BeanDeserializerFacotry</code>
+ * Used by <code>BeanDeserializerFactory</code>
  *
  * @since 2.8.11
  */
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java
index 58f1a5f..9e51d90 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java
@@ -133,8 +133,8 @@
         sb.append('[').append(getClass().getName());
         sb.append("; base-type:").append(_baseType);
         sb.append("; id-resolver: ").append(_idResolver);
-    	    sb.append(']');
-    	    return sb.toString();
+        sb.append(']');
+        return sb.toString();
     }
     
     /*
@@ -242,14 +242,13 @@
      * 
      * @since 2.4
      */
-    protected Object _deserializeWithNativeTypeId(JsonParser jp, DeserializationContext ctxt, Object typeId)
+    protected Object _deserializeWithNativeTypeId(JsonParser p, DeserializationContext ctxt, Object typeId)
         throws IOException
     {
         JsonDeserializer<Object> deser;
         if (typeId == null) {
-            /* 04-May-2014, tatu: Should error be obligatory, or should there be another method
-             *   for "try to deserialize with native tpye id"?
-             */
+            // 04-May-2014, tatu: Should error be obligatory, or should there be another method
+            //   for "try to deserialize with native type id"?
             deser = _findDefaultImplDeserializer(ctxt);
             if (deser == null) {
                 return ctxt.reportInputMismatch(baseType(),
@@ -259,7 +258,7 @@
             String typeIdStr = (typeId instanceof String) ? (String) typeId : String.valueOf(typeId);
             deser = _findDeserializer(ctxt, typeIdStr);
         }
-        return deser.deserialize(jp, ctxt);
+        return deser.deserialize(p, ctxt);
     }
 
     /**
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeNameIdResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeNameIdResolver.java
index d607fbf..1d2d785 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeNameIdResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeNameIdResolver.java
@@ -1,6 +1,7 @@
 package com.fasterxml.jackson.databind.jsontype.impl;
 
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
 
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.databind.BeanDescription;
@@ -14,46 +15,55 @@
     protected final MapperConfig<?> _config;
 
     /**
-     * Mappings from class name to type id, used for serialization
+     * Mappings from class name to type id, used for serialization.
+     *<p>
+     * Since lazily constructed will require synchronization (either internal
+     * by type, or external)
      */
-    protected final Map<String, String> _typeToId;
+    protected final ConcurrentHashMap<String, String> _typeToId;
 
     /**
-     * Mappings from type id to JavaType, used for deserialization
+     * Mappings from type id to JavaType, used for deserialization.
+     *<p>
+     * Eagerly constructed, not modified, can use regular unsynchronized {@link Map}.
      */
     protected final Map<String, JavaType> _idToType;
 
     protected TypeNameIdResolver(MapperConfig<?> config, JavaType baseType,
-            Map<String, String> typeToId, Map<String, JavaType> idToType)
+            ConcurrentHashMap<String, String> typeToId,
+            HashMap<String, JavaType> idToType)
     {
         super(baseType, config.getTypeFactory());
         _config = config;
         _typeToId = typeToId;
         _idToType = idToType;
     }
- 
+
     public static TypeNameIdResolver construct(MapperConfig<?> config, JavaType baseType,
             Collection<NamedType> subtypes, boolean forSer, boolean forDeser)
     {
         // sanity check
         if (forSer == forDeser) throw new IllegalArgumentException();
-        Map<String, String> typeToId = null;
-        Map<String, JavaType> idToType = null;
+
+        final ConcurrentHashMap<String, String> typeToId;
+        final HashMap<String, JavaType> idToType;
 
         if (forSer) {
-            typeToId = new HashMap<String, String>();
-        }
-        if (forDeser) {
-            idToType = new HashMap<String, JavaType>();
+            // Only need Class-to-id for serialization; but synchronized since may be
+            // lazily built (if adding type-id-mappings dynamically)
+            typeToId = new ConcurrentHashMap<>();
+            idToType = null;
+        } else {
+            idToType = new HashMap<>();
             // 14-Apr-2016, tatu: Apparently needed for special case of `defaultImpl`;
-            //    see [databind#1198] for details.
-            typeToId = new TreeMap<String, String>();
+            //    see [databind#1198] for details: but essentially we only need room
+            //    for a single value.
+            typeToId = new ConcurrentHashMap<>(4);
         }
         if (subtypes != null) {
             for (NamedType t : subtypes) {
-                /* no name? Need to figure out default; for now, let's just
-                 * use non-qualified class name
-                 */
+                // no name? Need to figure out default; for now, let's just
+                // use non-qualified class name
                 Class<?> cls = t.getType();
                 String id = t.hasName() ? t.getName() : _defaultTypeId(cls);
                 if (forSer) {
@@ -88,34 +98,34 @@
         if (clazz == null) {
             return null;
         }
-        Class<?> cls = _typeFactory.constructType(clazz).getRawClass();
-        final String key = cls.getName();
-        String name;
+        // NOTE: although we may need to let `TypeModifier` change actual type to use
+        // for id, we can use original type as key for more efficient lookup:
+        final String key = clazz.getName();
+        String name = _typeToId.get(key);
 
-        synchronized (_typeToId) {
-            name = _typeToId.get(key);
-            if (name == null) {
-                // 24-Feb-2011, tatu: As per [JACKSON-498], may need to dynamically look up name
-                // can either throw an exception, or use default name...
-                if (_config.isAnnotationProcessingEnabled()) {
-                    BeanDescription beanDesc = _config.introspectClassAnnotations(cls);
-                    name = _config.getAnnotationIntrospector().findTypeName(beanDesc.getClassInfo());
-                }
-                if (name == null) {
-                    // And if still not found, let's choose default?
-                    name = _defaultTypeId(cls);
-                }
-                _typeToId.put(key, name);
+        if (name == null) {
+            // 29-Nov-2019, tatu: As per test in `TestTypeModifierNameResolution` somehow
+            //    we need to do this odd piece here which seems unnecessary but isn't.
+            Class<?> cls = _typeFactory.constructType(clazz).getRawClass();                
+            // 24-Feb-2011, tatu: As per [JACKSON-498], may need to dynamically look up name
+            // can either throw an exception, or use default name...
+            if (_config.isAnnotationProcessingEnabled()) {
+                BeanDescription beanDesc = _config.introspectClassAnnotations(cls);
+                name = _config.getAnnotationIntrospector().findTypeName(beanDesc.getClassInfo());
             }
+            if (name == null) {
+                // And if still not found, let's choose default?
+                name = _defaultTypeId(cls);
+            }
+            _typeToId.put(key, name);
         }
         return name;
     }
 
     @Override
     public String idFromValueAndType(Object value, Class<?> type) {
-        /* 18-Jan-2013, tatu: We may be called with null value occasionally
-         *   it seems; nothing much we can figure out that way.
-         */
+        // 18-Jan-2013, tatu: We may be called with null value occasionally
+        //   it seems; nothing much we can figure out that way.
         if (value == null) {
             return idFromClass(type);
         }
@@ -128,11 +138,10 @@
     }
     
     protected JavaType _typeFromId(String id) {
-        /* Now: if no type is found, should we try to locate it by
-         * some other means? (specifically, if in same package as base type,
-         * could just try Class.forName)
-         * For now let's not add any such workarounds; can add if need be
-         */
+        // Now: if no type is found, should we try to locate it by
+        // some other means? (specifically, if in same package as base type,
+        // could just try Class.forName)
+        // For now let's not add any such workarounds; can add if need be
         return _idToType.get(id);
     }    
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/module/SimpleDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/module/SimpleDeserializers.java
index 0a9f443..ba0cbb1 100644
--- a/src/main/java/com/fasterxml/jackson/databind/module/SimpleDeserializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/module/SimpleDeserializers.java
@@ -126,6 +126,10 @@
         }
         JsonDeserializer<?> deser = _classMappings.get(new ClassKey(type));
         if (deser == null) {
+            // 29-Sep-2019, tatu: Not 100% sure this is workable logic but leaving
+            //   as is (wrt [databind#2457]. Probably works ok since this covers direct
+            //   sub-classes of `Enum`; but even if custom sub-classes aren't, unlikely
+            //   mapping for those ever requested for deserialization
             if (_hasEnumDeserializer && type.isEnum()) {
                 deser = _classMappings.get(new ClassKey(Enum.class));
             }
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java b/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java
index 6b49f32..fdd4782 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/ArrayNode.java
@@ -23,7 +23,10 @@
  */
 public class ArrayNode
     extends ContainerNode<ArrayNode>
+    implements java.io.Serializable // since 2.10
 {
+    private static final long serialVersionUID = 1L;
+
     private final List<JsonNode> _children;
 
     public ArrayNode(JsonNodeFactory nf) {
@@ -99,6 +102,9 @@
         return _children.size();
     }
 
+    @Override // since 2.10
+    public boolean isEmpty() { return _children.isEmpty(); }
+
     @Override
     public Iterator<JsonNode> elements() {
         return _children.iterator();
@@ -106,7 +112,7 @@
 
     @Override
     public JsonNode get(int index) {
-        if (index >= 0 && index < _children.size()) {
+        if ((index >= 0) && (index < _children.size())) {
             return _children.get(index);
         }
         return null;
@@ -127,6 +133,15 @@
     }
 
     @Override
+    public JsonNode required(int index) {
+        if ((index >= 0) && (index < _children.size())) {
+            return _children.get(index);
+        }
+        return _reportRequiredViolation("No value at index #%d [0, %d) of `ArrayNode`",
+                index, _children.size());
+    }
+
+    @Override
     public boolean equals(Comparator<JsonNode> comparator, JsonNode o)
     {
         if (!(o instanceof ArrayNode)) {
@@ -158,7 +173,7 @@
     {
         final List<JsonNode> c = _children;
         final int size = c.size();
-        f.writeStartArray(size);
+        f.writeStartArray(this, size);
         for (int i = 0; i < size; ++i) { // we'll typically have array list
             // For now, assuming it's either BaseJsonNode, JsonSerializable
             JsonNode n = c.get(i);
@@ -301,14 +316,16 @@
      */
     public ArrayNode addAll(Collection<? extends JsonNode> nodes)
     {
-        _children.addAll(nodes);
+        for (JsonNode node : nodes) {
+            add(node);
+        }
         return this;
     }
 
     /**
      * Method for inserting specified child node as an element
      * of this Array. If index is 0 or less, it will be inserted as
-     * the first element; if >= size(), appended at the end, and otherwise
+     * the first element; if {@code >= size()}, appended at the end, and otherwise
      * inserted before existing element in specified index.
      * No exceptions are thrown for any index.
      *
@@ -839,21 +856,6 @@
         return _children.hashCode();
     }
 
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder(16 + (size() << 4));
-        sb.append('[');
-        for (int i = 0, len = _children.size(); i < len; ++i) {
-            if (i > 0) {
-                sb.append(',');
-            }
-            sb.append(_children.get(i).toString());
-        }
-        sb.append(']');
-        return sb.toString();
-    }
-
     /*
     /**********************************************************
     /* Internal methods (overridable)
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/BaseJsonNode.java b/src/main/java/com/fasterxml/jackson/databind/node/BaseJsonNode.java
index d0d38dd..ea090f0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/BaseJsonNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/BaseJsonNode.java
@@ -14,11 +14,20 @@
  * The main addition here is that we declare that sub-classes must
  * implement {@link JsonSerializable}.
  * This simplifies object mapping aspects a bit, as no external serializers are needed.
+ *<p>
+ * Since 2.10, all implements have been {@link java.io.Serializable}.
  */
 public abstract class BaseJsonNode
     extends JsonNode
-    implements JsonSerializable
+    implements java.io.Serializable
 {
+    private static final long serialVersionUID = 1L;
+
+    // Simplest way is by using a helper
+    Object writeReplace() {
+        return NodeSerialization.from(this);
+    }
+
     protected BaseJsonNode() { }
 
     /*
@@ -41,6 +50,24 @@
     @Override public abstract int hashCode();
 
     /*
+    /**********************************************************************
+    /* Improved required-ness checks for standard JsonNode implementations
+    /**********************************************************************
+     */
+
+    @Override
+    public JsonNode required(String fieldName) {
+        return _reportRequiredViolation("Node of type `%s` has no fields",
+                getClass().getSimpleName());
+    }
+
+    @Override
+    public JsonNode required(int index) {
+        return _reportRequiredViolation("Node of type `%s` has no indexed values",
+                getClass().getSimpleName());
+    }
+
+    /*
     /**********************************************************
     /* Support for traversal-as-stream
     /**********************************************************
@@ -97,5 +124,21 @@
     public abstract void serializeWithType(JsonGenerator jgen, SerializerProvider provider,
             TypeSerializer typeSer)
         throws IOException, JsonProcessingException;
+
+   /*
+   /**********************************************************
+   /* Standard method overrides
+   /**********************************************************
+    */
+
+   @Override
+   public String toString() {
+       return InternalNodeMapper.nodeToString(this);
+   }
+
+   @Override
+   public String toPrettyString() {
+       return InternalNodeMapper.nodeToPrettyString(this);
+   }
 }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/BigIntegerNode.java b/src/main/java/com/fasterxml/jackson/databind/node/BigIntegerNode.java
index 39083c5..9f38dfc 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/BigIntegerNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/BigIntegerNode.java
@@ -10,6 +10,7 @@
 /**
  * Numeric node that contains simple 64-bit integer values.
  */
+@SuppressWarnings("serial")
 public class BigIntegerNode
     extends NumericNode
 {
@@ -17,9 +18,9 @@
     private final static BigInteger MAX_INTEGER = BigInteger.valueOf(Integer.MAX_VALUE);
     private final static BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE);
     private final static BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
-    
+
     final protected BigInteger _value;
-    
+
     /*
     /**********************************************************
     /* Construction
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/BinaryNode.java b/src/main/java/com/fasterxml/jackson/databind/node/BinaryNode.java
index 858d56c..4522735 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/BinaryNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/BinaryNode.java
@@ -14,6 +14,8 @@
 public class BinaryNode
     extends ValueNode
 {
+    private static final long serialVersionUID = 2L;
+
     final static BinaryNode EMPTY_BINARY_NODE = new BinaryNode(new byte[0]);
 
     protected final byte[] _data;
@@ -110,14 +112,4 @@
     public int hashCode() {
         return (_data == null) ? -1 : _data.length;
     }
-
-    /**
-     * Different from other values, since contents need to be surrounded
-     * by (double) quotes.
-     */
-    @Override
-    public String toString()
-    {
-        return Base64Variants.getDefaultVariant().encode(_data, true);
-    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/BooleanNode.java b/src/main/java/com/fasterxml/jackson/databind/node/BooleanNode.java
index ac3b390..a3bb91f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/BooleanNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/BooleanNode.java
@@ -14,6 +14,8 @@
 public class BooleanNode
     extends ValueNode
 {
+    private static final long serialVersionUID = 2L;
+
     // // Just need two instances...
 
     public final static BooleanNode TRUE = new BooleanNode(true);
@@ -27,6 +29,11 @@
      */
     protected BooleanNode(boolean v) { _value = v; }
 
+    // To support JDK serialization, recovery of Singleton instance
+    protected Object readResolve() {
+        return _value ? TRUE : FALSE;
+    }
+
     public static BooleanNode getTrue() { return TRUE; }
     public static BooleanNode getFalse() { return FALSE; }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/ContainerNode.java b/src/main/java/com/fasterxml/jackson/databind/node/ContainerNode.java
index fcfb23a..919219c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/ContainerNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/ContainerNode.java
@@ -15,6 +15,8 @@
     extends BaseJsonNode
     implements JsonNodeCreator
 {
+    private static final long serialVersionUID = 1L;
+
     /**
      * We will keep a reference to the Object (usually TreeMapper)
      * that can construct instances of nodes to add to this container
@@ -26,6 +28,8 @@
         _nodeFactory = nc;
     }
 
+    protected ContainerNode() { _nodeFactory = null; } // only for JDK ser
+
     // all containers are mutable: can't define:
 //    @Override public abstract <T extends JsonNode> T deepCopy();
 
@@ -52,11 +56,26 @@
 
     /*
     /**********************************************************
-    /* JsonNodeCreator implementation, just dispatch to
-    /* the real creator
+    /* JsonNodeCreator implementation, Enumerated/singleton types
     /**********************************************************
      */
 
+    @Override
+    public final BooleanNode booleanNode(boolean v) { return _nodeFactory.booleanNode(v); }
+
+    public JsonNode missingNode() {
+        return _nodeFactory.missingNode();
+    }
+
+    @Override
+    public final NullNode nullNode() { return _nodeFactory.nullNode(); }
+
+    /*
+    /**********************************************************
+    /* JsonNodeCreator implementation, just dispatch to real creator
+    /**********************************************************
+     */
+    
     /**
      * Factory method that constructs and returns an empty {@link ArrayNode}
      * Construction is done using registered {@link JsonNodeFactory}.
@@ -80,12 +99,6 @@
     public final ObjectNode objectNode() { return _nodeFactory.objectNode(); }
 
     @Override
-    public final NullNode nullNode() { return _nodeFactory.nullNode(); }
-
-    @Override
-    public final BooleanNode booleanNode(boolean v) { return _nodeFactory.booleanNode(v); }
-
-    @Override
     public final NumericNode numberNode(byte v) { return _nodeFactory.numberNode(v); }
     @Override
     public final NumericNode numberNode(short v) { return _nodeFactory.numberNode(v); }
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/DecimalNode.java b/src/main/java/com/fasterxml/jackson/databind/node/DecimalNode.java
index 578a7e7..cae761b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/DecimalNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/DecimalNode.java
@@ -11,6 +11,7 @@
  * Numeric node that contains values that do not fit in simple
  * integer (int, long) or floating point (double) values.
  */
+@SuppressWarnings("serial")
 public class DecimalNode
     extends NumericNode
 {
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/DoubleNode.java b/src/main/java/com/fasterxml/jackson/databind/node/DoubleNode.java
index ae14bdf..f2e5e93 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/DoubleNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/DoubleNode.java
@@ -13,6 +13,7 @@
  * Numeric node that contains 64-bit ("double precision")
  * floating point values simple 32-bit integer values.
  */
+@SuppressWarnings("serial")
 public class DoubleNode
     extends NumericNode
 {
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/FloatNode.java b/src/main/java/com/fasterxml/jackson/databind/node/FloatNode.java
index 2d8a182..a9fcc88 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/FloatNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/FloatNode.java
@@ -14,6 +14,7 @@
  * 
  * @since 2.2
  */
+@SuppressWarnings("serial")
 public class FloatNode extends NumericNode
 {
     protected final float _value;
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/IntNode.java b/src/main/java/com/fasterxml/jackson/databind/node/IntNode.java
index 9ad4709..a7e4257 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/IntNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/IntNode.java
@@ -12,6 +12,7 @@
 /**
  * Numeric node that contains simple 32-bit integer values.
  */
+@SuppressWarnings("serial")
 public class IntNode
     extends NumericNode
 {
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/InternalNodeMapper.java b/src/main/java/com/fasterxml/jackson/databind/node/InternalNodeMapper.java
new file mode 100644
index 0000000..01cf2a4
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/node/InternalNodeMapper.java
@@ -0,0 +1,53 @@
+package com.fasterxml.jackson.databind.node;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+
+/**
+ * Helper class used to implement <code>toString()</code> method for
+ * {@link BaseJsonNode}, by embedding a private instance of
+ * {@link JsonMapper}, only to be used for node serialization.
+ *
+ * @since 2.10 (but not to be included in 3.0)
+ */
+final class InternalNodeMapper {
+    private final static JsonMapper JSON_MAPPER = new JsonMapper();
+
+    private final static ObjectWriter STD_WRITER = JSON_MAPPER.writer();
+    private final static ObjectWriter PRETTY_WRITER = JSON_MAPPER.writer()
+            .withDefaultPrettyPrinter();
+
+    private final static ObjectReader NODE_READER = JSON_MAPPER.readerFor(JsonNode.class);
+
+    // // // Methods for `JsonNode.toString()` and `JsonNode.toPrettyString()`
+    
+    public static String nodeToString(JsonNode n) {
+        try {
+            return STD_WRITER.writeValueAsString(n);
+        } catch (IOException e) { // should never occur
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static String nodeToPrettyString(JsonNode n) {
+        try {
+            return PRETTY_WRITER.writeValueAsString(n);
+        } catch (IOException e) { // should never occur
+            throw new RuntimeException(e);
+        }
+    }
+
+    // // // Methods for JDK serialization support of JsonNodes
+    
+    public static byte[] valueToBytes(Object value) throws IOException {
+        return JSON_MAPPER.writeValueAsBytes(value);
+    }
+
+    public static JsonNode bytesToNode(byte[] json) throws IOException {
+        return NODE_READER.readValue(json);
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeCreator.java b/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeCreator.java
index 55c880f..1334786 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeCreator.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeCreator.java
@@ -19,6 +19,9 @@
     public ValueNode booleanNode(boolean v);
     public ValueNode nullNode();
 
+// Not yet in 2.10, will be added in 3.0    
+//    public JsonNode missingNode();
+    
     // Numeric types
 
     public ValueNode numberNode(byte v);
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeFactory.java b/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeFactory.java
index e933bc8..a924842 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/JsonNodeFactory.java
@@ -3,6 +3,7 @@
 import java.math.BigDecimal;
 import java.math.BigInteger;
 
+import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.util.RawValue;
 
 /**
@@ -108,6 +109,10 @@
     @Override
     public NullNode nullNode() { return NullNode.getInstance(); }
 
+    public JsonNode missingNode() {
+        return MissingNode.getInstance();
+    }
+    
     /*
     /**********************************************************
     /* Factory methods for numeric values
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/LongNode.java b/src/main/java/com/fasterxml/jackson/databind/node/LongNode.java
index b90d2b4..256d3f7 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/LongNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/LongNode.java
@@ -12,6 +12,7 @@
 /**
  * Numeric node that contains simple 64-bit integer values.
  */
+@SuppressWarnings("serial")
 public class LongNode
     extends NumericNode
 {
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/MissingNode.java b/src/main/java/com/fasterxml/jackson/databind/node/MissingNode.java
index 65509fe..120b36c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/MissingNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/MissingNode.java
@@ -22,14 +22,22 @@
 public final class MissingNode
     extends ValueNode
 {
+    private static final long serialVersionUID = 1L;
+
     private final static MissingNode instance = new MissingNode();
 
     /**
      *<p>
-     * NOTE: visibility raised to `protected` in 2.9.3 to allow custom subtypes.
+     * NOTE: visibility raised to `protected` in 2.9.3 to allow custom subtypes
+     * (which may not be greatest idea ever to have but was requested)
      */
     protected MissingNode() { }
 
+    // To support JDK serialization, recovery of Singleton instance
+    protected Object readResolve() {
+        return instance;
+    }
+    
     @Override
     public boolean isMissingNode() {
         return true;
@@ -62,9 +70,15 @@
     public double asDouble(double defaultValue);
     public boolean asBoolean(boolean defaultValue);
     */
+
+    /*
+    /**********************************************************
+    /* Serialization: bit tricky as we don't really have a value
+    /**********************************************************
+     */
     
     @Override
-    public final void serialize(JsonGenerator jg, SerializerProvider provider)
+    public final void serialize(JsonGenerator g, SerializerProvider provider)
         throws IOException, JsonProcessingException
     {
         /* Nothing to output... should we signal an error tho?
@@ -73,7 +87,7 @@
          * cannot just omit a value as JSON Object field name may have
          * been written out.
          */
-        jg.writeNull();
+        g.writeNull();
     }
 
     @Override
@@ -83,29 +97,57 @@
     {
         g.writeNull();
     }
+
+    /*
+    /**********************************************************
+    /* Jackson 2.10 improvements for validation
+    /**********************************************************
+     */
     
+    @SuppressWarnings("unchecked")
     @Override
-    public boolean equals(Object o)
-    {
-        /* Hmmh. Since there's just a singleton instance, this
-         * fails in all cases but with identity comparison.
-         * However: if this placeholder value was to be considered
-         * similar to SQL NULL, it shouldn't even equal itself?
-         * That might cause problems when dealing with collections
-         * like Sets... so for now, let's let identity comparison
-         * return true.
-         */
-        return (o == this);
+    public JsonNode require() {
+        return _reportRequiredViolation("require() called on `MissingNode`");
     }
 
+    @SuppressWarnings("unchecked")
     @Override
-    public String toString() {
-        // toString() should never return null
-        return "";
+    public JsonNode requireNonNull() {
+        return _reportRequiredViolation("requireNonNull() called on `MissingNode`");
     }
 
     @Override
     public int hashCode() {
         return JsonNodeType.MISSING.ordinal();
     }
+
+    /*
+    /**********************************************************
+    /* Standard method overrides
+    /**********************************************************
+     */
+
+    // 10-Dec-2019, tatu: Bit tricky case, see [databind#2566], but seems
+    //    best NOT to produce legit JSON.
+    @Override
+    public String toString() {
+        return "";
+    }
+
+    @Override
+    public String toPrettyString() {
+        return "";
+    }
+    
+    @Override
+    public boolean equals(Object o)
+    {
+        /* Hmmh. Since there's just a singleton instance, this fails in all cases but with
+         * identity comparison. However: if this placeholder value was to be considered
+         * similar to SQL NULL, it shouldn't even equal itself?
+         * That might cause problems when dealing with collections like Sets...
+         * so for now, let's let identity comparison return true.
+         */
+        return (o == this);
+    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/NodeCursor.java b/src/main/java/com/fasterxml/jackson/databind/node/NodeCursor.java
index 7db58f2..752c89b 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/NodeCursor.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/NodeCursor.java
@@ -128,6 +128,7 @@
         @Override
         public JsonToken nextToken() {
             if (!_done) {
+                ++_index;
                 _done = true;
                 return _node.asToken();
             }
@@ -167,6 +168,7 @@
                 _currentNode = null;
                 return null;
             }
+            ++_index;
             _currentNode = _contents.next();
             return _currentNode.asToken();
         }
@@ -213,6 +215,7 @@
                     _current = null;
                     return null;
                 }
+                ++_index;
                 _needEntry = false;
                 _current = _contents.next();
                 _currentName = (_current == null) ? null : _current.getKey();
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/NodeSerialization.java b/src/main/java/com/fasterxml/jackson/databind/node/NodeSerialization.java
new file mode 100644
index 0000000..b15d6ab
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/node/NodeSerialization.java
@@ -0,0 +1,51 @@
+package com.fasterxml.jackson.databind.node;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/**
+ * Helper value class only used during JDK serialization: contains JSON as `byte[]`
+ *
+ * @since 2.10
+ */
+class NodeSerialization implements java.io.Serializable,
+    java.io.Externalizable
+{
+    private static final long serialVersionUID = 1L;
+
+    public byte[] json;
+
+    public NodeSerialization() { }
+
+    public NodeSerialization(byte[] b) { json = b; }
+
+    protected Object readResolve() {
+        try {
+            return InternalNodeMapper.bytesToNode(json);
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Failed to JDK deserialize `JsonNode` value: "+e.getMessage(), e);
+        }
+    }    
+
+    public static NodeSerialization from(Object o) {
+        try {
+            return new NodeSerialization(InternalNodeMapper.valueToBytes(o));
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Failed to JDK serialize `"+o.getClass().getSimpleName()+"` value: "+e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeInt(json.length);
+        out.write(json);
+    }
+
+    @Override
+    public void readExternal(ObjectInput in) throws IOException {
+        final int len = in.readInt();
+        json = new byte[len];
+        in.readFully(json, 0, len);
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/NullNode.java b/src/main/java/com/fasterxml/jackson/databind/node/NullNode.java
index 1a22243..bc2bfb4 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/NullNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/NullNode.java
@@ -3,6 +3,7 @@
 import java.io.IOException;
 
 import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.SerializerProvider;
 
 
@@ -10,11 +11,13 @@
  * This singleton value class is used to contain explicit JSON null
  * value.
  */
-public final class NullNode
+public class NullNode
     extends ValueNode
 {
     // // Just need a fly-weight singleton
 
+    private static final long serialVersionUID = 1L;
+
     public final static NullNode instance = new NullNode();
 
     /**
@@ -23,6 +26,11 @@
      */
     protected NullNode() { }
 
+    // To support JDK serialization, recovery of Singleton instance
+    protected Object readResolve() {
+        return instance;
+    }
+    
     public static NullNode getInstance() { return instance; }
 
     @Override
@@ -35,6 +43,12 @@
     @Override public String asText(String defaultValue) { return defaultValue; }
     @Override public String asText() { return "null"; }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    public JsonNode requireNonNull() {
+        return _reportRequiredViolation("requireNonNull() called on `NullNode`");
+    }
+
     // as with MissingNode, not considered number node; hence defaults are returned if provided
     
     /*
@@ -53,7 +67,9 @@
 
     @Override
     public boolean equals(Object o) {
-        return (o == this);
+        // 29-Aug-2019, tatu: [databind#2433] Since custom sub-classes are allowed (bad idea probably),
+        //     need to do better comparison
+        return (o == this) || (o instanceof NullNode);
     }
 
     @Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/NumericNode.java b/src/main/java/com/fasterxml/jackson/databind/node/NumericNode.java
index a70a6b1..d131e61 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/NumericNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/NumericNode.java
@@ -11,6 +11,8 @@
 public abstract class NumericNode
     extends ValueNode
 {
+    private static final long serialVersionUID = 1L;
+
     protected NumericNode() { }
 
     @Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/ObjectNode.java b/src/main/java/com/fasterxml/jackson/databind/node/ObjectNode.java
index c80d3ad..85634c3 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/ObjectNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/ObjectNode.java
@@ -1,16 +1,16 @@
 package com.fasterxml.jackson.databind.node;
 
+import java.io.*;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.*;
+
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.type.WritableTypeId;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
 import com.fasterxml.jackson.databind.util.RawValue;
 
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.*;
-
 /**
  * Node that maps to JSON Object structures in JSON content.
  *<p>
@@ -18,7 +18,10 @@
  */
 public class ObjectNode
     extends ContainerNode<ObjectNode>
+    implements java.io.Serializable
 {
+    private static final long serialVersionUID = 1L; // since 2.10
+
     // Note: LinkedHashMap for backwards compatibility
     protected final Map<String, JsonNode> _children;
 
@@ -90,6 +93,9 @@
         return _children.size();
     }
 
+    @Override // since 2.10
+    public boolean isEmpty() { return _children.isEmpty(); }
+    
     @Override
     public Iterator<JsonNode> elements() {
         return _children.values().iterator();
@@ -123,6 +129,15 @@
         return MissingNode.getInstance();
     }
 
+    @Override
+    public JsonNode required(String fieldName) {
+        JsonNode n = _children.get(fieldName);
+        if (n != null) {
+            return n;
+        }
+        return _reportRequiredViolation("No value for property '%s' of `ObjectNode`", fieldName);
+    }
+
     /**
      * Method to use for accessing all fields (with both names
      * and values) of this JSON Object.
@@ -132,6 +147,7 @@
         return _children.entrySet().iterator();
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public ObjectNode with(String propertyName) {
         JsonNode n = _children.get(propertyName);
@@ -148,6 +164,7 @@
         return result;
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public ArrayNode withArray(String propertyName)
     {
@@ -353,6 +370,8 @@
      *<p>
      * NOTE: added to replace those uses of {@link #put(String, JsonNode)}
      * where chaining with 'this' is desired.
+     *<p>
+     * NOTE: co-variant return type since 2.10
      *
      * @param value to set field to; if null, will be converted
      *   to a {@link NullNode} first  (to remove field entry, call
@@ -362,18 +381,21 @@
      *
      * @since 2.1
      */
-    public JsonNode set(String fieldName, JsonNode value)
+    @SuppressWarnings("unchecked")
+    public <T extends JsonNode> T set(String fieldName, JsonNode value)
     {
         if (value == null) {
             value = nullNode();
         }
         _children.put(fieldName, value);
-        return this;
+        return (T) this;
     }
 
     /**
      * Method for adding given properties to this object node, overriding
      * any existing values for those properties.
+     *<p>
+     * NOTE: co-variant return type since 2.10
      * 
      * @param properties Properties to add
      * 
@@ -381,7 +403,8 @@
      *
      * @since 2.1
      */
-    public JsonNode setAll(Map<String,? extends JsonNode> properties)
+    @SuppressWarnings("unchecked")
+    public <T extends JsonNode> T setAll(Map<String,? extends JsonNode> properties)
     {
         for (Map.Entry<String,? extends JsonNode> en : properties.entrySet()) {
             JsonNode n = en.getValue();
@@ -390,12 +413,14 @@
             }
             _children.put(en.getKey(), n);
         }
-        return this;
+        return (T) this;
     }
 
     /**
      * Method for adding all properties of the given Object, overriding
      * any existing values for those properties.
+     *<p>
+     * NOTE: co-variant return type since 2.10
      * 
      * @param other Object of which properties to add to this object
      *
@@ -403,12 +428,13 @@
      *
      * @since 2.1
      */
-    public JsonNode setAll(ObjectNode other)
+    @SuppressWarnings("unchecked")
+    public <T extends JsonNode> T setAll(ObjectNode other)
     {
         _children.putAll(other._children);
-        return this;
+        return (T) this;
     }
-    
+
     /**
      * Method for replacing value of specific property with passed
      * value, and returning value (or null if none).
@@ -432,20 +458,25 @@
     /**
      * Method for removing field entry from this ObjectNode, and
      * returning instance after removal.
+     *<p>
+     * NOTE: co-variant return type since 2.10
      * 
      * @return This node after removing entry (if any)
      * 
      * @since 2.1
      */
-    public JsonNode without(String fieldName)
+    @SuppressWarnings("unchecked")
+    public <T extends JsonNode> T without(String fieldName)
     {
         _children.remove(fieldName);
-        return this;
+        return (T) this;
     }
 
     /**
      * Method for removing specified field properties out of
      * this ObjectNode.
+     *<p>
+     * NOTE: co-variant return type since 2.10
      * 
      * @param fieldNames Names of fields to remove
      * 
@@ -453,10 +484,11 @@
      * 
      * @since 2.1
      */
-    public ObjectNode without(Collection<String> fieldNames)
+    @SuppressWarnings("unchecked")
+    public <T extends JsonNode> T without(Collection<String> fieldNames)
     {
         _children.keySet().removeAll(fieldNames);
-        return this;
+        return (T) this;
     }
     
     /*
@@ -485,7 +517,7 @@
         }
         return _children.put(fieldName, value);
     }
-    
+
     /**
      * Method for removing field entry from this ObjectNode.
      * Will return value of the field, if such field existed;
@@ -852,25 +884,6 @@
         return _children.hashCode();
     }
 
-    @Override
-    public String toString()
-    {
-        StringBuilder sb = new StringBuilder(32 + (size() << 4));
-        sb.append("{");
-        int count = 0;
-        for (Map.Entry<String, JsonNode> en : _children.entrySet()) {
-            if (count > 0) {
-                sb.append(",");
-            }
-            ++count;
-            TextNode.appendQuoted(sb, en.getKey());
-            sb.append(':');
-            sb.append(en.getValue().toString());
-        }
-        sb.append("}");
-        return sb.toString();
-    }
-
     /*
     /**********************************************************
     /* Internal methods (overridable)
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/POJONode.java b/src/main/java/com/fasterxml/jackson/databind/node/POJONode.java
index 06c315c..6701de6 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/POJONode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/POJONode.java
@@ -5,7 +5,6 @@
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.JsonSerializable;
 import com.fasterxml.jackson.databind.SerializerProvider;
-import com.fasterxml.jackson.databind.util.RawValue;
 
 /**
  * Value node that contains a wrapped POJO, to be serialized as
@@ -15,6 +14,8 @@
 public class POJONode
     extends ValueNode
 {
+    private static final long serialVersionUID = 2L;
+
     protected final Object _value;
 
     public POJONode(Object v) { _value = v; }
@@ -156,17 +157,4 @@
     
     @Override
     public int hashCode() { return _value.hashCode(); }
-
-    @Override
-    public String toString()
-    {
-        // [databind#743]: Let's try indicating content type, for debugging purposes
-        if (_value instanceof byte[]) {
-            return String.format("(binary value of %d bytes)", ((byte[]) _value).length);
-        }
-        if (_value instanceof RawValue) {
-            return String.format("(raw value '%s')", ((RawValue) _value).toString());
-        }
-        return String.valueOf(_value);
-    }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/ShortNode.java b/src/main/java/com/fasterxml/jackson/databind/node/ShortNode.java
index dc01774..410696d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/ShortNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/ShortNode.java
@@ -12,6 +12,7 @@
 /**
  * Numeric node that contains simple 16-bit integer values.
  */
+@SuppressWarnings("serial")
 public class ShortNode
     extends NumericNode
 {
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/TextNode.java b/src/main/java/com/fasterxml/jackson/databind/node/TextNode.java
index 26a7f91..1707cb7 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/TextNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/TextNode.java
@@ -16,6 +16,8 @@
 public class TextNode
     extends ValueNode
 {
+    private static final long serialVersionUID = 2L;
+
     final static TextNode EMPTY_STRING_NODE = new TextNode("");
 
     protected final String _value;
@@ -63,7 +65,7 @@
     public byte[] getBinaryValue(Base64Variant b64variant) throws IOException
     {
         final String str = _value.trim();
-        ByteArrayBuilder builder = new ByteArrayBuilder(4 + ((str.length() * 3) << 2));
+        ByteArrayBuilder builder = new ByteArrayBuilder(4 + ((str.length() * 3) >> 2));
         try {
             b64variant.decode(str, builder);
         } catch (IllegalArgumentException e) {
@@ -164,19 +166,7 @@
     @Override
     public int hashCode() { return _value.hashCode(); }
 
-    /**
-     * Different from other values, Strings need quoting
-     */
-    @Override
-    public String toString()
-    {
-        int len = _value.length();
-        len = len + 2 + (len >> 4);
-        StringBuilder sb = new StringBuilder(len);
-        appendQuoted(sb, _value);
-        return sb.toString();
-    }
-
+    @Deprecated // since 2.10
     protected static void appendQuoted(StringBuilder sb, String content)
     {
         sb.append('"');
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/TreeTraversingParser.java b/src/main/java/com/fasterxml/jackson/databind/node/TreeTraversingParser.java
index 40bf3d3..908ccbe 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/TreeTraversingParser.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/TreeTraversingParser.java
@@ -273,47 +273,55 @@
     /**********************************************************
      */
 
-    //public byte getByteValue() throws IOException, JsonParseException
+    //public byte getByteValue() throws IOException
 
     @Override
-    public NumberType getNumberType() throws IOException, JsonParseException {
+    public NumberType getNumberType() throws IOException {
         JsonNode n = currentNumericNode();
         return (n == null) ? null : n.numberType();
     }
 
     @Override
-    public BigInteger getBigIntegerValue() throws IOException, JsonParseException
+    public BigInteger getBigIntegerValue() throws IOException
     {
         return currentNumericNode().bigIntegerValue();
     }
 
     @Override
-    public BigDecimal getDecimalValue() throws IOException, JsonParseException {
+    public BigDecimal getDecimalValue() throws IOException {
         return currentNumericNode().decimalValue();
     }
 
     @Override
-    public double getDoubleValue() throws IOException, JsonParseException {
+    public double getDoubleValue() throws IOException {
         return currentNumericNode().doubleValue();
     }
 
     @Override
-    public float getFloatValue() throws IOException, JsonParseException {
+    public float getFloatValue() throws IOException {
         return (float) currentNumericNode().doubleValue();
     }
 
     @Override
-    public long getLongValue() throws IOException, JsonParseException {
-        return currentNumericNode().longValue();
+    public int getIntValue() throws IOException {
+        final NumericNode node = (NumericNode) currentNumericNode();
+        if (!node.canConvertToInt()) {
+            reportOverflowInt();
+        }
+        return node.intValue();
     }
 
     @Override
-    public int getIntValue() throws IOException, JsonParseException {
-        return currentNumericNode().intValue();
+    public long getLongValue() throws IOException {
+        final NumericNode node = (NumericNode) currentNumericNode();
+        if (!node.canConvertToLong()) {
+            reportOverflowLong();
+        }
+        return node.longValue();
     }
 
     @Override
-    public Number getNumberValue() throws IOException, JsonParseException {
+    public Number getNumberValue() throws IOException {
         return currentNumericNode().numberValue();
     }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/node/ValueNode.java b/src/main/java/com/fasterxml/jackson/databind/node/ValueNode.java
index 363d59e..d62023a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/node/ValueNode.java
+++ b/src/main/java/com/fasterxml/jackson/databind/node/ValueNode.java
@@ -17,6 +17,8 @@
 public abstract class ValueNode
     extends BaseJsonNode
 {
+    private static final long serialVersionUID = 1L;
+
     protected ValueNode() { }
 
     @Override
@@ -49,17 +51,17 @@
 
     /*
     /**********************************************************************
-    /* Base impls for standard methods
+    /* Basic property access
     /**********************************************************************
      */
 
     @Override
-    public String toString() { return asText(); }
-
+    public boolean isEmpty() { return true; }
+    
     /*
-     **********************************************************************
-     * Navigation methods
-     **********************************************************************
+    /**********************************************************************
+    /* Navigation methods
+    /**********************************************************************
      */
 
     @Override
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BasicSerializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/ser/BasicSerializerFactory.java
index a3d422f..5863a15 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BasicSerializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BasicSerializerFactory.java
@@ -421,7 +421,7 @@
             }
             return NumberSerializer.instance;
         }
-        if (Enum.class.isAssignableFrom(raw)) {
+        if (ClassUtil.isEnumType(raw) && raw != Enum.class) {
             return buildEnumSerializer(prov.getConfig(), type, beanDesc);
         }
         return null;
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java
index 9813e4b..94a4438 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializer.java
@@ -75,14 +75,25 @@
      */
 
     /**
-     * Method for constructing dummy bean serializer; one that
-     * never outputs any properties
+     * @deprecated Since 2.10
      */
+    @Deprecated
     public static BeanSerializer createDummy(JavaType forType)
     {
         return new BeanSerializer(forType, null, NO_PROPS, null);
     }
 
+    /**
+     * Method for constructing dummy bean serializer; one that
+     * never outputs any properties
+     *
+     * @since 2.10
+     */
+    public static BeanSerializer createDummy(JavaType forType, BeanSerializerBuilder builder)
+    {
+        return new BeanSerializer(forType, builder, NO_PROPS, null);
+    }
+
     @Override
     public JsonSerializer<Object> unwrappingSerializer(NameTransformer unwrapper) {
         return new UnwrappingBeanSerializer(this, unwrapper);
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerBuilder.java b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerBuilder.java
index c89d380..e191140 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerBuilder.java
@@ -223,7 +223,8 @@
      * type information)
      */
     public BeanSerializer createDummy() {
-        return BeanSerializer.createDummy(_beanDesc.getType());
+        // 20-Sep-2019, tatu: Can not skimp on passing builder  (see [databind#2077])
+        return BeanSerializer.createDummy(_beanDesc.getType(), this);
     }
 }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java
index 0040256..79c9a96 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java
@@ -228,16 +228,12 @@
                     // And this is where this class comes in: if type is not a
                     // known "primary JDK type", perhaps it's a bean? We can still
                     // get a null, if we can't find a single suitable bean property.
-                    ser = findBeanSerializer(prov, type, beanDesc);
-                    // Finally: maybe we can still deal with it as an implementation of some basic JDK interface?
+                    ser = findBeanOrAddOnSerializer(prov, type, beanDesc, staticTyping);
+                    // 18-Sep-2014, tatu: Actually, as per [jackson-databind#539], need to get
+                    //   'unknown' serializer assigned earlier, here, so that it gets properly
+                    //   post-processed
                     if (ser == null) {
-                        ser = findSerializerByAddonType(config, type, beanDesc, staticTyping);
-                        // 18-Sep-2014, tatu: Actually, as per [jackson-databind#539], need to get
-                        //   'unknown' serializer assigned earlier, here, so that it gets properly
-                        //   post-processed
-                        if (ser == null) {
-                            ser = prov.getUnknownTypeSerializer(beanDesc.getBeanClass());
-                        }
+                        ser = prov.getUnknownTypeSerializer(beanDesc.getBeanClass());
                     }
                 }
             }
@@ -260,23 +256,34 @@
     /**********************************************************
      */
 
-    /**
-     * Method that will try to construct a {@link BeanSerializer} for
-     * given class. Returns null if no properties are found.
-     */
+    @Deprecated // since 2.10
     public JsonSerializer<Object> findBeanSerializer(SerializerProvider prov, JavaType type,
             BeanDescription beanDesc)
         throws JsonMappingException
     {
+        return findBeanOrAddOnSerializer(prov, type, beanDesc, prov.isEnabled(MapperFeature.USE_STATIC_TYPING));
+    }
+
+    /**
+     * Method that will try to construct a {@link BeanSerializer} for
+     * given class if at least one property is found, OR, if not,
+     * one of add-on types.
+     *<p>
+     * NOTE: behavior changed a bit
+     */
+    public JsonSerializer<Object> findBeanOrAddOnSerializer(SerializerProvider prov, JavaType type,
+            BeanDescription beanDesc, boolean staticTyping)
+        throws JsonMappingException
+    {
         // First things first: we know some types are not beans...
         if (!isPotentialBeanType(type.getRawClass())) {
             // 03-Aug-2012, tatu: Except we do need to allow serializers for Enums,
-            //   as per [databind#24]
-            if (!type.isEnumType()) {
+            //   as per [databind#24], [databind#2576]
+            if (!ClassUtil.isEnumType(type.getRawClass())) {
                 return null;
             }
         }
-        return constructBeanSerializer(prov, beanDesc);
+        return constructBeanOrAddOnSerializer(prov, type, beanDesc, staticTyping);
     }
 
     /**
@@ -344,16 +351,25 @@
     /**********************************************************
      */
 
-    /**
-     * Method called to construct serializer for serializing specified bean type.
-     * 
-     * @since 2.1
-     */
-    @SuppressWarnings("unchecked")
+    @Deprecated // since 2.10
     protected JsonSerializer<Object> constructBeanSerializer(SerializerProvider prov,
             BeanDescription beanDesc)
         throws JsonMappingException
     {
+        return constructBeanOrAddOnSerializer(prov, beanDesc.getType(), beanDesc, prov.isEnabled(MapperFeature.USE_STATIC_TYPING));
+    }
+
+    /**
+     * Method called to construct serializer for serializing specified bean type if
+     * (but only if, as of 2.10), at least one property is found.
+     * 
+     * @since 2.10
+     */
+    @SuppressWarnings("unchecked")
+    protected JsonSerializer<Object> constructBeanOrAddOnSerializer(SerializerProvider prov,
+            JavaType type, BeanDescription beanDesc, boolean staticTyping)
+        throws JsonMappingException
+    {
         // 13-Oct-2010, tatu: quick sanity check: never try to create bean serializer for plain Object
         // 05-Jul-2012, tatu: ... but we should be able to just return "unknown type" serializer, right?
         if (beanDesc.getBeanClass() == Object.class) {
@@ -402,10 +418,9 @@
 
         AnnotatedMember anyGetter = beanDesc.findAnyGetter();
         if (anyGetter != null) {
-            JavaType type = anyGetter.getType();
+            JavaType anyType = anyGetter.getType();
             // copied from BasicSerializerFactory.buildMapSerializer():
-            boolean staticTyping = config.isEnabled(MapperFeature.USE_STATIC_TYPING);
-            JavaType valueType = type.getContentType();
+            JavaType valueType = anyType.getContentType();
             TypeSerializer typeSer = createTypeSerializer(config, valueType);
             // last 2 nulls; don't know key, value serializers (yet)
             // 23-Feb-2015, tatu: As per [databind#705], need to support custom serializers
@@ -413,7 +428,8 @@
             if (anySer == null) {
                 // TODO: support '@JsonIgnoreProperties' with any setter?
                 anySer = MapSerializer.construct(/* ignored props*/ (Set<String>) null,
-                        type, staticTyping, typeSer, null, null, /*filterId*/ null);
+                        anyType, config.isEnabled(MapperFeature.USE_STATIC_TYPING),
+                        typeSer, null, null, /*filterId*/ null);
             }
             // TODO: can we find full PropertyName?
             PropertyName name = PropertyName.construct(anyGetter.getName());
@@ -435,15 +451,20 @@
         try {
             ser = (JsonSerializer<Object>) builder.build();
         } catch (RuntimeException e) {
-            prov.reportBadTypeDefinition(beanDesc, "Failed to construct BeanSerializer for %s: (%s) %s",
+            return prov.reportBadTypeDefinition(beanDesc, "Failed to construct BeanSerializer for %s: (%s) %s",
                     beanDesc.getType(), e.getClass().getName(), e.getMessage());
         }
         if (ser == null) {
-            // If we get this far, there were no properties found, so no regular BeanSerializer
-            // would be constructed. But, couple of exceptions.
-            // First: if there are known annotations, just create 'empty bean' serializer
-            if (beanDesc.hasKnownClassAnnotations()) {
-                return builder.createDummy();
+            // 06-Aug-2019, tatu: As per [databind#2390], we need to check for add-ons here,
+            //    before considering fallbacks
+            ser = (JsonSerializer<Object>) findSerializerByAddonType(config, type, beanDesc, staticTyping);
+            if (ser == null) {
+                // If we get this far, there were no properties found, so no regular BeanSerializer
+                // would be constructed. But, couple of exceptions.
+                // First: if there are known annotations, just create 'empty bean' serializer
+                if (beanDesc.hasKnownClassAnnotations()) {
+                    return builder.createDummy();
+                }
             }
         }
         return ser;
@@ -642,7 +663,9 @@
         for (int i = 0; i < propCount; ++i) {
             BeanPropertyWriter bpw = props.get(i);
             Class<?>[] views = bpw.getViews();
-            if (views == null) { // no view info? include or exclude by default?
+            if (views == null
+                    // [databind#2311]: sometimes we add empty array
+                    || views.length == 0) { // no view info? include or exclude by default?
                 if (includeByDefault) {
                     filtered[i] = bpw;
                 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java
index 64ced81..87d94b6 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/BeanAsArraySerializer.java
@@ -136,9 +136,9 @@
             _serializeWithObjectId(bean, gen, provider, typeSer);
             return;
         }
-        gen.setCurrentValue(bean);
         WritableTypeId typeIdDef = _typeIdDef(typeSer, bean, JsonToken.START_ARRAY);
         typeSer.writeTypePrefix(gen, typeIdDef);
+        gen.setCurrentValue(bean);
         serializeAsArray(bean, gen, provider);
         typeSer.writeTypeSuffix(gen, typeIdDef);
     }
@@ -161,9 +161,7 @@
          * any getter, filtering) have already been checked; so code here
          * is trivial.
          */
-        gen.writeStartArray();
-        // [databind#631]: Assign current value, to be accessible by custom serializers
-        gen.setCurrentValue(bean);
+        gen.writeStartArray(bean);
         serializeAsArray(bean, gen, provider);
         gen.writeEndArray();
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedListSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedListSerializer.java
index 44f5c87..f42e78e 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedListSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedListSerializer.java
@@ -75,7 +75,7 @@
                 return;
             }
         }
-        gen.writeStartArray(len);
+        gen.writeStartArray(value, len);
         serializeContents(value, gen, provider);
         gen.writeEndArray();
     }
@@ -182,7 +182,6 @@
                 }
             }
         } catch (Exception e) {
-            // [JACKSON-55] Need to add reference information
             wrapAndThrow(provider, e, value, i);
         }
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedStringListSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedStringListSerializer.java
index fbe88a6..ea817e7 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedStringListSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/IndexedStringListSerializer.java
@@ -73,7 +73,7 @@
                 return;
             }
         }
-        g.writeStartArray(len);
+        g.writeStartArray(value, len);
         serializeContents(value, g, provider, len);
         g.writeEndArray();
     }
@@ -85,6 +85,7 @@
     {
         WritableTypeId typeIdDef = typeSer.writeTypePrefix(g,
                 typeSer.typeId(value, JsonToken.START_ARRAY));
+        g.setCurrentValue(value);
         serializeContents(value, g, provider, value.size());
         typeSer.writeTypeSuffix(g, typeIdDef);
     }
@@ -92,7 +93,6 @@
     private final void serializeContents(List<String> value, JsonGenerator g,
             SerializerProvider provider, int len) throws IOException
     {
-        g.setCurrentValue(value);
         int i = 0;
         try {
             for (; i < len; ++i) {
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/IteratorSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/IteratorSerializer.java
index cf756db..77846fc 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/IteratorSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/IteratorSerializer.java
@@ -63,7 +63,7 @@
             }
         }
         */
-        gen.writeStartArray();
+        gen.writeStartArray(value);
         serializeContents(value, gen, provider);
         gen.writeEndArray();
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/PropertySerializerMap.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/PropertySerializerMap.java
index 14f1802..839fe3d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/PropertySerializerMap.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/PropertySerializerMap.java
@@ -349,11 +349,32 @@
         @Override
         public JsonSerializer<Object> serializerFor(Class<?> type)
         {
-            for (int i = 0, len = _entries.length; i < len; ++i) {
-                TypeAndSerializer entry = _entries[i];
-                if (entry.type == type) {
-                    return entry.serializer;
-                }
+            // Always have first 3 populated so
+            TypeAndSerializer entry;
+            entry = _entries[0];
+            if (entry.type == type) return entry.serializer;
+            entry = _entries[1];
+            if (entry.type == type) return entry.serializer;
+            entry = _entries[2];
+            if (entry.type == type) return entry.serializer;
+
+            switch (_entries.length) {
+            case 8:
+                entry = _entries[7];
+                if (entry.type == type) return entry.serializer;
+            case 7:
+                entry = _entries[6];
+                if (entry.type == type) return entry.serializer;
+            case 6:
+                entry = _entries[5];
+                if (entry.type == type) return entry.serializer;
+            case 5:
+                entry = _entries[4];
+                if (entry.type == type) return entry.serializer;
+            case 4:
+                entry = _entries[3];
+                if (entry.type == type) return entry.serializer;
+            default:
             }
             return null;
         }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringArraySerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringArraySerializer.java
index 1011bab..94c83cf 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringArraySerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringArraySerializer.java
@@ -167,7 +167,7 @@
                 return;
             }
         }
-        gen.writeStartArray(len);
+        gen.writeStartArray(value, len);
         serializeContents(value, gen, provider);
         gen.writeEndArray();
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringCollectionSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringCollectionSerializer.java
index b936eac..37ddd1c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringCollectionSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/StringCollectionSerializer.java
@@ -67,7 +67,6 @@
     public void serialize(Collection<String> value, JsonGenerator g,
             SerializerProvider provider) throws IOException
     {
-        g.setCurrentValue(value);
         final int len = value.size();
         if (len == 1) {
             if (((_unwrapSingle == null) &&
@@ -77,7 +76,7 @@
                 return;
             }
         }
-        g.writeStartArray(len);
+        g.writeStartArray(value, len);
         serializeContents(value, g, provider);
         g.writeEndArray();
     }
@@ -87,9 +86,9 @@
             SerializerProvider provider, TypeSerializer typeSer)
         throws IOException
     {
-        g.setCurrentValue(value);
         WritableTypeId typeIdDef = typeSer.writeTypePrefix(g,
                 typeSer.typeId(value, JsonToken.START_ARRAY));
+        g.setCurrentValue(value);
         serializeContents(value, g, provider);
         typeSer.writeTypeSuffix(g, typeIdDef);
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnknownSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnknownSerializer.java
index 70b53e0..738c55d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnknownSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/impl/UnknownSerializer.java
@@ -33,7 +33,7 @@
             failForEmpty(provider, value);
         }
         // But if it's fine, we'll just output empty JSON Object:
-        gen.writeStartObject();
+        gen.writeStartObject(value, 0);
         gen.writeEndObject();
     }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/ArraySerializerBase.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/ArraySerializerBase.java
index 69af378..47ff359 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/ArraySerializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/ArraySerializerBase.java
@@ -118,9 +118,7 @@
                 return;
             }
         }
-        gen.setCurrentValue(value);
-        gen.writeStartArray();
-        // [databind#631]: Assign current value, to be accessible by custom serializers
+        gen.writeStartArray(value);
         serializeContents(value, gen, provider);
         gen.writeEndArray();
     }
@@ -130,10 +128,10 @@
             TypeSerializer typeSer)
         throws IOException
     {
-        // [databind#631]: Assign current value, to be accessible by custom serializers
-        g.setCurrentValue(value);
         WritableTypeId typeIdDef = typeSer.writeTypePrefix(g,
                 typeSer.typeId(value, JsonToken.START_ARRAY));
+        // [databind#631]: Assign current value, to be accessible by custom serializers
+        g.setCurrentValue(value);
         serializeContents(value, g, provider);
         typeSer.writeTypeSuffix(g, typeIdDef);
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/AsArraySerializerBase.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/AsArraySerializerBase.java
index 87647ba..712cc31 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/AsArraySerializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/AsArraySerializerBase.java
@@ -244,9 +244,7 @@
             serializeContents(value, gen, provider);
             return;
         }
-        gen.writeStartArray();
-        // [databind#631]: Assign current value, to be accessible by custom serializers
-        gen.setCurrentValue(value);
+        gen.writeStartArray(value);
         serializeContents(value, gen, provider);
         gen.writeEndArray();
     }
@@ -255,10 +253,10 @@
     public void serializeWithType(T value, JsonGenerator g, SerializerProvider provider,
             TypeSerializer typeSer) throws IOException
     {
-        // [databind#631]: Assign current value, to be accessible by custom serializers
-        g.setCurrentValue(value);
         WritableTypeId typeIdDef = typeSer.writeTypePrefix(g,
                 typeSer.typeId(value, JsonToken.START_ARRAY));
+        // [databind#631]: Assign current value, to be accessible by custom serializers
+        g.setCurrentValue(value);
         serializeContents(value, g, provider);
         typeSer.writeTypeSuffix(g, typeIdDef);
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java
index a95d812..b7eba96 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java
@@ -23,6 +23,7 @@
 import com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator;
 import com.fasterxml.jackson.databind.ser.impl.WritableObjectId;
 import com.fasterxml.jackson.databind.util.ArrayBuilders;
+import com.fasterxml.jackson.databind.util.ClassUtil;
 import com.fasterxml.jackson.databind.util.Converter;
 import com.fasterxml.jackson.databind.util.NameTransformer;
 
@@ -114,6 +115,8 @@
         _props = properties;
         _filteredProps = filteredProperties;
         if (builder == null) { // mostly for testing
+            // 20-Sep-2019, tatu: Actually not just that but also "dummy" serializer for
+            //     case of no bean properties, too
             _typeId = null;
             _anyGetterWriter = null;
             _propertyFilterId = null;
@@ -414,7 +417,7 @@
         final AnnotatedMember accessor = (property == null || intr == null)
                 ? null : property.getMember();
         final SerializationConfig config = provider.getConfig();
-        
+
         // Let's start with one big transmutation: Enums that are annotated
         // to serialize as Objects may want to revert
         JsonFormat.Value format = findFormatOverrides(provider, property, handledType());
@@ -423,7 +426,7 @@
             shape = format.getShape();
             // or, alternatively, asked to revert "back to" other representations...
             if ((shape != JsonFormat.Shape.ANY) && (shape != _serializationShape)) {
-                if (_handledType.isEnum()) {
+                if (ClassUtil.isEnumType(_handledType)) {
                     switch (shape) {
                     case STRING:
                     case NUMBER:
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/ByteBufferSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/ByteBufferSerializer.java
index 302b4ed..2bcda95 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/ByteBufferSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/ByteBufferSerializer.java
@@ -20,7 +20,8 @@
     {
         // first, simple case when wrapping an array...
         if (bbuf.hasArray()) {
-            gen.writeBinary(bbuf.array(), bbuf.arrayOffset(), bbuf.limit());
+            final int pos = bbuf.position();
+            gen.writeBinary(bbuf.array(), bbuf.arrayOffset() + pos, bbuf.limit() - pos);
             return;
         }
         // the other case is more complicated however. Best to handle with InputStream wrapper.
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/CollectionSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/CollectionSerializer.java
index 6dec6a7..321e6b7 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/CollectionSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/CollectionSerializer.java
@@ -103,7 +103,7 @@
                 return;
             }
         }
-        g.writeStartArray(len);
+        g.writeStartArray(value, len);
         serializeContents(value, g, provider);
         g.writeEndArray();
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSerializer.java
index def97ee..a62ae37 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSerializer.java
@@ -119,7 +119,6 @@
     public final void serialize(Enum<?> en, JsonGenerator gen, SerializerProvider serializers)
         throws IOException
     {
-        // [JACKSON-684]: serialize as index?
         if (_serializeAsIndex(serializers)) {
             gen.writeNumber(en.ordinal());
             return;
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSetSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSetSerializer.java
index 6211d71..3706edc 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSetSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/EnumSetSerializer.java
@@ -60,7 +60,7 @@
                 return;
             }
         }
-        gen.writeStartArray(len);
+        gen.writeStartArray(value, len);
         serializeContents(value, gen, provider);
         gen.writeEndArray();
     }
@@ -77,9 +77,8 @@
          */
         for (Enum<?> en : value) {
             if (enumSer == null) {
-                /* 12-Jan-2010, tatu: Since enums cannot be polymorphic, let's
-                 *   not bother with typed serializer variant here
-                 */
+                // 12-Jan-2010, tatu: Since enums cannot be polymorphic, let's
+                //   not bother with typed serializer variant here
                 enumSer = provider.findValueSerializer(en.getDeclaringClass(), _property);
             }
             enumSer.serialize(en, gen, provider);
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/IterableSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/IterableSerializer.java
index 5cc5068..8ced8ca 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/IterableSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/IterableSerializer.java
@@ -70,7 +70,7 @@
                 return;
             }
         }
-        gen.writeStartArray();
+        gen.writeStartArray(value);
         serializeContents(value, gen, provider);
         gen.writeEndArray();
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/JsonValueSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/JsonValueSerializer.java
index 6112a7d..77fb8a1 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/JsonValueSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/JsonValueSerializer.java
@@ -249,7 +249,7 @@
          */
         final JavaType type = _accessor.getType();
         Class<?> declaring = _accessor.getDeclaringClass();
-        if ((declaring != null) && declaring.isEnum()) {
+        if ((declaring != null) && ClassUtil.isEnumType(declaring)) {
             if (_acceptJsonFormatVisitorForEnum(visitor, typeHint, declaring)) {
                 return;
             }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java
index b3a2e62..7fd7043 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java
@@ -466,53 +466,53 @@
                     mser = mser.withFilterId(filterId);
                 }
             }
-            JsonInclude.Value inclV = property.findPropertyInclusion(provider.getConfig(), null);
-            if (inclV != null) {
-                JsonInclude.Include incl = inclV.getContentInclusion();
+        }
+        JsonInclude.Value inclV = findIncludeOverrides(provider, property, Map.class);
+        if (inclV != null) {
+            JsonInclude.Include incl = inclV.getContentInclusion();
 
-                if (incl != JsonInclude.Include.USE_DEFAULTS) {
-                    Object valueToSuppress;
-                    boolean suppressNulls;
-                    switch (incl) {
-                    case NON_DEFAULT:
-                        valueToSuppress = BeanUtil.getDefaultValue(_valueType);
-                        suppressNulls = true;
-                        if (valueToSuppress != null) {
-                            if (valueToSuppress.getClass().isArray()) {
-                                valueToSuppress = ArrayBuilders.getArrayComparator(valueToSuppress);
-                            }
+            if (incl != JsonInclude.Include.USE_DEFAULTS) {
+                Object valueToSuppress;
+                boolean suppressNulls;
+                switch (incl) {
+                case NON_DEFAULT:
+                    valueToSuppress = BeanUtil.getDefaultValue(_valueType);
+                    suppressNulls = true;
+                    if (valueToSuppress != null) {
+                        if (valueToSuppress.getClass().isArray()) {
+                            valueToSuppress = ArrayBuilders.getArrayComparator(valueToSuppress);
                         }
-                        break;
-                    case NON_ABSENT:
-                        suppressNulls = true;
-                        valueToSuppress = _valueType.isReferenceType() ? MARKER_FOR_EMPTY : null;
-                        break;
-                    case NON_EMPTY:
-                        suppressNulls = true;
-                        valueToSuppress = MARKER_FOR_EMPTY;
-                        break;
-                    case CUSTOM:
-                        valueToSuppress = provider.includeFilterInstance(null, inclV.getContentFilter());
-                        if (valueToSuppress == null) { // is this legal?
-                            suppressNulls = true;
-                        } else {
-                            suppressNulls = provider.includeFilterSuppressNulls(valueToSuppress);
-                        }
-                        break;
-                    case NON_NULL:
-                        valueToSuppress = null;
-                        suppressNulls = true;
-                        break;
-                    case ALWAYS: // default
-                    default:
-                        valueToSuppress = null;
-                        // 30-Sep-2016, tatu: Should not need to check global flags here,
-                        //   if inclusion forced to be ALWAYS
-                        suppressNulls = false;
-                        break;
                     }
-                    mser = mser.withContentInclusion(valueToSuppress, suppressNulls);
+                    break;
+                case NON_ABSENT:
+                    suppressNulls = true;
+                    valueToSuppress = _valueType.isReferenceType() ? MARKER_FOR_EMPTY : null;
+                    break;
+                case NON_EMPTY:
+                    suppressNulls = true;
+                    valueToSuppress = MARKER_FOR_EMPTY;
+                    break;
+                case CUSTOM:
+                    valueToSuppress = provider.includeFilterInstance(null, inclV.getContentFilter());
+                    if (valueToSuppress == null) { // is this legal?
+                        suppressNulls = true;
+                    } else {
+                        suppressNulls = provider.includeFilterSuppressNulls(valueToSuppress);
+                    }
+                    break;
+                case NON_NULL:
+                    valueToSuppress = null;
+                    suppressNulls = true;
+                    break;
+                case ALWAYS: // default
+                default:
+                    valueToSuppress = null;
+                    // 30-Sep-2016, tatu: Should not need to check global flags here,
+                    //   if inclusion forced to be ALWAYS
+                    suppressNulls = false;
+                    break;
                 }
+                mser = mser.withContentInclusion(valueToSuppress, suppressNulls);
             }
         }
         return mser;
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/NumberSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/NumberSerializer.java
index 1180798..1bf9010 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/NumberSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/NumberSerializer.java
@@ -6,8 +6,10 @@
 import java.math.BigInteger;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonParser;
+
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
@@ -29,6 +31,11 @@
      */
     public final static NumberSerializer instance = new NumberSerializer(Number.class);
 
+    /**
+     * Copied from `jackson-core` class `GeneratorBase`
+     */
+    protected final static int MAX_BIG_DECIMAL_SCALE = 9999;
+    
     protected final boolean _isInt;
 
     /**
@@ -48,6 +55,10 @@
         if (format != null) {
             switch (format.getShape()) {
             case STRING:
+                // [databind#2264]: Need special handling for `BigDecimal`
+                if (((Class<?>) handledType()) == BigDecimal.class) {
+                    return bigDecimalAsStringSerializer();
+                }
                 return ToStringSerializer.instance;
             default:
             }
@@ -91,8 +102,7 @@
         if (_isInt) {
             visitIntFormat(visitor, typeHint, JsonParser.NumberType.BIG_INTEGER);
         } else {
-            Class<?> h = handledType();
-            if (h == BigDecimal.class) {
+            if (((Class<?>) handledType()) == BigDecimal.class) {
                 visitFloatFormat(visitor, typeHint, JsonParser.NumberType.BIG_DECIMAL);
             } else {
                 // otherwise bit unclear what to call... but let's try:
@@ -100,4 +110,63 @@
             }
         }
     }
-}
\ No newline at end of file
+
+    /**
+     * @since 2.10
+     */
+    public static JsonSerializer<?> bigDecimalAsStringSerializer() {
+        return BigDecimalAsStringSerializer.BD_INSTANCE;
+    }
+    
+    final static class BigDecimalAsStringSerializer
+        extends ToStringSerializerBase
+    {
+        final static BigDecimalAsStringSerializer BD_INSTANCE = new BigDecimalAsStringSerializer();
+        
+        public BigDecimalAsStringSerializer() {
+            super(BigDecimal.class);
+        }
+
+        @Override
+        public boolean isEmpty(SerializerProvider prov, Object value) {
+            // As per [databind#2513], should not delegate; also, never empty (numbers do
+            // have "default value" to filter by, just not "empty"
+            return false;
+        }
+
+        @Override
+        public void serialize(Object value, JsonGenerator gen, SerializerProvider provider)
+            throws IOException
+        {
+            final String text;
+            if (gen.isEnabled(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN)) {
+                final BigDecimal bd = (BigDecimal) value;
+                // 24-Aug-2016, tatu: [core#315] prevent possible DoS vector, so we need this
+                if (!_verifyBigDecimalRange(gen, bd)) {
+                    // ... but wouldn't it be nice to trigger error via generator? Alas,
+                    // no method to do that. So we'll do...
+                    final String errorMsg = String.format(
+                            "Attempt to write plain `java.math.BigDecimal` (see JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN) with illegal scale (%d): needs to be between [-%d, %d]",
+                            bd.scale(), MAX_BIG_DECIMAL_SCALE, MAX_BIG_DECIMAL_SCALE);
+                    provider.reportMappingProblem(errorMsg);
+                }
+                text = bd.toPlainString();
+            } else {
+                text = value.toString();
+            }
+            gen.writeString(text);
+        }
+
+        @Override
+        public String valueToString(Object value) {
+            // should never be called
+            throw new IllegalStateException();
+        }
+
+        // 24-Aug-2016, tatu: [core#315] prevent possible DoS vector, so we need this
+        protected boolean _verifyBigDecimalRange(JsonGenerator gen, BigDecimal value) throws IOException {
+            int scale = value.scale();
+            return ((scale >= -MAX_BIG_DECIMAL_SCALE) && (scale <= MAX_BIG_DECIMAL_SCALE));
+        }
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/NumberSerializers.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/NumberSerializers.java
index e27722c..8cac29d 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/NumberSerializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/NumberSerializers.java
@@ -2,12 +2,13 @@
 
 import java.io.IOException;
 import java.lang.reflect.Type;
+import java.math.BigDecimal;
 import java.util.Map;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 
 import com.fasterxml.jackson.core.*;
-
+import com.fasterxml.jackson.core.type.WritableTypeId;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
@@ -16,7 +17,7 @@
 
 /**
  * Container class for serializers used for handling standard JDK-provided
- * types.
+ * primitve number types and their wrapper counterparts (like {@link java.lang.Integer}).
  */
 @SuppressWarnings("serial")
 public class NumberSerializers {
@@ -46,8 +47,19 @@
     /**********************************************************
      */
 
-    protected abstract static class Base<T> extends StdScalarSerializer<T>
-            implements ContextualSerializer {
+    /**
+     * Shared base class for actual primitive/wrapper number serializers.
+     * Note that this class is not meant as general-purpose base class nor
+     * is it part of public API: you may extend it with the caveat that not
+     * being part of public API its implementation and interfaces may change
+     * in minor releases; however deprecation markers will be used to allow
+     * code evolution.
+     *<p>
+     * NOTE: {@code public} since 2.10: previously had {@code protected} access.
+     */
+    public abstract static class Base<T> extends StdScalarSerializer<T>
+            implements ContextualSerializer
+    {
         protected final JsonParser.NumberType _numberType;
         protected final String _schemaType;
         protected final boolean _isInt;
@@ -86,6 +98,9 @@
             if (format != null) {
                 switch (format.getShape()) {
                 case STRING:
+                    if (((Class<?>) handledType()) == BigDecimal.class) {
+                        return NumberSerializer.bigDecimalAsStringSerializer();
+                    }
                     return ToStringSerializer.instance;
                 default:
                 }
@@ -101,7 +116,7 @@
      */
 
     @JacksonStdImpl
-    public final static class ShortSerializer extends Base<Object> {
+    public static class ShortSerializer extends Base<Object> {
         final static ShortSerializer instance = new ShortSerializer();
 
         public ShortSerializer() {
@@ -119,14 +134,14 @@
      * This is the special serializer for regular {@link java.lang.Integer}s
      * (and primitive ints)
      * <p>
-     * Since this is one of "native" types, no type information is ever included
-     * on serialization (unlike for most scalar types)
+     * Since this is one of "natural" types, no type information is ever included
+     * on serialization (unlike for most scalar types, except for {@code double}).
      * <p>
      * NOTE: as of 2.6, generic signature changed to Object, to avoid generation
      * of bridge methods.
      */
     @JacksonStdImpl
-    public final static class IntegerSerializer extends Base<Object> {
+    public static class IntegerSerializer extends Base<Object> {
         public IntegerSerializer(Class<?> type) {
             super(type, JsonParser.NumberType.INT, "integer");
         }
@@ -153,7 +168,7 @@
      * calling {@link java.lang.Number#intValue}.
      */
     @JacksonStdImpl
-    public final static class IntLikeSerializer extends Base<Object> {
+    public static class IntLikeSerializer extends Base<Object> {
         final static IntLikeSerializer instance = new IntLikeSerializer();
 
         public IntLikeSerializer() {
@@ -168,7 +183,7 @@
     }
 
     @JacksonStdImpl
-    public final static class LongSerializer extends Base<Object> {
+    public static class LongSerializer extends Base<Object> {
         public LongSerializer(Class<?> cls) {
             super(cls, JsonParser.NumberType.LONG, "number");
         }
@@ -181,7 +196,7 @@
     }
 
     @JacksonStdImpl
-    public final static class FloatSerializer extends Base<Object> {
+    public static class FloatSerializer extends Base<Object> {
         final static FloatSerializer instance = new FloatSerializer();
 
         public FloatSerializer() {
@@ -200,10 +215,10 @@
      * primitive doubles)
      * <p>
      * Since this is one of "native" types, no type information is ever included
-     * on serialization (unlike for most scalar types as of 1.5)
+     * on serialization (unlike for most scalar types other than {@code long}).
      */
     @JacksonStdImpl
-    public final static class DoubleSerializer extends Base<Object> {
+    public static class DoubleSerializer extends Base<Object> {
         public DoubleSerializer(Class<?> cls) {
             super(cls, JsonParser.NumberType.DOUBLE, "number");
         }
@@ -216,11 +231,26 @@
 
         // IMPORTANT: copied from `NonTypedScalarSerializerBase`
         @Override
-        public void serializeWithType(Object value, JsonGenerator gen,
+        public void serializeWithType(Object value, JsonGenerator g,
                 SerializerProvider provider, TypeSerializer typeSer)
                 throws IOException {
-            // no type info, just regular serialization
-            serialize(value, gen, provider);
+            // 08-Feb-2018, tatu: Except that as per [databind#2236], NaN values need
+            //    special handling
+            Double d = (Double) value;
+            if (notFinite(d)) {
+                WritableTypeId typeIdDef = typeSer.writeTypePrefix(g,
+                        // whether to indicate it's number or string is arbitrary; important it is scalar
+                        typeSer.typeId(value, JsonToken.VALUE_NUMBER_FLOAT));
+                g.writeNumber(d);
+                typeSer.writeTypeSuffix(g, typeIdDef);
+            } else {
+                g.writeNumber(d);
+            }
+        }
+
+        public static boolean notFinite(double value) {
+            // `jackson-core` has helper method in 3 but not yet
+            return Double.isNaN(value) || Double.isInfinite(value);
         }
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/ObjectArraySerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/ObjectArraySerializer.java
index a113ae2..4475fce 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/ObjectArraySerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/ObjectArraySerializer.java
@@ -209,7 +209,7 @@
                 return;
             }
         }
-        gen.writeStartArray(len);
+        gen.writeStartArray(value, len);
         serializeContents(value, gen, provider);
         gen.writeEndArray();
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdArraySerializers.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdArraySerializers.java
index eb05fa4..c5c1a4c 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdArraySerializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdArraySerializers.java
@@ -141,8 +141,7 @@
                 serializeContents(value, g, provider);
                 return;
             }
-            g.writeStartArray(len);
-            g.setCurrentValue(value);
+            g.writeStartArray(value, len);
             serializeContents(value, g, provider);
             g.writeEndArray();
         }
@@ -219,8 +218,7 @@
                 serializeContents(value, g, provider);
                 return;
             }
-            g.writeStartArray(len);
-            g.setCurrentValue(value);
+            g.writeStartArray(value, len);
             serializeContents(value, g, provider);
             g.writeEndArray();
         }
@@ -274,8 +272,7 @@
         {
             // [JACKSON-289] allows serializing as 'sparse' char array too:
             if (provider.isEnabled(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS)) {
-                g.writeStartArray(value.length);
-                g.setCurrentValue(value);
+                g.writeStartArray(value, value.length);
                 _writeArrayContents(g, value);
                 g.writeEndArray();
             } else {
@@ -389,7 +386,6 @@
                 return;
             }
             // 11-May-2016, tatu: As per [core#277] we have efficient `writeArray(...)` available
-            g.setCurrentValue(value);
             g.writeArray(value, 0, value.length);
         }
 
@@ -462,7 +458,6 @@
                 return;
             }
             // 11-May-2016, tatu: As per [core#277] we have efficient `writeArray(...)` available
-            g.setCurrentValue(value);
             g.writeArray(value, 0, value.length);
         }
         
@@ -539,8 +534,7 @@
                 serializeContents(value, g, provider);
                 return;
             }
-            g.writeStartArray(len);
-            g.setCurrentValue(value);
+            g.writeStartArray(value, len);
             serializeContents(value, g, provider);
             g.writeEndArray();
         }
@@ -626,7 +620,6 @@
                 serializeContents(value, g, provider);
                 return;
             }
-            g.setCurrentValue(value);
             // 11-May-2016, tatu: As per [core#277] we have efficient `writeArray(...)` available
             g.writeArray(value, 0, value.length);
         }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializers.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializers.java
index 70fe67f..c3c93d5 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializers.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/StdKeySerializers.java
@@ -98,7 +98,9 @@
             if (rawKeyType == Enum.class) {
                 return new Dynamic();
             }
-            if (rawKeyType.isEnum()) {
+            // 29-Sep-2019, tatu: [databind#2457] can not use 'rawKeyType.isEnum()`, won't work
+            //    for subtypes.
+            if (ClassUtil.isEnumType(rawKeyType)) {
                 return EnumKeySerializer.construct(rawKeyType,
                         EnumValues.constructFromName(config, (Class<Enum<?>>) rawKeyType));
             }
@@ -166,7 +168,8 @@
                         key = value.toString();
                     } else {
                         Enum<?> e = (Enum<?>) value;
-                        if (provider.isEnabled(SerializationFeature.WRITE_ENUMS_USING_INDEX)) {
+                        // 14-Sep-2019, tatu: [databind#2129] Use this specific feature
+                        if (provider.isEnabled(SerializationFeature.WRITE_ENUM_KEYS_USING_INDEX)) {
                             key = String.valueOf(e.ordinal());
                         } else {
                             key = e.name();
@@ -293,7 +296,8 @@
                 return;
             }
             Enum<?> en = (Enum<?>) value;
-            if (serializers.isEnabled(SerializationFeature.WRITE_ENUMS_USING_INDEX)) {
+            // 14-Sep-2019, tatu: [databind#2129] Use this specific feature
+            if (serializers.isEnabled(SerializationFeature.WRITE_ENUM_KEYS_USING_INDEX)) {
                 g.writeFieldName(String.valueOf(en.ordinal()));
                 return;
             }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/ToStringSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/ToStringSerializer.java
index eb73422..c0fff28 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/ToStringSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/ToStringSerializer.java
@@ -1,27 +1,18 @@
 package com.fasterxml.jackson.databind.ser.std;
 
-import java.io.IOException;
-import java.lang.reflect.Type;
-
-import com.fasterxml.jackson.core.*;
-import com.fasterxml.jackson.core.type.WritableTypeId;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.SerializerProvider;
 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
-import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
-import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
 
 /**
  * Simple general purpose serializer, useful for any
  * type for which {@link Object#toString} returns the desired JSON
  * value.
+ *<p>
+ * Since 2.10 extends {@link ToStringSerializerBase}
  */
 @JacksonStdImpl
 @SuppressWarnings("serial")
 public class ToStringSerializer
-    extends StdSerializer<Object>
+    extends ToStringSerializerBase
 {
     /**
      * Singleton instance to use.
@@ -39,56 +30,16 @@
     public ToStringSerializer() { super(Object.class); }
 
     /**
-     * Sometimes it may actually make sense to retain actual handled type, so...
+     * Sometimes it may actually make sense to retain actual handled type.
      * 
      * @since 2.5
      */
     public ToStringSerializer(Class<?> handledType) {
-        super(handledType, false);
+        super(handledType);
     }
 
     @Override
-    public boolean isEmpty(SerializerProvider prov, Object value) {
-        return value.toString().isEmpty();
-    }
-
-    @Override
-    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider)
-        throws IOException
-    {
-        gen.writeString(value.toString());
-    }
-
-    /* 01-Mar-2011, tatu: We were serializing as "raw" String; but generally that
-     *   is not what we want, since lack of type information would imply real
-     *   String type.
-     */
-    /**
-     * Default implementation will write type prefix, call regular serialization
-     * method (since assumption is that value itself does not need JSON
-     * Array or Object start/end markers), and then write type suffix.
-     * This should work for most cases; some sub-classes may want to
-     * change this behavior.
-     */
-    @Override
-    public void serializeWithType(Object value, JsonGenerator g, SerializerProvider provider,
-            TypeSerializer typeSer)
-        throws IOException
-    {
-        WritableTypeId typeIdDef = typeSer.writeTypePrefix(g,
-                typeSer.typeId(value, JsonToken.VALUE_STRING));
-        serialize(value, g, provider);
-        typeSer.writeTypeSuffix(g, typeIdDef);
-    }
-
-    @Override
-    public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException {
-        return createSchemaNode("string", true);
-    }
-
-    @Override
-    public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException
-    {
-        visitStringFormat(visitor, typeHint);
+    public final String valueToString(Object value) {
+        return value.toString();
     }
 }
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/ToStringSerializerBase.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/ToStringSerializerBase.java
new file mode 100644
index 0000000..7e759f6
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/ToStringSerializerBase.java
@@ -0,0 +1,74 @@
+package com.fasterxml.jackson.databind.ser.std;
+
+import java.io.IOException;
+import java.lang.reflect.Type;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.core.type.WritableTypeId;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
+import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
+
+/**
+ * Intermediate base class that serves as base for standard {@link ToStringSerializer}
+ * as well as for custom subtypes that want to add processing for converting from
+ * value to output into its {@code String} representation (whereas standard version
+ * simply calls value object's {@code toString()} method).
+ *
+ * @since 2.10
+ */
+@SuppressWarnings("serial")
+public abstract class ToStringSerializerBase
+    extends StdSerializer<Object>
+{
+    public ToStringSerializerBase(Class<?> handledType) {
+        super(handledType, false);
+    }
+
+    @Override
+    public boolean isEmpty(SerializerProvider prov, Object value) {
+        return valueToString(value).isEmpty();
+    }
+
+    @Override
+    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider)
+        throws IOException
+    {
+        gen.writeString(valueToString(value));
+    }
+
+    /**
+     * Default implementation will write type prefix, call regular serialization
+     * method (since assumption is that value itself does not need JSON
+     * Array or Object start/end markers), and then write type suffix.
+     * This should work for most cases; some sub-classes may want to
+     * change this behavior.
+     */
+    @Override
+    public void serializeWithType(Object value, JsonGenerator g, SerializerProvider provider,
+            TypeSerializer typeSer)
+        throws IOException
+    {
+        WritableTypeId typeIdDef = typeSer.writeTypePrefix(g,
+                typeSer.typeId(value, JsonToken.VALUE_STRING));
+        serialize(value, g, provider);
+        typeSer.writeTypeSuffix(g, typeIdDef);
+    }
+
+    @Override
+    public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException {
+        return createSchemaNode("string", true);
+    }
+
+    @Override
+    public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException
+    {
+        visitStringFormat(visitor, typeHint);
+    }
+
+    public abstract String valueToString(Object value);
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/UUIDSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/UUIDSerializer.java
index 21768e7..7ab5918 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ser/std/UUIDSerializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/UUIDSerializer.java
@@ -5,6 +5,8 @@
 
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
+import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonValueFormat;
 import com.fasterxml.jackson.databind.util.TokenBuffer;
 
 /**
@@ -39,11 +41,10 @@
     {
         // First: perhaps we could serialize it as raw binary data?
         if (gen.canWriteBinaryNatively()) {
-            /* 07-Dec-2013, tatu: One nasty case; that of TokenBuffer. While it can
-             *   technically retain binary data, we do not want to do use binary
-             *   with it, as that results in UUIDs getting converted to Base64 for
-             *   most conversions.
-             */
+            // 07-Dec-2013, tatu: One nasty case; that of TokenBuffer. While it can
+            //   technically retain binary data, we do not want to do use binary
+            //   with it, as that results in UUIDs getting converted to Base64 for
+            //   most conversions.
             if (!(gen instanceof TokenBuffer)) {
                 gen.writeBinary(_asBytes(value));
                 return;
@@ -72,12 +73,20 @@
         gen.writeString(ch, 0, 36);
     }
 
+    // Need to add bit of extra info, format
+    @Override
+    public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
+        throws JsonMappingException
+    {
+        visitStringFormat(visitor, typeHint, JsonValueFormat.UUID);
+    }
+
     private static void _appendInt(int bits, char[] ch, int offset)
     {
         _appendShort(bits >> 16, ch, offset);
         _appendShort(bits, ch, offset+4);
     }
-    
+
     private static void _appendShort(int bits, char[] ch, int offset)
     {
         ch[offset] = HEX_CHARS[(bits >> 12) & 0xF];
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/ResolvedRecursiveType.java b/src/main/java/com/fasterxml/jackson/databind/type/ResolvedRecursiveType.java
index 4f4984e..7f73387 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/ResolvedRecursiveType.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/ResolvedRecursiveType.java
@@ -28,10 +28,10 @@
    
     @Override
     public JavaType getSuperClass() {
-    	if (_referencedType != null) {
-    		return _referencedType.getSuperClass();
-    	}
-    	return super.getSuperClass();
+        if (_referencedType != null) {
+            return _referencedType.getSuperClass();
+        }
+        return super.getSuperClass();
     }
 
     public JavaType getSelfReferencedType() { return _referencedType; }
@@ -47,8 +47,12 @@
 
     @Override
     public StringBuilder getGenericSignature(StringBuilder sb) {
+        // 30-Oct-2019, tatu: Alas, need to break recursion, otherwise we'll
+        //    end up in StackOverflowError... two choices; '?' for "not known",
+        //    or erased signature.
         if (_referencedType != null) {
-            return _referencedType.getGenericSignature(sb);
+//            return _referencedType.getGenericSignature(sb);
+            return _referencedType.getErasedSignature(sb);
         }
         return sb.append("?");
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/TypeBindings.java b/src/main/java/com/fasterxml/jackson/databind/type/TypeBindings.java
index 872608a..3dcea8a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/TypeBindings.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/TypeBindings.java
@@ -83,7 +83,7 @@
     public static TypeBindings create(Class<?> erasedType, List<JavaType> typeList)
     {
         JavaType[] types = (typeList == null || typeList.isEmpty()) ?
-                NO_TYPES : typeList.toArray(new JavaType[typeList.size()]);
+                NO_TYPES : typeList.toArray(NO_TYPES);
         return create(erasedType, types);
     }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java b/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java
index afe787f..c6a3e77 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java
@@ -6,6 +6,7 @@
 
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.util.ArrayBuilders;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 import com.fasterxml.jackson.databind.util.LRUMap;
@@ -31,7 +32,7 @@
  *</pre>
  */
 @SuppressWarnings({"rawtypes" })
-public final class TypeFactory
+public class TypeFactory // note: was final in 2.9, removed from 2.10
     implements java.io.Serializable
 {
     private static final long serialVersionUID = 1L;
@@ -63,6 +64,7 @@
     private final static Class<?> CLS_COMPARABLE = Comparable.class;
     private final static Class<?> CLS_CLASS = Class.class;
     private final static Class<?> CLS_ENUM = Enum.class;
+    private final static Class<?> CLS_JSON_NODE = JsonNode.class; // since 2.10
 
     private final static Class<?> CLS_BOOL = Boolean.TYPE;
     private final static Class<?> CLS_INT = Integer.TYPE;
@@ -110,6 +112,14 @@
     protected final static SimpleType CORE_TYPE_CLASS = new SimpleType(CLS_CLASS);
 
     /**
+     * Cache {@link JsonNode} because it is no critical path of simple tree model
+     * reading and does not have things to override
+     *
+     * @since 2.10
+     */
+    protected final static SimpleType CORE_TYPE_JSON_NODE = new SimpleType(CLS_JSON_NODE);
+
+    /**
      * Since type resolution can be expensive (specifically when resolving
      * actual generic types), we will use small cache to avoid repetitive
      * resolution of core types
@@ -171,6 +181,11 @@
         _classLoader = classLoader;
     }
 
+    /**
+     * "Mutant factory" method which will construct a new instance with specified
+     * {@link TypeModifier} added as the first modifier to call (in case there
+     * are multiple registered).
+     */
     public TypeFactory withModifier(TypeModifier mod) 
     {
         LRUMap<Object,JavaType> typeCache = _typeCache;
@@ -192,6 +207,10 @@
         return new TypeFactory(typeCache, _parser, mods, _classLoader);
     }
 
+    /**
+     * "Mutant factory" method which will construct a new instance with specified
+     * {@link ClassLoader} to use by {@link #findClass}.
+     */
     public TypeFactory withClassLoader(ClassLoader classLoader) {
         return new TypeFactory(_typeCache, _parser, _modifiers, classLoader);
     }
@@ -285,7 +304,7 @@
         Throwable prob = null;
         ClassLoader loader = this.getClassLoader();
         if (loader == null) {
-            loader = 	Thread.currentThread().getContextClassLoader();
+            loader = Thread.currentThread().getContextClassLoader();
         }
         if (loader != null) {
             try {
@@ -348,7 +367,6 @@
         if (rawBase == subclass) {
             return baseType;
         }
-
         JavaType newType;
 
         // also: if we start from untyped, not much to save
@@ -363,12 +381,7 @@
             }
             // A few special cases where we can simplify handling:
 
-            // (1) Original target type has no generics -- just resolve subtype
-            if (baseType.getBindings().isEmpty()) {
-                newType = _fromClass(null, subclass, EMPTY_BINDINGS);
-                break;
-            }
-            // (2) A small set of "well-known" List/Map subtypes where can take a short-cut
+            // (1) A small set of "well-known" List/Map subtypes where can take a short-cut
             if (baseType.isContainerType()) {
                 if (baseType.isMapLikeType()) {
                     if ((subclass == HashMap.class)
@@ -395,6 +408,12 @@
                     }
                 }
             }
+            // (2) Original target type has no generics -- just resolve subtype
+            if (baseType.getBindings().isEmpty()) {
+                newType = _fromClass(null, subclass, EMPTY_BINDINGS);
+                break;
+            }
+
             // (3) Sub-class does not take type parameters -- just resolve subtype
             int typeParamCount = subclass.getTypeParameters().length;
             if (typeParamCount == 0) {
@@ -469,8 +488,11 @@
                 // 19-Apr-2018, tatu: Hack for [databind#1964] -- allow type demotion
                 //    for `java.util.Map` key type if (and only if) target type is
                 //    `java.lang.Object`
+                // 19-Aug-2019, tatu: Further, allow for all Map-like types, with assumption
+                //    first argument would be key; initially just because Scala Maps have
+                //    some issues (see [databind#2422])
                 if (i == 0) {
-                    if (sourceType.hasRawClass(Map.class)
+                    if (sourceType.isMapLikeType()
                             && act.hasRawClass(Object.class)) {
                         continue;
                     }
@@ -919,7 +941,7 @@
     /**
      * Factory method for constructing {@link JavaType} that
      * represents a parameterized type. For example, to represent
-     * type <code>List&lt;Set&lt;Integer>></code>, you could
+     * type {@code List<Set<Integer>>}, you could
      * call
      *<pre>
      *  JavaType inner = TypeFactory.constructParametricType(Set.class, Set.class, Integer.class);
@@ -928,7 +950,7 @@
      *<p>
      * The reason for first two arguments to be separate is that parameterization may
      * apply to a super-type. For example, if generic type was instead to be
-     * constructed for <code>ArrayList&lt;Integer></code>, the usual call would be:
+     * constructed for {@code ArrayList<Integer>}, the usual call would be:
      *<pre>
      *  TypeFactory.constructParametricType(ArrayList.class, List.class, Integer.class);
      *</pre>
@@ -955,8 +977,7 @@
     /**
      * Factory method for constructing {@link JavaType} that
      * represents a parameterized type. For example, to represent
-     * type <code>List&lt;Set&lt;Integer>></code>, you could
-     * call
+     * type {@code List<Set<Integer>>}, you could call
      *<pre>
      *  JavaType inner = TypeFactory.constructParametricType(Set.class, Set.class, Integer.class);
      *  return TypeFactory.constructParametricType(ArrayList.class, List.class, inner);
@@ -964,7 +985,7 @@
      *<p>
      * The reason for first two arguments to be separate is that parameterization may
      * apply to a super-type. For example, if generic type was instead to be
-     * constructed for <code>ArrayList&lt;Integer></code>, the usual call would be:
+     * constructed for {@code ArrayList<Integer>}, the usual call would be:
      *<pre>
      *  TypeFactory.constructParametricType(ArrayList.class, List.class, Integer.class);
      *</pre>
@@ -973,10 +994,10 @@
      * one such example is parameterization of types that implement {@link java.util.Iterator}.
      *<p>
      * NOTE: type modifiers are NOT called on constructed type.
-     * 
+     *
      * @param rawType Actual type-erased type
      * @param parameterTypes Type parameters to apply
-     * 
+     *
      * @since 2.5 NOTE: was briefly deprecated for 2.6
      */
     public JavaType constructParametricType(Class<?> rawType, JavaType... parameterTypes)
@@ -1196,6 +1217,7 @@
         } else {
             if (clz == CLS_STRING) return CORE_TYPE_STRING;
             if (clz == CLS_OBJECT) return CORE_TYPE_OBJECT; // since 2.7
+            if (clz == CLS_JSON_NODE) return CORE_TYPE_JSON_NODE; // since 2.10
         }
         return null;
     }
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/ClassUtil.java b/src/main/java/com/fasterxml/jackson/databind/util/ClassUtil.java
index 28e88c5..c34c30f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/ClassUtil.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/ClassUtil.java
@@ -82,12 +82,15 @@
      * Method for finding all super classes (but not super interfaces) of given class,
      * starting with the immediate super class and ending in the most distant one.
      * Class itself is included if <code>addClassItself</code> is true.
+     *<p>
+     * NOTE: mostly/only called to resolve mix-ins as that's where we do not care
+     * about fully-resolved types, just associated annotations.
      *
      * @since 2.7
      */
     public static List<Class<?>> findSuperClasses(Class<?> cls, Class<?> endBefore,
             boolean addClassItself) {
-        List<Class<?>> result = new LinkedList<Class<?>>();
+        List<Class<?>> result = new ArrayList<Class<?>>(8);
         if ((cls != null) && (cls != endBefore))  {
             if (addClassItself) {
                 result.add(cls);
@@ -166,7 +169,7 @@
         if (type.isArray()) {
             return "array";
         }
-        if (type.isEnum()) {
+        if (Enum.class.isAssignableFrom(type)) {
             return "enum";
         }
         if (type.isPrimitive()) {
@@ -654,7 +657,7 @@
     /* Type name, name, desc handling methods
     /**********************************************************
      */
-    
+
     /**
      * Helper method used to construct appropriate description
      * when passed either type (Class) or an instance; in latter
@@ -671,6 +674,27 @@
     }
 
     /**
+     * Helper method to create and return "backticked" description of given
+     * resolved type (or, {@code "null"} if {@code null} passed), similar
+     * to return vaue of {@link #getClassDescription(Object)}.
+     *
+     * @param fullType Fully resolved type or null
+     * @return String description of type including generic type parameters, surrounded
+     *   by backticks, if type passed; or string "null" if {code null} passed
+     *
+     * @since 2.10
+     */
+    public static String getTypeDescription(JavaType fullType)
+    {
+        if (fullType == null) {
+            return "[null]";
+        }
+        StringBuilder sb = new StringBuilder(80).append('`');
+        sb.append(fullType.toCanonical());
+        return sb.append('`').toString();
+    }
+
+    /**
      * Helper method used to construct appropriate description
      * when passed either type (Class) or an instance; in latter
      * case, class of instance is to be used.
@@ -681,7 +705,8 @@
         if (inst == null) {
             return "[null]";
         }
-        return nameOf(inst.getClass());
+        Class<?> raw = (inst instanceof Class<?>) ? (Class<?>) inst : inst.getClass();
+        return nameOf(raw);
     }
 
     /**
@@ -725,7 +750,7 @@
 
     /*
     /**********************************************************
-    /* Other escaping, description acces
+    /* Other escaping, description access
     /**********************************************************
      */
     
@@ -930,6 +955,16 @@
      */
 
     /**
+     * Helper method that encapsulates reliable check on whether
+     * given raw type "is an Enum", that is, is or extends {@link java.lang.Enum}.
+     *
+     * @since 2.10.1
+     */
+    public static boolean isEnumType(Class<?> rawType) {
+        return Enum.class.isAssignableFrom(rawType);
+    }
+
+    /**
      * Helper method that can be used to dynamically figure out
      * enumeration type of given {@link EnumSet}, without having
      * access to its declaration.
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/CompactStringObjectMap.java b/src/main/java/com/fasterxml/jackson/databind/util/CompactStringObjectMap.java
index f27c0c7..cf8024a 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/CompactStringObjectMap.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/CompactStringObjectMap.java
@@ -53,6 +53,11 @@
         for (Map.Entry<String,T> entry : all.entrySet()) {
             String key = entry.getKey();
 
+            // 09-Sep-2019, tatu: [databind#2309] skip `null`s if any included
+            if (key == null) {
+                continue;
+            }
+            
             int slot = key.hashCode() & mask;
             int ix = slot+slot;
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/ConstantValueInstantiator.java b/src/main/java/com/fasterxml/jackson/databind/util/ConstantValueInstantiator.java
deleted file mode 100644
index 0f8abb7..0000000
--- a/src/main/java/com/fasterxml/jackson/databind/util/ConstantValueInstantiator.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.fasterxml.jackson.databind.util;
-
-import java.io.IOException;
-
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.deser.ValueInstantiator;
-
-/**
- * Trivial {@link ValueInstantiator} implementation that will simply return constant
- * {@code Object} it is configured with. May be used as-is, or as base class to override
- * simplistic behavior further.
- *
- * @since 2.9.4
- */
-public class ConstantValueInstantiator extends ValueInstantiator
-{
-    protected final Object _value;
-
-    public ConstantValueInstantiator(Object value) {
-        _value = value;
-    }
-
-    @Override
-    public Class<?> getValueClass() {
-        return _value.getClass();
-    }
-
-    @Override // yes, since default ctor works
-    public boolean canInstantiate() { return true; }
-
-    @Override
-    public boolean canCreateUsingDefault() {  return true; }
-
-    @Override
-    public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
-        return _value;
-    }
-}
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/StdDateFormat.java b/src/main/java/com/fasterxml/jackson/databind/util/StdDateFormat.java
index 02afe5f..a93d0a3 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/StdDateFormat.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/StdDateFormat.java
@@ -16,6 +16,13 @@
  * serializers and deserializers. For serialization defaults to using
  * an ISO-8601 compliant format (format String "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
  * and for deserialization, both ISO-8601 and RFC-1123.
+ *<br>
+ * Note that `Z` in format String refers to RFC-822 timezone notation which produces
+ * values like "-0800" -- that is, full minute/hour combo without colon, and not using `Z`
+ * as alias for "+0000".
+ *<p>
+ * Note also that to enable use of colon in timezone is possible by using method
+ * {@link #withColonInTimeZone} for creating new differently configured format instance.
  */
 @SuppressWarnings("serial")
 public class StdDateFormat
@@ -140,16 +147,18 @@
      * @since 2.9.1
      */
     private transient Calendar _calendar;
-    
+
     private transient DateFormat _formatRFC1123;
 
     /** 
      * Whether the TZ offset must be formatted with a colon between hours and minutes ({@code HH:mm} format)
+     *<p>
+     * Defaults to {@code false} for backwards compatibility reasons
      *
      * @since 2.9.1
      */
     private boolean _tzSerializedWithColon = false;
-    
+
     /*
     /**********************************************************
     /* Life cycle, accessing singleton "standard" formats
@@ -180,7 +189,7 @@
         _lenient = lenient;
         _tzSerializedWithColon = formatTzOffsetWithColon;
     }
-    
+
     public static TimeZone getDefaultTimeZone() {
         return DEFAULT_TIMEZONE;
     }
@@ -471,7 +480,7 @@
             buffer.append(offset < 0 ? '-' : '+');
             pad2(buffer, hours);
             if( _tzSerializedWithColon ) {
-            		buffer.append(':');
+                buffer.append(':');
             }
             pad2(buffer, minutes);
         } else {
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java b/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java
index f31334e..e37835f 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/TokenBuffer.java
@@ -477,7 +477,7 @@
      */
     public TokenBuffer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
     {
-        if (p.getCurrentTokenId() != JsonToken.FIELD_NAME.id()) {
+        if (!p.hasToken(JsonToken.FIELD_NAME)) {
             copyCurrentStructure(p);
             return this;
         }
@@ -667,14 +667,36 @@
     public final void writeStartArray() throws IOException
     {
         _writeContext.writeValue();
-        _append(JsonToken.START_ARRAY);
+        _appendStartMarker(JsonToken.START_ARRAY);
         _writeContext = _writeContext.createChildArrayContext();
     }
 
+    @Override // since 2.10 (method added in 2.4)
+    public final void writeStartArray(int size) throws IOException
+    {
+        _writeContext.writeValue();
+        _appendStartMarker(JsonToken.START_ARRAY);
+        _writeContext = _writeContext.createChildArrayContext();
+    }
+
+    @Override // since 2.10.1
+    public void writeStartArray(Object forValue) throws IOException {
+        _writeContext.writeValue();
+        _appendStartMarker(JsonToken.START_ARRAY);
+        _writeContext = _writeContext.createChildArrayContext();
+    }
+
+    @Override // since 2.10.1
+    public void writeStartArray(Object forValue, int size) throws IOException {
+        _writeContext.writeValue();
+        _appendStartMarker(JsonToken.START_ARRAY);
+        _writeContext = _writeContext.createChildArrayContext(forValue);
+    }
+
     @Override
     public final void writeEndArray() throws IOException
     {
-        _append(JsonToken.END_ARRAY);
+        _appendEndMarker(JsonToken.END_ARRAY);
         // Let's allow unbalanced tho... i.e. not run out of root level, ever
         JsonWriteContext c = _writeContext.getParent();
         if (c != null) {
@@ -686,7 +708,7 @@
     public final void writeStartObject() throws IOException
     {
         _writeContext.writeValue();
-        _append(JsonToken.START_OBJECT);
+        _appendStartMarker(JsonToken.START_OBJECT);
         _writeContext = _writeContext.createChildObjectContext();
     }
 
@@ -694,18 +716,24 @@
     public void writeStartObject(Object forValue) throws IOException
     {
         _writeContext.writeValue();
-        _append(JsonToken.START_OBJECT);
-        JsonWriteContext ctxt = _writeContext.createChildObjectContext();
+        _appendStartMarker(JsonToken.START_OBJECT);
+        JsonWriteContext ctxt = _writeContext.createChildObjectContext(forValue);
         _writeContext = ctxt;
-        if (forValue != null) {
-            ctxt.setCurrentValue(forValue);
-        }
+    }
+
+    @Override // since 2.10.1
+    public void writeStartObject(Object forValue, int size) throws IOException
+    {
+        _writeContext.writeValue();
+        _appendStartMarker(JsonToken.START_OBJECT);
+        JsonWriteContext ctxt = _writeContext.createChildObjectContext(forValue);
+        _writeContext = ctxt;
     }
 
     @Override
     public final void writeEndObject() throws IOException
     {
-        _append(JsonToken.END_OBJECT);
+        _appendEndMarker(JsonToken.END_OBJECT);
         // Let's allow unbalanced tho... i.e. not run out of root level, ever
         JsonWriteContext c = _writeContext.getParent();
         if (c != null) {
@@ -717,16 +745,16 @@
     public final void writeFieldName(String name) throws IOException
     {
         _writeContext.writeFieldName(name);
-        _append(JsonToken.FIELD_NAME, name);
+        _appendFieldName(name);
     }
 
     @Override
     public void writeFieldName(SerializableString name) throws IOException
     {
         _writeContext.writeFieldName(name.getValue());
-        _append(JsonToken.FIELD_NAME, name);
+        _appendFieldName(name);
     }
-    
+
     /*
     /**********************************************************
     /* JsonGenerator implementation: write methods, textual
@@ -1001,7 +1029,7 @@
         if (_mayHaveNativeIds) {
             _checkNativeIds(p);
         }
-        switch (p.getCurrentToken()) {
+        switch (p.currentToken()) {
         case START_OBJECT:
             writeStartObject();
             break;
@@ -1038,11 +1066,10 @@
             break;
         case VALUE_NUMBER_FLOAT:
             if (_forceBigDecimal) {
-                /* 10-Oct-2015, tatu: Ideally we would first determine whether underlying
-                 *   number is already decoded into a number (in which case might as well
-                 *   access as number); or is still retained as text (in which case we
-                 *   should further defer decoding that may not need BigDecimal):
-                 */
+                // 10-Oct-2015, tatu: Ideally we would first determine whether underlying
+                //   number is already decoded into a number (in which case might as well
+                //   access as number); or is still retained as text (in which case we
+                //   should further defer decoding that may not need BigDecimal):
                 writeNumber(p.getDecimalValue());
             } else {
                 switch (p.getNumberType()) {
@@ -1070,14 +1097,14 @@
             writeObject(p.getEmbeddedObject());
             break;
         default:
-            throw new RuntimeException("Internal error: should never end up through this code path");
+            throw new RuntimeException("Internal error: unexpected token: "+p.currentToken());
         }
     }
-    
+
     @Override
     public void copyCurrentStructure(JsonParser p) throws IOException
     {
-        JsonToken t = p.getCurrentToken();
+        JsonToken t = p.currentToken();
 
         // Let's handle field-name separately first
         if (t == JsonToken.FIELD_NAME) {
@@ -1087,54 +1114,173 @@
             writeFieldName(p.getCurrentName());
             t = p.nextToken();
             // fall-through to copy the associated value
+        } else if (t == null) {
+            throw new IllegalStateException("No token available from argument `JsonParser`");
         }
 
-        if (_mayHaveNativeIds) {
-            _checkNativeIds(p);
-        }
-        
+        // We'll do minor handling here to separate structured, scalar values,
+        // then delegate appropriately.
+        // Plus also deal with oddity of "dangling" END_OBJECT/END_ARRAY
         switch (t) {
         case START_ARRAY:
-            writeStartArray();
-            while (p.nextToken() != JsonToken.END_ARRAY) {
-                copyCurrentStructure(p);
+            if (_mayHaveNativeIds) {
+                _checkNativeIds(p);
             }
-            writeEndArray();
+            writeStartArray();
+            _copyBufferContents(p);
             break;
         case START_OBJECT:
-            writeStartObject();
-            while (p.nextToken() != JsonToken.END_OBJECT) {
-                copyCurrentStructure(p);
+            if (_mayHaveNativeIds) {
+                _checkNativeIds(p);
             }
+            writeStartObject();
+            _copyBufferContents(p);
+            break;
+        case END_ARRAY:
+            writeEndArray();
+            break;
+        case END_OBJECT:
             writeEndObject();
             break;
         default: // others are simple:
-            copyCurrentEvent(p);
+            _copyBufferValue(p, t);
         }
     }
 
-    
-    private final void _checkNativeIds(JsonParser jp) throws IOException
+    protected void _copyBufferContents(JsonParser p) throws IOException
     {
-        if ((_typeId = jp.getTypeId()) != null) {
-            _hasNativeId = true;
+        int depth = 1;
+        JsonToken t;
+
+        while ((t = p.nextToken()) != null) {
+            switch (t) {
+            case FIELD_NAME:
+                if (_mayHaveNativeIds) {
+                    _checkNativeIds(p);
+                }
+                writeFieldName(p.getCurrentName());
+                break;
+
+            case START_ARRAY:
+                if (_mayHaveNativeIds) {
+                    _checkNativeIds(p);
+                }
+                writeStartArray();
+                ++depth;
+                break;
+
+            case START_OBJECT:
+                if (_mayHaveNativeIds) {
+                    _checkNativeIds(p);
+                }
+                writeStartObject();
+                ++depth;
+                break;
+
+            case END_ARRAY:
+                writeEndArray();
+                if (--depth == 0) {
+                    return;
+                }
+                break;
+            case END_OBJECT:
+                writeEndObject();
+                if (--depth == 0) {
+                    return;
+                }
+                break;
+
+            default:
+                _copyBufferValue(p, t);
+            }
         }
-        if ((_objectId = jp.getObjectId()) != null) {
-            _hasNativeId = true;
+    }
+
+    // NOTE: Copied from earlier `copyCurrentEvent()`
+    private void _copyBufferValue(JsonParser p, JsonToken t) throws IOException
+    {
+        if (_mayHaveNativeIds) {
+            _checkNativeIds(p);
+        }
+        switch (t) {
+        case VALUE_STRING:
+            if (p.hasTextCharacters()) {
+                writeString(p.getTextCharacters(), p.getTextOffset(), p.getTextLength());
+            } else {
+                writeString(p.getText());
+            }
+            break;
+        case VALUE_NUMBER_INT:
+            switch (p.getNumberType()) {
+            case INT:
+                writeNumber(p.getIntValue());
+                break;
+            case BIG_INTEGER:
+                writeNumber(p.getBigIntegerValue());
+                break;
+            default:
+                writeNumber(p.getLongValue());
+            }
+            break;
+        case VALUE_NUMBER_FLOAT:
+            if (_forceBigDecimal) {
+                writeNumber(p.getDecimalValue());
+            } else {
+                switch (p.getNumberType()) {
+                case BIG_DECIMAL:
+                    writeNumber(p.getDecimalValue());
+                    break;
+                case FLOAT:
+                    writeNumber(p.getFloatValue());
+                    break;
+                default:
+                    writeNumber(p.getDoubleValue());
+                }
+            }
+            break;
+        case VALUE_TRUE:
+            writeBoolean(true);
+            break;
+        case VALUE_FALSE:
+            writeBoolean(false);
+            break;
+        case VALUE_NULL:
+            writeNull();
+            break;
+        case VALUE_EMBEDDED_OBJECT:
+            writeObject(p.getEmbeddedObject());
+            break;
+        default:
+            throw new RuntimeException("Internal error: unexpected token: "+t);
         }
     }
     
+    private final void _checkNativeIds(JsonParser p) throws IOException
+    {
+        if ((_typeId = p.getTypeId()) != null) {
+            _hasNativeId = true;
+        }
+        if ((_objectId = p.getObjectId()) != null) {
+            _hasNativeId = true;
+        }
+    }
+
     /*
     /**********************************************************
     /* Internal methods
     /**********************************************************
      */
 
+    /*// Not used in / since 2.10
     protected final void _append(JsonToken type)
     {
-        Segment next = _hasNativeId
-                ? _last.append(_appendAt, type, _objectId, _typeId)
-                : _last.append(_appendAt, type);
+        Segment next;
+
+        if (_hasNativeId) {
+            next =_last.append(_appendAt, type, _objectId, _typeId);
+        } else {
+            next =  _last.append(_appendAt, type);
+        }
         if (next == null) {
             ++_appendAt;
         } else {
@@ -1145,9 +1291,12 @@
 
     protected final void _append(JsonToken type, Object value)
     {
-        Segment next = _hasNativeId
-                ? _last.append(_appendAt, type, value, _objectId, _typeId)
-                : _last.append(_appendAt, type, value);
+        Segment next;
+        if (_hasNativeId) {
+            next =  _last.append(_appendAt, type, value, _objectId, _typeId);
+        } else {
+            next = _last.append(_appendAt, type, value);
+        }
         if (next == null) {
             ++_appendAt;
         } else {
@@ -1155,19 +1304,23 @@
             _appendAt = 1;
         }
     }
+    */
 
     /**
-     * Similar to {@link #_append(JsonToken)} but also updates context with
-     * knowledge that a scalar value was written
+     * Method used for appending token known to represent a "simple" scalar
+     * value where token is the only information
      *
      * @since 2.6.4
      */
     protected final void _appendValue(JsonToken type)
     {
         _writeContext.writeValue();
-        Segment next = _hasNativeId
-                ? _last.append(_appendAt, type, _objectId, _typeId)
-                : _last.append(_appendAt, type);
+        Segment next;
+        if (_hasNativeId) {
+            next = _last.append(_appendAt, type, _objectId, _typeId);
+        } else {
+            next = _last.append(_appendAt, type);
+        }
         if (next == null) {
             ++_appendAt;
         } else {
@@ -1177,17 +1330,20 @@
     }
 
     /**
-     * Similar to {@link #_append(JsonToken,Object)} but also updates context with
-     * knowledge that a scalar value was written
+     * Method used for appending token known to represent a scalar value
+     * where there is additional content (text, number) beyond type token
      *
      * @since 2.6.4
      */
     protected final void _appendValue(JsonToken type, Object value)
     {
         _writeContext.writeValue();
-        Segment next = _hasNativeId
-                ? _last.append(_appendAt, type, value, _objectId, _typeId)
-                : _last.append(_appendAt, type, value);
+        Segment next;
+        if (_hasNativeId) {
+            next = _last.append(_appendAt, type, value, _objectId, _typeId);
+        } else {
+            next = _last.append(_appendAt, type, value);
+        }
         if (next == null) {
             ++_appendAt;
         } else {
@@ -1196,13 +1352,21 @@
         }
     }
 
-    // 21-Oct-2016, tatu: Does not seem to be used or needed
-    /*
-    protected final void _appendRaw(int rawType, Object value)
+    /**
+     * Specialized method used for appending a field name, appending either
+     * {@link String} or {@link SerializableString}.
+     *
+     * @since 2.10
+     */
+    protected final void _appendFieldName(Object value)
     {
-        Segment next = _hasNativeId
-                ? _last.appendRaw(_appendAt, rawType, value, _objectId, _typeId)
-                : _last.appendRaw(_appendAt, rawType, value);
+        // NOTE: do NOT clear _objectId / _typeId
+        Segment next;
+        if (_hasNativeId) {
+            next =  _last.append(_appendAt, JsonToken.FIELD_NAME, value, _objectId, _typeId);
+        } else {
+            next = _last.append(_appendAt, JsonToken.FIELD_NAME, value);
+        }
         if (next == null) {
             ++_appendAt;
         } else {
@@ -1210,7 +1374,44 @@
             _appendAt = 1;
         }
     }
-    */
+
+    /**
+     * Specialized method used for appending a structural start Object/Array marker
+     *
+     * @since 2.10
+     */
+    protected final void _appendStartMarker(JsonToken type)
+    {
+        Segment next;
+        if (_hasNativeId) {
+            next =_last.append(_appendAt, type, _objectId, _typeId);
+        } else {
+            next =  _last.append(_appendAt, type);
+        }
+        if (next == null) {
+            ++_appendAt;
+        } else {
+            _last = next;
+            _appendAt = 1; // since we added first at 0
+        }
+    }
+
+    /**
+     * Specialized method used for appending a structural end Object/Array marker
+     *
+     * @since 2.10
+     */
+    protected final void _appendEndMarker(JsonToken type)
+    {
+        // NOTE: type/object id not relevant
+        Segment next = _last.append(_appendAt, type);
+        if (next == null) {
+            ++_appendAt;
+        } else {
+            _last = next;
+            _appendAt = 1;
+        }
+    }
 
     @Override
     protected void _reportUnsupportedOperation() {
@@ -1382,6 +1583,8 @@
                     || _currToken == JsonToken.END_ARRAY) {
                 // Closing JSON Object/Array? Close matching context
                 _parsingContext = _parsingContext.parentOrCopy();
+            } else {
+                _parsingContext.updateForValue();
             }
             return _currToken;
         }
diff --git a/src/main/java/com/fasterxml/jackson/databind/util/TokenBufferReadContext.java b/src/main/java/com/fasterxml/jackson/databind/util/TokenBufferReadContext.java
index 6652036..d1a9e08 100644
--- a/src/main/java/com/fasterxml/jackson/databind/util/TokenBufferReadContext.java
+++ b/src/main/java/com/fasterxml/jackson/databind/util/TokenBufferReadContext.java
@@ -92,10 +92,14 @@
     }
 
     public TokenBufferReadContext createChildArrayContext() {
+        // For current context there will be one next Array value, first:
+        ++_index;
         return new TokenBufferReadContext(this, TYPE_ARRAY, -1);
     }
 
     public TokenBufferReadContext createChildObjectContext() {
+        // For current context there will be one next Object value, first:
+        ++_index;
         return new TokenBufferReadContext(this, TYPE_OBJECT, -1);
     }
 
@@ -132,4 +136,17 @@
     public void setCurrentName(String name) throws JsonProcessingException {
         _currentName = name;
     }
+
+    /*
+    /**********************************************************
+    /* Extended support for context updates
+    /**********************************************************
+     */
+
+    /**
+     * @since 2.10.1
+     */
+    public void updateForValue() {
+        ++_index;
+    }
 }
diff --git a/src/moditect/module-info.java b/src/moditect/module-info.java
new file mode 100644
index 0000000..1909d17
--- /dev/null
+++ b/src/moditect/module-info.java
@@ -0,0 +1,40 @@
+// Generated 08-Mar-2019 using Moditect maven plugin
+module com.fasterxml.jackson.databind {
+    requires java.desktop;
+    requires java.logging;
+
+    requires transitive com.fasterxml.jackson.annotation;
+    requires transitive com.fasterxml.jackson.core;
+    // these types were suggested as transitive, but aren't actually
+    // exposed externally (only within internal APIs)
+    requires java.sql;
+    requires java.xml;
+
+    exports com.fasterxml.jackson.databind;
+    exports com.fasterxml.jackson.databind.annotation;
+    exports com.fasterxml.jackson.databind.cfg;
+    exports com.fasterxml.jackson.databind.deser;
+    exports com.fasterxml.jackson.databind.deser.impl;
+    exports com.fasterxml.jackson.databind.deser.std;
+    exports com.fasterxml.jackson.databind.exc;
+    exports com.fasterxml.jackson.databind.ext;
+    exports com.fasterxml.jackson.databind.introspect;
+    exports com.fasterxml.jackson.databind.json;
+    exports com.fasterxml.jackson.databind.jsonFormatVisitors;
+    exports com.fasterxml.jackson.databind.jsonschema;
+    exports com.fasterxml.jackson.databind.jsontype;
+    exports com.fasterxml.jackson.databind.jsontype.impl;
+    exports com.fasterxml.jackson.databind.module;
+    exports com.fasterxml.jackson.databind.node;
+    exports com.fasterxml.jackson.databind.ser;
+    exports com.fasterxml.jackson.databind.ser.impl;
+    exports com.fasterxml.jackson.databind.ser.std;
+    exports com.fasterxml.jackson.databind.type;
+    exports com.fasterxml.jackson.databind.util;
+
+    // [databind#2485]: prevent warning for "unused" with self-use
+    uses com.fasterxml.jackson.databind.Module;
+
+    provides com.fasterxml.jackson.core.ObjectCodec with
+        com.fasterxml.jackson.databind.ObjectMapper;
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java b/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java
index 4771d79..5d2558f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java
@@ -11,6 +11,7 @@
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
@@ -208,36 +209,45 @@
 
     private static ObjectMapper SHARED_MAPPER;
 
-    protected ObjectMapper objectMapper() {
+    protected ObjectMapper sharedMapper() {
         if (SHARED_MAPPER == null) {
-            SHARED_MAPPER = newObjectMapper();
+            SHARED_MAPPER = newJsonMapper();
         }
         return SHARED_MAPPER;
     }
 
+    protected ObjectMapper objectMapper() {
+        return sharedMapper();
+    }
+
     protected ObjectWriter objectWriter() {
-        return objectMapper().writer();
+        return sharedMapper().writer();
     }
 
     protected ObjectReader objectReader() {
-        return objectMapper().reader();
+        return sharedMapper().reader();
     }
     
     protected ObjectReader objectReader(Class<?> cls) {
-        return objectMapper().readerFor(cls);
+        return sharedMapper().readerFor(cls);
     }
 
-    // @since 2.9
-    protected static ObjectMapper newObjectMapper() {
+    // @since 2.10
+    protected static ObjectMapper newJsonMapper() {
         return new ObjectMapper();
     }
 
+    // @since 2.10
+    protected static JsonMapper.Builder jsonMapperBuilder() {
+        return JsonMapper.builder();
+    }
+
     // @since 2.7
     protected TypeFactory newTypeFactory() {
         // this is a work-around; no null modifier added
         return TypeFactory.defaultInstance().withModifier(null);
     }
-    
+
     /*
     /**********************************************************
     /* Additional assert methods
@@ -291,13 +301,13 @@
     protected String serializeAsString(Object value)
         throws IOException
     {
-        return serializeAsString(objectMapper(), value);
+        return serializeAsString(sharedMapper(), value);
     }
 
     protected String asJSONObjectValueString(Object... args)
         throws IOException
     {
-        return asJSONObjectValueString(objectMapper(), args);
+        return asJSONObjectValueString(sharedMapper(), args);
     }
 
     protected String asJSONObjectValueString(ObjectMapper m, Object... args)
@@ -319,7 +329,7 @@
     protected <T> T readAndMapFromString(String input, Class<T> cls)
         throws IOException
     {
-        return readAndMapFromString(objectMapper(), input, cls);
+        return readAndMapFromString(sharedMapper(), input, cls);
     }
 
     protected <T> T readAndMapFromString(ObjectMapper m, String input, Class<T> cls) throws IOException
diff --git a/src/test/java/com/fasterxml/jackson/databind/FullStreamReadTest.java b/src/test/java/com/fasterxml/jackson/databind/FullStreamReadTest.java
deleted file mode 100644
index 6bfa5cc..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/FullStreamReadTest.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package com.fasterxml.jackson.databind;
-
-import java.util.*;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.databind.exc.MismatchedInputException;
-
-public class FullStreamReadTest extends BaseMapTest
-{
-    private final static String JSON_OK_ARRAY = " [ 1, 2, 3]    ";
-    private final static String JSON_OK_ARRAY_WITH_COMMENT = JSON_OK_ARRAY + " // stuff ";
-
-    private final static String JSON_FAIL_ARRAY = JSON_OK_ARRAY + " [ ]";
-
-    /*
-    /**********************************************************
-    /* Test methods, config
-    /**********************************************************
-     */
-
-    private final ObjectMapper MAPPER = newObjectMapper();
-
-    public void testMapperAcceptTrailing() throws Exception
-    {
-        assertFalse(MAPPER.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS));
-
-        // by default, should be ok to read, all
-        _verifyArray(MAPPER.readTree(JSON_OK_ARRAY));
-        _verifyArray(MAPPER.readTree(JSON_OK_ARRAY_WITH_COMMENT));
-        _verifyArray(MAPPER.readTree(JSON_FAIL_ARRAY));
-
-        // and also via "untyped"
-        _verifyCollection(MAPPER.readValue(JSON_OK_ARRAY, List.class));
-        _verifyCollection(MAPPER.readValue(JSON_OK_ARRAY_WITH_COMMENT, List.class));
-        _verifyCollection(MAPPER.readValue(JSON_FAIL_ARRAY, List.class));
-    }
-
-    public void testMapperFailOnTrailing() throws Exception
-    {
-        // but things change if we enforce checks
-        ObjectMapper strict = newObjectMapper()
-                .enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
-        assertTrue(strict.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS));
-
-        // some still ok
-        _verifyArray(strict.readTree(JSON_OK_ARRAY));
-        _verifyCollection(strict.readValue(JSON_OK_ARRAY, List.class));
-
-        // but if real content exists, will fail
-        try {
-            strict.readTree(JSON_FAIL_ARRAY);
-            fail("Should not have passed");
-        } catch (MismatchedInputException e) {
-            verifyException(e, "Trailing token (of type START_ARRAY)");
-            verifyException(e, "value (bound as `com.fasterxml.jackson.databind.JsonNode`)");
-        }
-
-        try {
-            strict.readValue(JSON_FAIL_ARRAY, List.class);
-            fail("Should not have passed");
-        } catch (MismatchedInputException e) {
-            verifyException(e, "Trailing token (of type START_ARRAY)");
-            verifyException(e, "value (bound as `java.util.List`)");
-        }
-
-        // others fail conditionally: will fail on comments unless enabled
-
-        try {
-            strict.readValue(JSON_OK_ARRAY_WITH_COMMENT, List.class);
-            fail("Should not have passed");
-        } catch (JsonParseException e) {
-            verifyException(e, "Unexpected character");
-            verifyException(e, "maybe a (non-standard) comment");
-        }
-        try {
-            strict.readTree(JSON_OK_ARRAY_WITH_COMMENT);
-            fail("Should not have passed");
-        } catch (JsonParseException e) {
-            verifyException(e, "Unexpected character");
-            verifyException(e, "maybe a (non-standard) comment");
-        }
-
-        ObjectMapper strictWithComments = strict.copy();
-        strictWithComments.enable(JsonParser.Feature.ALLOW_COMMENTS);
-        _verifyArray(strictWithComments.readTree(JSON_OK_ARRAY_WITH_COMMENT));
-        _verifyCollection(strictWithComments.readValue(JSON_OK_ARRAY_WITH_COMMENT, List.class));
-    }
-
-    public void testReaderAcceptTrailing() throws Exception
-    {
-        ObjectReader R = MAPPER.reader();
-        assertFalse(R.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS));
-
-        _verifyArray(R.readTree(JSON_OK_ARRAY));
-        _verifyArray(R.readTree(JSON_OK_ARRAY_WITH_COMMENT));
-        _verifyArray(R.readTree(JSON_FAIL_ARRAY));
-        ObjectReader rColl = R.forType(List.class);
-        _verifyCollection((List<?>)rColl.readValue(JSON_OK_ARRAY));
-        _verifyCollection((List<?>)rColl.readValue(JSON_OK_ARRAY_WITH_COMMENT));
-        _verifyCollection((List<?>)rColl.readValue(JSON_FAIL_ARRAY));
-    }
-
-    public void testReaderFailOnTrailing() throws Exception
-    {
-        ObjectReader strictR = MAPPER.reader().with(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
-        ObjectReader strictRForList = strictR.forType(List.class);
-        _verifyArray(strictR.readTree(JSON_OK_ARRAY));
-        _verifyCollection((List<?>)strictRForList.readValue(JSON_OK_ARRAY));
-
-        // Will fail hard if there is a trailing token
-        try {
-            strictRForList.readValue(JSON_FAIL_ARRAY);
-            fail("Should not have passed");
-        } catch (MismatchedInputException e) {
-            verifyException(e, "Trailing token (of type START_ARRAY)");
-            verifyException(e, "value (bound as `java.util.List`)");
-        }
-        try {
-            strictR.readTree(JSON_FAIL_ARRAY);
-            fail("Should not have passed");
-        } catch (MismatchedInputException e) {
-            verifyException(e, "Trailing token (of type START_ARRAY)");
-            verifyException(e, "value (bound as `com.fasterxml.jackson.databind.JsonNode`)");
-        }
-
-        // ... also verify that same happens with "value to update"
-        try {
-            strictR.withValueToUpdate(new ArrayList<Object>())
-                .readValue(JSON_FAIL_ARRAY);
-            fail("Should not have passed");
-        } catch (MismatchedInputException e) {
-            verifyException(e, "Trailing token (of type START_ARRAY)");
-            verifyException(e, "value (bound as `java.util.ArrayList`)");
-        }
-
-        // others conditionally: will fail on comments unless enabled
-
-        try {
-            strictRForList.readValue(JSON_OK_ARRAY_WITH_COMMENT);
-            fail("Should not have passed");
-        } catch (JsonParseException e) {
-            verifyException(e, "Unexpected character");
-            verifyException(e, "maybe a (non-standard) comment");
-        }
-        try {
-            strictR.readTree(JSON_OK_ARRAY_WITH_COMMENT);
-            fail("Should not have passed");
-        } catch (JsonParseException e) {
-            verifyException(e, "Unexpected character");
-            verifyException(e, "maybe a (non-standard) comment");
-        }
-
-        // but works if comments enabled etc
-
-        ObjectReader strictRWithComments = strictR.with(JsonParser.Feature.ALLOW_COMMENTS);
-        
-        _verifyCollection((List<?>)strictRWithComments.forType(List.class).readValue(JSON_OK_ARRAY_WITH_COMMENT));
-        _verifyArray(strictRWithComments.readTree(JSON_OK_ARRAY_WITH_COMMENT));
-    }
-
-    private void _verifyArray(JsonNode n) throws Exception
-    {
-        assertTrue(n.isArray());
-        assertEquals(3, n.size());
-    }
-
-    private void _verifyCollection(List<?> coll) throws Exception
-    {
-        assertEquals(3, coll.size());
-        assertEquals(Integer.valueOf(1), coll.get(0));
-        assertEquals(Integer.valueOf(2), coll.get(1));
-        assertEquals(Integer.valueOf(3), coll.get(2));
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/MapperViaParserTest.java b/src/test/java/com/fasterxml/jackson/databind/MapperViaParserTest.java
index 54400df..a4a3272 100644
--- a/src/test/java/com/fasterxml/jackson/databind/MapperViaParserTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/MapperViaParserTest.java
@@ -6,7 +6,9 @@
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.io.CharacterEscapes;
 import com.fasterxml.jackson.core.io.SerializedString;
+import com.fasterxml.jackson.core.json.JsonWriteFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 
 public class MapperViaParserTest  extends BaseMapTest
 {
@@ -94,60 +96,58 @@
     /**
      * Test similar to above, but instead reads a sequence of values
      */
-    public void testIncrementalPojoReading()
-        throws IOException
+    public void testIncrementalPojoReading() throws IOException
     {
         JsonFactory jf = new MappingJsonFactory();
         final String JSON = "[ 1, true, null, \"abc\" ]";
-        JsonParser jp = jf.createParser(new StringReader(JSON));
+        JsonParser p = jf.createParser(new StringReader(JSON));
 
         // let's advance past array start to prevent full binding
-        assertToken(JsonToken.START_ARRAY, jp.nextToken());
+        assertToken(JsonToken.START_ARRAY, p.nextToken());
 
-        assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
-        assertEquals(Integer.valueOf(1), jp.readValueAs(Integer.class));
-        assertEquals(Boolean.TRUE, jp.readValueAs(Boolean.class));
+        assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
+        assertEquals(Integer.valueOf(1), p.readValueAs(Integer.class));
+        assertEquals(Boolean.TRUE, p.readValueAs(Boolean.class));
         /* note: null can be returned both when there is no more
          * data in current scope, AND when Json null literal is
          * bound!
          */
-        assertNull(jp.readValueAs(Object.class));
+        assertNull(p.readValueAs(Object.class));
         // but we can verify that it was Json null by:
-        assertEquals(JsonToken.VALUE_NULL, jp.getLastClearedToken());
+        assertEquals(JsonToken.VALUE_NULL, p.getLastClearedToken());
 
-        assertEquals("abc", jp.readValueAs(String.class));
+        assertEquals("abc", p.readValueAs(String.class));
 
         // this null is for actually hitting the END_ARRAY
-        assertNull(jp.readValueAs(Object.class));
-        assertEquals(JsonToken.END_ARRAY, jp.getLastClearedToken());
+        assertNull(p.readValueAs(Object.class));
+        assertEquals(JsonToken.END_ARRAY, p.getLastClearedToken());
 
         // afrer which there should be nothing to advance to:
-        assertNull(jp.nextToken());
+        assertNull(p.nextToken());
 
-        jp.close();
+        p.close();
     }
 
     @SuppressWarnings("resource")
-    public void testPojoReadingFailing()
-        throws IOException
+    public void testPojoReadingFailing() throws IOException
     {
         // regular factory can't do it, without a call to setCodec()
-        JsonFactory jf = new JsonFactory();
+        JsonFactory f = new JsonFactory();
         try {
             final String JSON = "{ \"x\" : 9 }";
-            JsonParser jp = jf.createParser(new StringReader(JSON));
-            Pojo p = jp.readValueAs(Pojo.class);
-            fail("Expected an exception: got "+p);
+            JsonParser p = f.createParser(new StringReader(JSON));
+            Pojo pojo = p.readValueAs(Pojo.class);
+            fail("Expected an exception: got "+pojo);
         } catch (IllegalStateException e) {
             verifyException(e, "No ObjectCodec defined");
         }
     }
-    
-    // for [JACKSON-672]
+
     public void testEscapingUsingMapper() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true);
+        ObjectMapper mapper = JsonMapper.builder()
+               .configure(JsonWriteFeature.ESCAPE_NON_ASCII, true)
+               .build();
         mapper.writeValueAsString(String.valueOf((char) 257));
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java b/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java
index f59eabc..7f1daa5 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java
@@ -1,5 +1,6 @@
 package com.fasterxml.jackson.databind;
 
+import com.fasterxml.jackson.databind.module.SimpleModule;
 import java.io.*;
 import java.util.*;
 
@@ -8,10 +9,12 @@
 import com.fasterxml.jackson.annotation.JsonSetter;
 import com.fasterxml.jackson.annotation.Nulls;
 import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.core.json.JsonWriteFeature;
 import com.fasterxml.jackson.core.util.MinimalPrettyPrinter;
 
 import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
 import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.databind.node.*;
 
 public class ObjectMapperTest extends BaseMapTest
@@ -56,7 +59,7 @@
     /**********************************************************
      */
 
-    public void testFactorFeatures()
+    public void testFactoryFeatures()
     {
         assertTrue(MAPPER.isEnabled(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES));
     }
@@ -64,24 +67,32 @@
     public void testGeneratorFeatures()
     {
         // and also for mapper
-        ObjectMapper mapper = new ObjectMapper();
-        assertFalse(mapper.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII));
-        assertTrue(mapper.isEnabled(JsonGenerator.Feature.QUOTE_FIELD_NAMES));
-        mapper.disable(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM,
-                JsonGenerator.Feature.QUOTE_FIELD_NAMES);
+        JsonMapper mapper = new JsonMapper();
+        assertTrue(mapper.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET));
+        assertTrue(mapper.isEnabled(StreamWriteFeature.AUTO_CLOSE_TARGET));
+        assertFalse(mapper.isEnabled(JsonWriteFeature.ESCAPE_NON_ASCII));
+        assertTrue(mapper.isEnabled(JsonWriteFeature.WRITE_NAN_AS_STRINGS));
+        mapper = JsonMapper.builder()
+                .disable(StreamWriteFeature.FLUSH_PASSED_TO_STREAM)
+                .disable(JsonWriteFeature.WRITE_NAN_AS_STRINGS)
+                .build();
+        assertFalse(mapper.isEnabled(StreamWriteFeature.FLUSH_PASSED_TO_STREAM));
+        assertFalse(mapper.isEnabled(JsonWriteFeature.WRITE_NAN_AS_STRINGS));
     }
 
     public void testParserFeatures()
     {
         // and also for mapper
         ObjectMapper mapper = new ObjectMapper();
-                
+
         assertTrue(mapper.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE));
-        assertFalse(mapper.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
+        assertTrue(mapper.isEnabled(StreamReadFeature.AUTO_CLOSE_SOURCE));
+        assertFalse(mapper.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
 
         mapper.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE,
                 JsonParser.Feature.STRICT_DUPLICATE_DETECTION);
         assertFalse(mapper.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE));
+        assertFalse(mapper.isEnabled(StreamReadFeature.AUTO_CLOSE_SOURCE));
     }
 
     /*
@@ -99,9 +110,9 @@
         assertFalse(m.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
         InjectableValues inj = new InjectableValues.Std();
         m.setInjectableValues(inj);
-        assertFalse(m.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
-        m.enable(JsonParser.Feature.ALLOW_COMMENTS);
-        assertTrue(m.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
+        assertFalse(m.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
+        m.enable(JsonParser.Feature.IGNORE_UNDEFINED);
+        assertTrue(m.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
 
         // // First: verify that handling of features is decoupled:
         
@@ -138,7 +149,7 @@
         assertEquals(0, m2.getDeserializationConfig().mixInCount());
 
         // [databind#913]: Ensure JsonFactory Features copied
-        assertTrue(m2.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
+        assertTrue(m2.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
     }
 
     // [databind#1580]
@@ -228,7 +239,9 @@
         assertFalse(dc.shouldSortPropertiesAlphabetically());
 
         // but when enabled, should be visible:
-        m.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
+        m = jsonMapperBuilder()
+                .enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
+                .build();
         sc = m.getSerializationConfig();
         assertTrue(sc.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY));
         assertTrue(sc.shouldSortPropertiesAlphabetically());
@@ -345,17 +358,17 @@
     {
         // ensure we have "fresh" instance to start with
         ObjectMapper mapper = new ObjectMapper();
-        assertFalse(mapper.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
-        mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
-        assertTrue(mapper.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
+        assertFalse(mapper.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
+        mapper.configure(JsonParser.Feature.IGNORE_UNDEFINED, true);
+        assertTrue(mapper.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
 
         ObjectMapper copy = mapper.copy();
-        assertTrue(copy.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
+        assertTrue(copy.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
 
         // also verify there's no back-linkage
-        copy.configure(JsonParser.Feature.ALLOW_COMMENTS, false);
-        assertFalse(copy.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
-        assertTrue(mapper.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
+        copy.configure(JsonParser.Feature.IGNORE_UNDEFINED, false);
+        assertFalse(copy.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
+        assertTrue(mapper.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
     }
 
     // since 2.8
@@ -364,15 +377,17 @@
         ByteArrayOutputStream bytes = new ByteArrayOutputStream();
         ObjectNode input = MAPPER.createObjectNode();
         input.put("a", 1);
-        DataOutput data = new DataOutputStream(bytes);
         final String exp = "{\"a\":1}";
-        MAPPER.writeValue(data, input);
+        try (DataOutputStream data = new DataOutputStream(bytes)) {
+            MAPPER.writeValue((DataOutput) data, input);
+        }
         assertEquals(exp, bytes.toString("UTF-8"));
 
         // and also via ObjectWriter...
         bytes.reset();
-        data = new DataOutputStream(bytes);
-        MAPPER.writer().writeValue(data, input);
+        try (DataOutputStream data = new DataOutputStream(bytes)) {
+            MAPPER.writer().writeValue((DataOutput) data, input);
+        }
         assertEquals(exp, bytes.toString("UTF-8"));
     }
 
@@ -396,4 +411,42 @@
                 .readTree(input);
         assertNotNull(n);
     }
+
+    @SuppressWarnings("serial")
+    public void testRegisterDependentModules() {
+        ObjectMapper objectMapper = newJsonMapper();
+
+        final SimpleModule secondModule = new SimpleModule() {
+            @Override
+            public Object getTypeId() {
+                return "second";
+            }
+        };
+
+        final SimpleModule thirdModule = new SimpleModule() {
+            @Override
+            public Object getTypeId() {
+                return "third";
+            }
+        };
+
+        final SimpleModule firstModule = new SimpleModule() {
+            @Override
+            public Iterable<? extends Module> getDependencies() {
+                return Arrays.asList(secondModule, thirdModule);
+            }
+
+            @Override
+            public Object getTypeId() {
+                return "main";
+            }
+        };
+
+        objectMapper.registerModule(firstModule);
+
+        assertEquals(
+            new HashSet<>(Arrays.asList("second", "third", "main")),
+            objectMapper.getRegisteredModuleIds()
+        );
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ObjectReaderTest.java b/src/test/java/com/fasterxml/jackson/databind/ObjectReaderTest.java
index 1d67d55..7426829 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ObjectReaderTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ObjectReaderTest.java
@@ -1,22 +1,26 @@
 package com.fasterxml.jackson.databind;
 
+import java.io.IOException;
 import java.io.StringWriter;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.core.*;
-
+import com.fasterxml.jackson.core.json.JsonReadFeature;
 import com.fasterxml.jackson.databind.cfg.ContextAttributes;
 import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 
 public class ObjectReaderTest extends BaseMapTest
 {
-    final ObjectMapper MAPPER = new ObjectMapper();
+    final JsonMapper MAPPER = JsonMapper.builder().build();
 
     static class POJO {
         public Map<String, Object> name;
@@ -51,7 +55,7 @@
         final String JSON = "[ /* foo */ 7 ]";
         // default won't accept comments, let's change that:
         ObjectReader reader = MAPPER.readerFor(int[].class)
-                .with(JsonParser.Feature.ALLOW_COMMENTS);
+                .with(JsonReadFeature.ALLOW_JAVA_COMMENTS);
 
         int[] value = reader.readValue(JSON);
         assertNotNull(value);
@@ -60,7 +64,7 @@
 
         // but also can go back
         try {
-            reader.without(JsonParser.Feature.ALLOW_COMMENTS).readValue(JSON);
+            reader.without(JsonReadFeature.ALLOW_JAVA_COMMENTS).readValue(JSON);
             fail("Should not have passed");
         } catch (JsonProcessingException e) {
             verifyException(e, "foo");
@@ -81,7 +85,7 @@
     {
         ObjectReader r = MAPPER.reader();
         assertFalse(r.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES));
-        assertFalse(r.isEnabled(JsonParser.Feature.ALLOW_COMMENTS));
+        assertFalse(r.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
         
         r = r.withoutFeatures(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES,
                 DeserializationFeature.FAIL_ON_INVALID_SUBTYPE);
@@ -97,6 +101,29 @@
                 DeserializationFeature.FAIL_ON_INVALID_SUBTYPE));
     }
 
+    public void testFeatureSettingsDeprecated() throws Exception
+    {
+        final ObjectReader r = MAPPER.reader();
+        assertFalse(r.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
+
+        assertTrue(r.with(JsonParser.Feature.IGNORE_UNDEFINED)
+                .isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
+        assertFalse(r.without(JsonParser.Feature.IGNORE_UNDEFINED)
+                .isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
+
+        // and then variants
+        assertFalse(r.isEnabled(JsonParser.Feature.STRICT_DUPLICATE_DETECTION));
+        ObjectReader r2 = r.withFeatures(JsonParser.Feature.IGNORE_UNDEFINED,
+                JsonParser.Feature.STRICT_DUPLICATE_DETECTION);
+        assertTrue(r2.isEnabled(JsonParser.Feature.STRICT_DUPLICATE_DETECTION));
+        assertTrue(r2.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
+
+        ObjectReader r3 = r2.withoutFeatures(JsonParser.Feature.IGNORE_UNDEFINED,
+                JsonParser.Feature.STRICT_DUPLICATE_DETECTION);
+        assertFalse(r3.isEnabled(JsonParser.Feature.STRICT_DUPLICATE_DETECTION));
+        assertFalse(r3.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
+    }
+
     public void testMiscSettings() throws Exception
     {
         ObjectReader r = MAPPER.reader();
@@ -151,6 +178,16 @@
         assertEquals(Integer.valueOf(123), n);
     }
 
+    // @since 2.10
+    public void testGetValueType() throws Exception
+    {
+        ObjectReader r = MAPPER.reader();
+        assertNull(r.getValueType());
+
+        r = r.forType(String.class);
+        assertEquals(MAPPER.constructType(String.class), r.getValueType());
+    }
+
     /*
     /**********************************************************
     /* Test methods, JsonPointer
@@ -324,4 +361,28 @@
             verifyException(e, "Cannot use FormatSchema");
         }
     }
+
+    // For [databind#2297]
+    public void testUnknownFields() throws Exception
+    {
+        ObjectMapper mapper = JsonMapper.builder().addHandler(new DeserializationProblemHandler(){
+            @Override
+            public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p, JsonDeserializer<?> deserializer, Object beanOrClass, String propertyName) throws IOException {
+                p.readValueAsTree();
+                return true;
+            }
+        }).build();
+        A aObject = mapper.readValue("{\"unknownField\" : 1, \"knownField\": \"test\"}", A.class);
+
+        assertEquals("test", aObject.knownField);
+    }
+
+    private static class A{
+        private String knownField;
+
+        @JsonCreator
+        private A(@JsonProperty("knownField") String knownField) {
+            this.knownField = knownField;
+        }
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ObjectWriterTest.java b/src/test/java/com/fasterxml/jackson/databind/ObjectWriterTest.java
index b9d2e5d..7c04265 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ObjectWriterTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ObjectWriterTest.java
@@ -11,6 +11,7 @@
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.io.SerializedString;
+import com.fasterxml.jackson.core.json.JsonWriteFeature;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 
 /**
@@ -90,12 +91,12 @@
     public void testObjectWriterFeatures() throws Exception
     {
         ObjectWriter writer = MAPPER.writer()
-                .without(JsonGenerator.Feature.QUOTE_FIELD_NAMES);                
+                .without(JsonWriteFeature.QUOTE_FIELD_NAMES);                
         Map<String,Integer> map = new HashMap<String,Integer>();
         map.put("a", 1);
         assertEquals("{a:1}", writer.writeValueAsString(map));
         // but can also reconfigure
-        assertEquals("{\"a\":1}", writer.with(JsonGenerator.Feature.QUOTE_FIELD_NAMES)
+        assertEquals("{\"a\":1}", writer.with(JsonWriteFeature.QUOTE_FIELD_NAMES)
                 .writeValueAsString(map));
     }
 
@@ -260,9 +261,8 @@
     public void testGeneratorFeatures() throws Exception
     {
         ObjectWriter w = MAPPER.writer();
-        assertFalse(w.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII));
-        assertNotSame(w, w.with(JsonGenerator.Feature.ESCAPE_NON_ASCII));
-        assertNotSame(w, w.withFeatures(JsonGenerator.Feature.ESCAPE_NON_ASCII));
+        assertNotSame(w, w.with(JsonWriteFeature.ESCAPE_NON_ASCII));
+        assertNotSame(w, w.withFeatures(JsonWriteFeature.ESCAPE_NON_ASCII));
 
         assertTrue(w.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET));
         assertNotSame(w, w.without(JsonGenerator.Feature.AUTO_CLOSE_TARGET));
@@ -282,7 +282,7 @@
             w.acceptJsonFormatVisitor((JavaType) null, null);
             fail("Should not pass");
         } catch (IllegalArgumentException e) {
-            verifyException(e, "type must be provided");
+            verifyException(e, "argument \"type\" is null");
         }
     }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/RoundtripTest.java b/src/test/java/com/fasterxml/jackson/databind/RoundtripTest.java
index 18fe21e..704c573 100644
--- a/src/test/java/com/fasterxml/jackson/databind/RoundtripTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/RoundtripTest.java
@@ -1,5 +1,7 @@
 package com.fasterxml.jackson.databind;
 
+import com.fasterxml.jackson.databind.testutil.MediaItem;
+
 public class RoundtripTest extends BaseMapTest
 {
     private final ObjectMapper MAPPER = new ObjectMapper();
diff --git a/src/test/java/com/fasterxml/jackson/databind/TestJDKSerialization.java b/src/test/java/com/fasterxml/jackson/databind/TestJDKSerialization.java
index d42abe0..e79f934 100644
--- a/src/test/java/com/fasterxml/jackson/databind/TestJDKSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/TestJDKSerialization.java
@@ -5,12 +5,6 @@
 
 import com.fasterxml.jackson.annotation.JsonAnyGetter;
 import com.fasterxml.jackson.annotation.JsonAnySetter;
-import com.fasterxml.jackson.databind.DeserializationConfig;
-import com.fasterxml.jackson.databind.JavaType;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectReader;
-import com.fasterxml.jackson.databind.ObjectWriter;
-import com.fasterxml.jackson.databind.SerializationConfig;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.fasterxml.jackson.databind.util.LRUMap;
 
@@ -72,7 +66,7 @@
      *   ObjectMapper here can lead to strange unit test suite failures, so
      *   let's create a private copy for this class only.
      */
-    private final ObjectMapper MAPPER = new ObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
     
     public void testConfigs() throws IOException
     {
@@ -97,7 +91,7 @@
     // for [databind#899]
     public void testEnumHandlers() throws IOException
     {
-        ObjectMapper mapper = new ObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         // ensure we have serializers and/or deserializers, first
         String json = mapper.writerFor(EnumPOJO.class)
                 .writeValueAsString(new EnumPOJO());
@@ -218,7 +212,7 @@
     
     protected byte[] jdkSerialize(Object o) throws IOException
     {
-        ByteArrayOutputStream bytes = new ByteArrayOutputStream(1000);
+        ByteArrayOutputStream bytes = new ByteArrayOutputStream(2000);
         ObjectOutputStream obOut = new ObjectOutputStream(bytes);
         obOut.writeObject(o);
         obOut.close();
diff --git a/src/test/java/com/fasterxml/jackson/databind/TestNodeJDKSerialization.java b/src/test/java/com/fasterxml/jackson/databind/TestNodeJDKSerialization.java
new file mode 100644
index 0000000..949fee5
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/TestNodeJDKSerialization.java
@@ -0,0 +1,92 @@
+package com.fasterxml.jackson.databind;
+
+import java.io.*;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+public class TestNodeJDKSerialization extends BaseMapTest
+{
+    private final ObjectMapper MAPPER = newJsonMapper();
+
+    /*
+    /**********************************************************
+    /* Then something bit different; serialize `JsonNode`(s)
+    /**********************************************************
+     */
+
+    // [databind#18]: Allow JDK serialization of `ObjectNode`
+    public void testObjectNodeSerialization() throws Exception
+    {
+        ObjectNode root = MAPPER.createObjectNode();
+        root.put("answer", 42);
+        ArrayNode arr = root.withArray("matrix");
+        arr.add(1).add(12345678901L).add(true).add("...");
+        ObjectNode misc = root.with("misc");
+        misc.put("value", 0.25);
+
+        testNodeRoundtrip(root);
+    }
+
+    // [databind#18]: Allow JDK serialization of `ArrayNode`
+    public void testArrayNodeSerialization() throws Exception
+    {
+        ArrayNode root = MAPPER.createArrayNode();
+        root.add(false);
+        ObjectNode props = root.addObject();
+        props.put("answer", 42);
+        root.add(137);
+
+        testNodeRoundtrip(root);
+    }
+
+    // and then also some scalar types
+    public void testScalarSerialization() throws Exception
+    {
+        testNodeRoundtrip(MAPPER.getNodeFactory().nullNode());
+
+        testNodeRoundtrip(MAPPER.getNodeFactory().textNode("Foobar"));
+
+        testNodeRoundtrip(MAPPER.getNodeFactory().booleanNode(true));
+        testNodeRoundtrip(MAPPER.getNodeFactory().booleanNode(false));
+
+        testNodeRoundtrip(MAPPER.getNodeFactory().numberNode(123));
+        testNodeRoundtrip(MAPPER.getNodeFactory().numberNode(-12345678901234L));
+    }
+
+    /*
+    /**********************************************************
+    /* Helper methods
+    /**********************************************************
+     */
+
+    protected void testNodeRoundtrip(JsonNode input) throws Exception
+    {
+        byte[] ser = jdkSerialize(input);
+        JsonNode result = jdkDeserialize(ser);
+        assertEquals(input, result);
+    }
+
+    protected byte[] jdkSerialize(Object o) throws IOException
+    {
+        ByteArrayOutputStream bytes = new ByteArrayOutputStream(1000);
+        ObjectOutputStream obOut = new ObjectOutputStream(bytes);
+        obOut.writeObject(o);
+        obOut.close();
+        return bytes.toByteArray();
+    }
+
+    @SuppressWarnings("unchecked")
+    protected <T> T jdkDeserialize(byte[] raw) throws IOException
+    {
+        ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(raw));
+        try {
+            return (T) objIn.readObject();
+        } catch (ClassNotFoundException e) {
+            fail("Missing class: "+e.getMessage());
+            return null;
+        } finally {
+            objIn.close();
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/access/TestAnyGetterAccess.java b/src/test/java/com/fasterxml/jackson/databind/access/TestAnyGetterAccess.java
index 311a86b..be141ca 100644
--- a/src/test/java/com/fasterxml/jackson/databind/access/TestAnyGetterAccess.java
+++ b/src/test/java/com/fasterxml/jackson/databind/access/TestAnyGetterAccess.java
@@ -51,7 +51,7 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = new ObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
     
     public void testDynaBean() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/big/TestBiggerData.java b/src/test/java/com/fasterxml/jackson/databind/big/TestBiggerData.java
index 655a3d8..d0b3dd6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/big/TestBiggerData.java
+++ b/src/test/java/com/fasterxml/jackson/databind/big/TestBiggerData.java
@@ -72,10 +72,11 @@
     /**********************************************************
      */
 
+	private final ObjectMapper MAPPER = newJsonMapper();
+
 	public void testReading() throws Exception
 	{
-		ObjectMapper mapper = objectMapper();
-		Citm citm = mapper.readValue(getClass().getResourceAsStream("/data/citm_catalog.json"),
+		Citm citm = MAPPER.readValue(getClass().getResourceAsStream("/data/citm_catalog.json"),
 				Citm.class);
 		assertNotNull(citm);
 		assertNotNull(citm.areaNames);
@@ -99,14 +100,13 @@
 
 	public void testRoundTrip() throws Exception
 	{
-		ObjectMapper mapper = objectMapper();
-		Citm citm = mapper.readValue(getClass().getResourceAsStream("/data/citm_catalog.json"),
+		Citm citm = MAPPER.readValue(getClass().getResourceAsStream("/data/citm_catalog.json"),
 				Citm.class);
 
-		ObjectWriter w = mapper.writerWithDefaultPrettyPrinter();
+		ObjectWriter w = MAPPER.writerWithDefaultPrettyPrinter();
 		
 		String json1 = w.writeValueAsString(citm);
-		Citm citm2 = mapper.readValue(json1, Citm.class);
+		Citm citm2 = MAPPER.readValue(json1, Citm.class);
 		String json2 = w.writeValueAsString(citm2);
 
 		assertEquals(json1, json2);
diff --git a/src/test/java/com/fasterxml/jackson/databind/cfg/DatabindContextTest.java b/src/test/java/com/fasterxml/jackson/databind/cfg/DatabindContextTest.java
index 9da87a0..633f83e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/cfg/DatabindContextTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/cfg/DatabindContextTest.java
@@ -4,7 +4,7 @@
 
 public class DatabindContextTest extends BaseMapTest
 {
-    private final ObjectMapper MAPPER = objectMapper();
+    private final ObjectMapper MAPPER = sharedMapper();
 
     public void testDeserializationContext() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/cfg/DeserializationConfigTest.java b/src/test/java/com/fasterxml/jackson/databind/cfg/DeserializationConfigTest.java
index 5a78e89..d1ac009 100644
--- a/src/test/java/com/fasterxml/jackson/databind/cfg/DeserializationConfigTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/cfg/DeserializationConfigTest.java
@@ -3,7 +3,7 @@
 import java.util.Collections;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.json.JsonReadFeature;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.introspect.ClassIntrospector;
 
@@ -59,13 +59,13 @@
     public void testParserFeatures() throws Exception
     {
         DeserializationConfig config = MAPPER.getDeserializationConfig();
-        assertNotSame(config, config.with(JsonParser.Feature.ALLOW_COMMENTS));
-        assertNotSame(config, config.withFeatures(JsonParser.Feature.ALLOW_COMMENTS,
-                JsonParser.Feature.ALLOW_MISSING_VALUES));
+        assertNotSame(config, config.with(JsonReadFeature.ALLOW_JAVA_COMMENTS));
+        assertNotSame(config, config.withFeatures(JsonReadFeature.ALLOW_JAVA_COMMENTS,
+                JsonReadFeature.ALLOW_MISSING_VALUES));
 
-        assertNotSame(config, config.without(JsonParser.Feature.ALLOW_COMMENTS));
-        assertNotSame(config, config.withoutFeatures(JsonParser.Feature.ALLOW_COMMENTS,
-                JsonParser.Feature.ALLOW_MISSING_VALUES));
+        assertNotSame(config, config.without(JsonReadFeature.ALLOW_JAVA_COMMENTS));
+        assertNotSame(config, config.withoutFeatures(JsonReadFeature.ALLOW_JAVA_COMMENTS,
+                JsonReadFeature.ALLOW_MISSING_VALUES));
     }
 
     public void testFormatFeatures() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/cfg/SerConfigTest.java b/src/test/java/com/fasterxml/jackson/databind/cfg/SerConfigTest.java
index adb3b18..26942fa 100644
--- a/src/test/java/com/fasterxml/jackson/databind/cfg/SerConfigTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/cfg/SerConfigTest.java
@@ -3,9 +3,8 @@
 import java.util.Collections;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.core.JsonFactory;
 import com.fasterxml.jackson.core.JsonGenerator;
-
+import com.fasterxml.jackson.core.json.JsonWriteFeature;
 import com.fasterxml.jackson.databind.*;
 
 public class SerConfigTest extends BaseMapTest
@@ -51,17 +50,12 @@
     public void testGeneratorFeatures() throws Exception
     {
         SerializationConfig config = MAPPER.getSerializationConfig();
-        JsonFactory f = MAPPER.getFactory();
-        assertFalse(config.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII, f));
-        assertNotSame(config, config.with(JsonGenerator.Feature.ESCAPE_NON_ASCII));
-        SerializationConfig newConfig = config.withFeatures(JsonGenerator.Feature.ESCAPE_NON_ASCII,
-                JsonGenerator.Feature.IGNORE_UNKNOWN);
+        assertNotSame(config, config.with(JsonWriteFeature.ESCAPE_NON_ASCII));
+        SerializationConfig newConfig = config.withFeatures(JsonGenerator.Feature.IGNORE_UNKNOWN);
         assertNotSame(config, newConfig);
-        assertTrue(newConfig.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII, f));
 
-        assertNotSame(config, config.without(JsonGenerator.Feature.ESCAPE_NON_ASCII));
-        assertNotSame(config, config.withoutFeatures(JsonGenerator.Feature.ESCAPE_NON_ASCII,
-                JsonGenerator.Feature.IGNORE_UNKNOWN));
+        assertNotSame(config, config.without(JsonWriteFeature.ESCAPE_NON_ASCII));
+        assertNotSame(config, config.withoutFeatures(JsonGenerator.Feature.IGNORE_UNKNOWN));
     }
 
     public void testFormatFeatures() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextAttributeWithDeser.java b/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextAttributeWithDeser.java
index 16491fd..fe9f10a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextAttributeWithDeser.java
+++ b/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextAttributeWithDeser.java
@@ -45,7 +45,7 @@
     /**********************************************************
      */
 
-    final ObjectMapper MAPPER = objectMapper();
+    final ObjectMapper MAPPER = sharedMapper();
     
     public void testSimplePerCall() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextAttributeWithSer.java b/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextAttributeWithSer.java
index 830621e..a6a63d8 100644
--- a/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextAttributeWithSer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextAttributeWithSer.java
@@ -47,7 +47,7 @@
     /**********************************************************
      */
 
-    final ObjectMapper MAPPER = objectMapper();
+    final ObjectMapper MAPPER = sharedMapper();
     
     public void testSimplePerCall() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextualDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextualDeserialization.java
index 19ab6df..1f5825e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextualDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextualDeserialization.java
@@ -14,6 +14,7 @@
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
 import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.databind.module.SimpleModule;
 
 /**
@@ -181,6 +182,12 @@
     /**********************************************************
      */
 
+    private final ObjectMapper ANNOTATED_CTXT_MAPPER = JsonMapper.builder()
+            .addModule(new SimpleModule("test", Version.unknownVersion())
+                    .addDeserializer(StringValue.class, new AnnotatedContextualDeserializer()
+            ))
+            .build();
+    
     public void testSimple() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
@@ -296,12 +303,7 @@
     /**********************************************************
      */
 
-    private ObjectMapper _mapperWithAnnotatedContextual()
-    {
-        ObjectMapper mapper = new ObjectMapper();
-        SimpleModule module = new SimpleModule("test", Version.unknownVersion());
-        module.addDeserializer(StringValue.class, new AnnotatedContextualDeserializer());
-        mapper.registerModule(module);
-        return mapper;
+    private ObjectMapper _mapperWithAnnotatedContextual() {
+        return ANNOTATED_CTXT_MAPPER;
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextualSerialization.java b/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextualSerialization.java
index b1fd92b..6b57205 100644
--- a/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextualSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/contextual/TestContextualSerialization.java
@@ -20,15 +20,8 @@
  */
 public class TestContextualSerialization extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Helper classes
-    /**********************************************************
-     */
-
-    /* NOTE: important; MUST be considered a 'Jackson' annotation to be seen
-     * (or recognized otherwise via AnnotationIntrospect.isHandled())
-     */
+    // NOTE: important; MUST be considered a 'Jackson' annotation to be seen
+    // (or recognized otherwise via AnnotationIntrospect.isHandled())
     @Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
     @Retention(RetentionPolicy.RUNTIME)
     @JacksonAnnotation
@@ -166,13 +159,13 @@
         protected int isResolved;
 
         public ContextualAndResolvable() { this(0, 0); }
-        
+
         public ContextualAndResolvable(int resolved, int contextual)
         {
             isContextual = contextual;
             isResolved = resolved;
         }
-        
+
         @Override
         public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException
         {
@@ -191,7 +184,36 @@
             ++isResolved;
         }
     }
+
+    static class AccumulatingContextual
+        extends JsonSerializer<String>
+        implements ContextualSerializer
+    {
+        protected String desc;
     
+        public AccumulatingContextual() { this(""); }
+    
+        public AccumulatingContextual(String newDesc) {
+            desc = newDesc;
+        }
+    
+        @Override
+        public void serialize(String value, JsonGenerator g, SerializerProvider provider) throws IOException
+        {
+            g.writeString(desc+"/"+value);
+        }
+    
+        @Override
+        public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
+                throws JsonMappingException
+        {
+            if (property == null) {
+                return new AccumulatingContextual(desc+"/ROOT");
+            }
+            return new AccumulatingContextual(desc+"/"+property.getName());
+        }
+    }
+
     /*
     /**********************************************************
     /* Unit tests
@@ -270,22 +292,35 @@
         assertEquals("{\"value\":\"prefix->abc\"}", mapper.writeValueAsString(bean));
     }
 
-    /*
-    // [JACKSON-647]: is resolve() called for contextual instances?
     public void testResolveOnContextual() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
         SimpleModule module = new SimpleModule("test", Version.unknownVersion());
         module.addSerializer(String.class, new ContextualAndResolvable());
-        mapper.registerModule(module);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .addModule(module)
+                .build();
         assertEquals(quote("contextual=1,resolved=1"), mapper.writeValueAsString("abc"));
+
+        // also: should NOT be called again
+        assertEquals(quote("contextual=1,resolved=1"), mapper.writeValueAsString("foo"));
     }
 
     public void testContextualArrayElement() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         ContextualArrayElementBean beans = new ContextualArrayElementBean("456");
         assertEquals("{\"beans\":[\"elem->456\"]}", mapper.writeValueAsString(beans));
     }
-    */
+
+    // Test to verify aspects of [databind#2429]
+    public void testRootContextualization2429() throws Exception
+    {
+        ObjectMapper mapper = jsonMapperBuilder()
+                .addModule(new SimpleModule("test", Version.unknownVersion())
+                        .addSerializer(String.class, new AccumulatingContextual()))
+                .build();
+        assertEquals(quote("/ROOT/foo"), mapper.writeValueAsString("foo"));
+        assertEquals(quote("/ROOT/bar"), mapper.writeValueAsString("bar"));
+        assertEquals(quote("/ROOT/3"), mapper.writeValueAsString("3"));
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/NumericConversionTest.java b/src/test/java/com/fasterxml/jackson/databind/convert/NumericConversionTest.java
index 287ad4b..03f79cf 100644
--- a/src/test/java/com/fasterxml/jackson/databind/convert/NumericConversionTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/NumericConversionTest.java
@@ -5,7 +5,7 @@
 
 public class NumericConversionTest extends BaseMapTest
 {
-    private final ObjectMapper MAPPER = objectMapper();
+    private final ObjectMapper MAPPER = sharedMapper();
     private final ObjectReader R = MAPPER.reader().without(DeserializationFeature.ACCEPT_FLOAT_AS_INT);
 
     public void testDoubleToInt() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java b/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java
index ac08d94..d0cb4ec 100644
--- a/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/TestBeanConversions.java
@@ -217,19 +217,10 @@
      */
     public void testIssue11() throws Exception
     {
-        // First the expected use case, Node specification
-        ObjectNode root = MAPPER.createObjectNode();
-        JsonNode n = root;
-        ObjectNode ob2 = MAPPER.convertValue(n, ObjectNode.class);
-        assertSame(root, ob2);
-
-        JsonNode n2 = MAPPER.convertValue(n, JsonNode.class);
-        assertSame(root, n2);
-        
         // then some other no-op conversions
-        String STR = "test";
-        CharSequence seq = MAPPER.convertValue(STR, CharSequence.class);
-        assertSame(STR, seq);
+        StringBuilder SB = new StringBuilder("test");
+        CharSequence seq = MAPPER.convertValue(SB, CharSequence.class);
+        assertNotSame(SB, seq);
 
         // and then something that should NOT use short-cut
         Leaf l = new Leaf(13);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/PropertyAliasTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/PropertyAliasTest.java
index 3cc17ff..982a37f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/PropertyAliasTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/PropertyAliasTest.java
@@ -30,6 +30,22 @@
         }
     }
 
+    static class AliasBean2378 {
+        String partitionId;
+        String _id;
+
+        private AliasBean2378(boolean bogus, String partId, String userId) {
+            partitionId = partId;
+            _id = userId;
+        }
+
+        @JsonCreator
+        public static AliasBean2378 create(@JsonProperty("partitionId") String partId,
+                @JsonProperty("id") @JsonAlias("userId") String userId) {
+            return new AliasBean2378(false, partId, userId);
+        }
+    }
+
     static class PolyWrapperForAlias {
         @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
                 include = JsonTypeInfo.As.WRAPPER_ARRAY)
@@ -42,7 +58,7 @@
         public PolyWrapperForAlias(Object v) { value = v; }
     }
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     // [databind#1029]
     public void testSimpleAliases() throws Exception
@@ -81,4 +97,14 @@
         assertEquals("Bob", bean.name);
         assertEquals(17, bean._a);
     }
+
+    // [databind#2378]
+    public void testAliasInFactoryMethod() throws Exception
+    {
+        AliasBean2378 bean = MAPPER.readValue(aposToQuotes(
+                "{'partitionId' : 'a', 'userId' : '123'}"
+                ), AliasBean2378.class);
+        assertEquals("a", bean.partitionId);
+        assertEquals("123", bean._id);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyDeser1805Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyDeser1805Test.java
index a8f68d0..7741337 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyDeser1805Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyDeser1805Test.java
@@ -48,7 +48,7 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     public void testReadOnly1382() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestBasicAnnotations.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestBasicAnnotations.java
index 4796e40..259ab40 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestBasicAnnotations.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestBasicAnnotations.java
@@ -195,8 +195,9 @@
         AnnoBean bean = MAPPER.readValue("{ \"y\" : 0 }", AnnoBean.class);
         assertEquals(0, bean.value);
 
-        ObjectMapper m = new ObjectMapper();
-        m.configure(MapperFeature.USE_ANNOTATIONS, false);
+        ObjectMapper m = jsonMapperBuilder()
+                .configure(MapperFeature.USE_ANNOTATIONS, false)
+                .build();
         // without annotations, should default to default bean-based name...
         bean = m.readValue("{ \"x\" : 0 }", AnnoBean.class);
         assertEquals(0, bean.value);
@@ -207,16 +208,18 @@
         ObjectMapper m = new ObjectMapper();
         assertEquals(Alpha.B, m.readValue(quote("B"), Alpha.class));
 
-        m = new ObjectMapper();
-        m.configure(MapperFeature.USE_ANNOTATIONS, false);
+        m = jsonMapperBuilder()
+                .configure(MapperFeature.USE_ANNOTATIONS, false)
+                .build();
         // should still use the basic name handling here
         assertEquals(Alpha.B, m.readValue(quote("B"), Alpha.class));
     }
 
     public void testNoAccessOverrides() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS);
+        ObjectMapper m = jsonMapperBuilder()
+                .disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS)
+                .build();
         SimpleBean bean = m.readValue("{\"x\":1,\"y\":2}", SimpleBean.class);
         assertEquals(1, bean.x);
         assertEquals(2, bean.y);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestCustomDeserializers.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestCustomDeserializers.java
index f85d995..e5ae7a0 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestCustomDeserializers.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestCustomDeserializers.java
@@ -13,6 +13,7 @@
 import com.fasterxml.jackson.databind.annotation.*;
 import com.fasterxml.jackson.databind.deser.std.*;
 import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.util.StdConverter;
 
 /**
@@ -22,12 +23,6 @@
 public class TestCustomDeserializers
     extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Helper classes
-    /**********************************************************
-     */
-
     static class DummyDeserializer<T>
         extends StdDeserializer<T>
     {
@@ -307,6 +302,16 @@
         }
     }
 
+    static class MyNodeDeserializer extends StdDeserializer<Object> {
+        public MyNodeDeserializer() { super(Object.class); }
+
+        @Override
+        public Object deserialize(JsonParser p, DeserializationContext ctxt)
+                throws IOException {
+            return ctxt.readTree(p);
+        }
+    }
+
     /*
     /**********************************************************
     /* Unit tests
@@ -456,4 +461,41 @@
         String str = mapper.readValue(quote("foo"), String.class);
         assertEquals("MY:foo", str);
     }
+
+    // [databind#2392]
+    public void testModifyingCustomDeserializer() throws Exception
+    {
+        ObjectMapper mapper = jsonMapperBuilder()
+                .addModule(new SimpleModule()
+                        .setDeserializerModifier(new BeanDeserializerModifier() {
+                            @Override
+                            public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config,
+                                    BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
+                                if (deserializer instanceof DummyDeserializer<?>) {
+                                    return new DummyDeserializer<String>("FOOBAR", String.class);
+                                }
+                                return deserializer;
+                            }
+                        })
+                        .addDeserializer(String.class, new DummyDeserializer<String>("dummy", String.class))
+                        ).build();
+        String str = mapper.readValue(quote("foo"), String.class);
+        assertEquals("FOOBAR", str);
+    }
+
+    // [databind#2452]
+    public void testCustomSerializerWithReadTree() throws Exception
+    {
+        ObjectMapper mapper = jsonMapperBuilder()
+                .addModule(new SimpleModule()
+                        .addDeserializer(Object.class, new MyNodeDeserializer())
+                        )
+                .build();
+        ObjectWrapper w = mapper.readValue(aposToQuotes("[ 1, { 'a' : 3}, 123 ] "),
+                ObjectWrapper.class);
+        assertEquals(ArrayNode.class, w.getObject().getClass());
+        JsonNode n = (JsonNode) w.getObject();
+        assertEquals(3, n.size());
+        assertEquals(123, n.get(2).intValue());
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestJacksonTypes.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestJacksonTypes.java
index 5ff6ca7..c6d3931 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestJacksonTypes.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestJacksonTypes.java
@@ -13,14 +13,15 @@
 public class TestJacksonTypes
     extends com.fasterxml.jackson.databind.BaseMapTest
 {
+    private final ObjectMapper MAPPER = sharedMapper();
+
     public void testJsonLocation() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
         // note: source reference is untyped, only String guaranteed to work
         JsonLocation loc = new JsonLocation("whatever",  -1, -1, 100, 13);
         // Let's use serializer here; goal is round-tripping
-        String ser = serializeAsString(m, loc);
-        JsonLocation result = m.readValue(ser, JsonLocation.class);
+        String ser = MAPPER.writeValueAsString(loc);
+        JsonLocation result = MAPPER.readValue(ser, JsonLocation.class);
         assertNotNull(result);
         assertEquals(loc.getSourceRef(), result.getSourceRef());
         assertEquals(loc.getByteOffset(), result.getByteOffset());
@@ -35,21 +36,33 @@
         JsonLocation loc = new JsonLocation(null,  -1, -1, 100, 13);
         assertTrue(loc.equals(loc));
         assertFalse(loc.equals(null));
-        assertFalse(loc.equals("abx"));
+        final Object value = "abx";
+        assertFalse(loc.equals(value));
 
         // should we check it's not 0?
         loc.hashCode();
     }
 
+    public void testJavaType() throws Exception
+    {
+        TypeFactory tf = TypeFactory.defaultInstance();
+        // first simple type:
+        String json = MAPPER.writeValueAsString(tf.constructType(String.class));
+        assertEquals(quote(java.lang.String.class.getName()), json);
+        // and back
+        JavaType t = MAPPER.readValue(json, JavaType.class);
+        assertNotNull(t);
+        assertEquals(String.class, t.getRawClass());
+    }
+
     /**
      * Verify that {@link TokenBuffer} can be properly deserialized
      * automatically, using the "standard" JSON sample document
      */
     public void testTokenBufferWithSample() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
         // First, try standard sample doc:
-        TokenBuffer result = m.readValue(SAMPLE_DOC_JSON_SPEC, TokenBuffer.class);
+        TokenBuffer result = MAPPER.readValue(SAMPLE_DOC_JSON_SPEC, TokenBuffer.class);
         verifyJsonSpecSampleDoc(result.asParser(), true);
         result.close();
     }
@@ -57,13 +70,12 @@
     @SuppressWarnings("resource")
     public void testTokenBufferWithSequence() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
         // and then sequence of other things
         JsonParser jp = createParserUsingReader("[ 32, [ 1 ], \"abc\", { \"a\" : true } ]");
         assertToken(JsonToken.START_ARRAY, jp.nextToken());
 
         assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
-        TokenBuffer buf = m.readValue(jp, TokenBuffer.class);
+        TokenBuffer buf = MAPPER.readValue(jp, TokenBuffer.class);
 
         // check manually...
         JsonParser bufParser = buf.asParser();
@@ -72,7 +84,7 @@
         assertNull(bufParser.nextToken());
 
         // then bind to another
-        buf = m.readValue(jp, TokenBuffer.class);
+        buf = MAPPER.readValue(jp, TokenBuffer.class);
         bufParser = buf.asParser();
         assertToken(JsonToken.START_ARRAY, bufParser.nextToken());
         assertToken(JsonToken.VALUE_NUMBER_INT, bufParser.nextToken());
@@ -81,13 +93,13 @@
         assertNull(bufParser.nextToken());
 
         // third one, with automatic binding
-        buf = m.readValue(jp, TokenBuffer.class);
-        String str = m.readValue(buf.asParser(), String.class);
+        buf = MAPPER.readValue(jp, TokenBuffer.class);
+        String str = MAPPER.readValue(buf.asParser(), String.class);
         assertEquals("abc", str);
 
         // and ditto for last one
-        buf = m.readValue(jp, TokenBuffer.class);
-        Map<?,?> map = m.readValue(buf.asParser(), Map.class);
+        buf = MAPPER.readValue(jp, TokenBuffer.class);
+        Map<?,?> map = MAPPER.readValue(buf.asParser(), Map.class);
         assertEquals(1, map.size());
         assertEquals(Boolean.TRUE, map.get("a"));
         
@@ -95,16 +107,42 @@
         assertNull(jp.nextToken());
     }
 
-    public void testJavaType() throws Exception
+    // 10k does it, 5k not, but use bit higher values just in case
+    private final static int RECURSION_2398 = 25000;
+
+    // [databind#2398]
+    public void testDeeplyNestedArrays() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        TypeFactory tf = TypeFactory.defaultInstance();
-        // first simple type:
-        String json = mapper.writeValueAsString(tf.constructType(String.class));
-        assertEquals(quote(java.lang.String.class.getName()), json);
-        // and back
-        JavaType t = mapper.readValue(json, JavaType.class);
-        assertNotNull(t);
-        assertEquals(String.class, t.getRawClass());
+        try (JsonParser p = MAPPER.tokenStreamFactory().createParser(_createNested(RECURSION_2398 * 2,
+                "[", " 123 ", "]"))) {
+            p.nextToken();
+            TokenBuffer b = new TokenBuffer(p);
+            b.copyCurrentStructure(p);
+            b.close();
+        }
+    }
+
+    public void testDeeplyNestedObjects() throws Exception
+    {
+        try (JsonParser p = MAPPER.tokenStreamFactory().createParser(_createNested(RECURSION_2398,
+                "{\"a\":", "42", "}"))) {
+            p.nextToken();
+            TokenBuffer b = new TokenBuffer(p);
+            b.copyCurrentStructure(p);
+            b.close();
+        }
+    }
+
+    private String _createNested(int nesting, String open, String middle, String close) 
+    {
+        StringBuilder sb = new StringBuilder(2 * nesting);
+        for (int i = 0; i < nesting; ++i) {
+            sb.append(open);
+        }
+        sb.append(middle);
+        for (int i = 0; i < nesting; ++i) {
+            sb.append(close);
+        }
+        return sb.toString();
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestSetterlessProperties.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestSetterlessProperties.java
index b83eb40..a30767c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestSetterlessProperties.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestSetterlessProperties.java
@@ -68,7 +68,9 @@
         ObjectMapper m = new ObjectMapper();
         // by default, it should be enabled
         assertTrue(m.isEnabled(MapperFeature.USE_GETTERS_AS_SETTERS));
-        m.configure(MapperFeature.USE_GETTERS_AS_SETTERS, false);
+        m = jsonMapperBuilder()
+                .configure(MapperFeature.USE_GETTERS_AS_SETTERS, false)
+                .build();
         assertFalse(m.isEnabled(MapperFeature.USE_GETTERS_AS_SETTERS));
 
         // and now this should fail
@@ -98,8 +100,9 @@
     public void testSimpleSetterlessMapFailure()
         throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.configure(MapperFeature.USE_GETTERS_AS_SETTERS, false);
+        ObjectMapper m = jsonMapperBuilder()
+                .configure(MapperFeature.USE_GETTERS_AS_SETTERS, false)
+                .build();
         // so this should fail now without a setter
         try {
             m.readValue
@@ -110,13 +113,14 @@
         }
     }
 
-    /* Test for [JACKSON-328], precedence of "getter-as-setter" (for Lists) versus
+    /* Test precedence of "getter-as-setter" (for Lists) versus
      * field for same property.
      */
     public void testSetterlessPrecedence() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.configure(MapperFeature.USE_GETTERS_AS_SETTERS, true);
+        ObjectMapper m = jsonMapperBuilder()
+                .configure(MapperFeature.USE_GETTERS_AS_SETTERS, true)
+                .build();
         Dual value = m.readValue("{\"list\":[1,2,3]}, valueType)", Dual.class);
         assertNotNull(value);
         assertEquals(3, value.values.size());
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java
index e14ad18..3f016fd 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java
@@ -190,6 +190,17 @@
         }
     }
 
+    // for [databind#2553]
+    @SuppressWarnings("rawtypes")
+    static class List2553 {
+        @JsonDeserialize(contentAs = Item2553.class)
+        public List items;
+    }
+
+    static class Item2553 {
+        public String name;
+    }
+
     final static class InvalidContentClass
     {
         /* Such annotation not allowed, since it makes no sense;
@@ -230,10 +241,11 @@
     /**********************************************************
      */
 
+    private final ObjectMapper MAPPER = newJsonMapper();
+
     public void testOverrideClassValid() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        CollectionHolder result = m.readValue
+        CollectionHolder result = MAPPER.readValue
             ("{ \"strings\" : [ \"test\" ] }", CollectionHolder.class);
 
         Collection<String> strs = result._strings;
@@ -244,9 +256,8 @@
 
     public void testOverrideMapValid() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
         // note: expecting conversion from number to String, as well
-        MapHolder result = m.readValue
+        MapHolder result = MAPPER.readValue
             ("{ \"strings\" :  { \"a\" : 3 } }", MapHolder.class);
 
         Map<String,String> strs = result._data;
@@ -258,8 +269,7 @@
 
     public void testOverrideArrayClass() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        ArrayHolder result = m.readValue
+        ArrayHolder result = MAPPER.readValue
             ("{ \"strings\" : [ \"test\" ] }", ArrayHolder.class);
 
         String[] strs = result._strings;
@@ -272,7 +282,7 @@
     {
         // should fail due to incompatible Annotation
         try {
-            BrokenCollectionHolder result = new ObjectMapper().readValue
+            BrokenCollectionHolder result = MAPPER.readValue
                 ("{ \"strings\" : [ ] }", BrokenCollectionHolder.class);
             fail("Expected a failure, but got results: "+result);
         } catch (JsonMappingException jme) {
@@ -288,21 +298,21 @@
 
     public void testRootInterfaceAs() throws Exception
     {
-        RootInterface value = new ObjectMapper().readValue("{\"a\":\"abc\" }", RootInterface.class);
+        RootInterface value = MAPPER.readValue("{\"a\":\"abc\" }", RootInterface.class);
         assertTrue(value instanceof RootInterfaceImpl);
         assertEquals("abc", value.getA());
     }
 
     public void testRootInterfaceUsing() throws Exception
     {
-        RootString value = new ObjectMapper().readValue("\"xxx\"", RootString.class);
+        RootString value = MAPPER.readValue("\"xxx\"", RootString.class);
         assertTrue(value instanceof RootString);
         assertEquals("xxx", value.contents());
     }
 
     public void testRootListAs() throws Exception
     {
-        RootMap value = new ObjectMapper().readValue("{\"a\":\"b\"}", RootMap.class);
+        RootMap value = MAPPER.readValue("{\"a\":\"b\"}", RootMap.class);
         assertEquals(1, value.size());
         Object v2 = value.get("a");
         assertEquals(RootStringImpl.class, v2.getClass());
@@ -311,7 +321,7 @@
 
     public void testRootMapAs() throws Exception
     {
-        RootList value = new ObjectMapper().readValue("[ \"c\" ]", RootList.class);
+        RootList value = MAPPER.readValue("[ \"c\" ]", RootList.class);
         assertEquals(1, value.size());
         Object v2 = value.get(0);
         assertEquals(RootStringImpl.class, v2.getClass());
@@ -327,8 +337,7 @@
     @SuppressWarnings("unchecked")
 	public void testOverrideKeyClassValid() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        MapKeyHolder result = m.readValue("{ \"map\" : { \"xxx\" : \"yyy\" } }", MapKeyHolder.class);
+        MapKeyHolder result = MAPPER.readValue("{ \"map\" : { \"xxx\" : \"yyy\" } }", MapKeyHolder.class);
         Map<StringWrapper, String> map = (Map<StringWrapper,String>)(Map<?,?>)result._map;
         assertEquals(1, map.size());
         Map.Entry<StringWrapper, String> en = map.entrySet().iterator().next();
@@ -343,7 +352,7 @@
     {
         // should fail due to incompatible Annotation
         try {
-            BrokenMapKeyHolder result = new ObjectMapper().readValue
+            BrokenMapKeyHolder result = MAPPER.readValue
                 ("{ \"123\" : \"xxx\" }", BrokenMapKeyHolder.class);
             fail("Expected a failure, but got results: "+result);
         } catch (JsonMappingException jme) {
@@ -358,10 +367,9 @@
      */
 
     @SuppressWarnings("unchecked")
-	public void testOverrideContentClassValid() throws Exception
+    public void testOverrideContentClassValid() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        ListContentHolder result = m.readValue("{ \"list\" : [ \"abc\" ] }", ListContentHolder.class);
+        ListContentHolder result = MAPPER.readValue("{ \"list\" : [ \"abc\" ] }", ListContentHolder.class);
         List<StringWrapper> list = (List<StringWrapper>)result._list;
         assertEquals(1, list.size());
         Object value = list.get(0);
@@ -371,8 +379,7 @@
 
     public void testOverrideArrayContents() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        ArrayContentHolder result = m.readValue("{ \"data\" : [ 1, 2, 3 ] }",
+        ArrayContentHolder result = MAPPER.readValue("{ \"data\" : [ 1, 2, 3 ] }",
                                                 ArrayContentHolder.class);
         Object[] data = result._data;
         assertEquals(3, data.length);
@@ -384,8 +391,7 @@
 
     public void testOverrideMapContents() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        MapContentHolder result = m.readValue("{ \"map\" : { \"a\" : 9 } }",
+        MapContentHolder result = MAPPER.readValue("{ \"map\" : { \"a\" : 9 } }",
                                                 MapContentHolder.class);
         Map<Object,Object> map = result._map;
         assertEquals(1, map.size());
@@ -393,4 +399,14 @@
         assertEquals(Integer.class, ob.getClass());
         assertEquals(Integer.valueOf(9), ob);
     }
+
+    // [databind#2553]
+    public void testRawListTypeContentAs() throws Exception
+    {
+        List2553 list =  MAPPER.readValue("{\"items\": [{\"name\":\"item1\"}]}", List2553.class);
+        assertEquals(1, list.items.size());
+        Object value = list.items.get(0);
+        assertEquals(Item2553.class, value.getClass());
+        assertEquals("item1", ((Item2553) value).name);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderSimpleTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderSimpleTest.java
index 7644dc4..ddef4b2 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderSimpleTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderSimpleTest.java
@@ -216,10 +216,11 @@
     {
         public int x;
         private Map<String,Object> stuff = new HashMap<String,Object>();
-        
-        public ValueBuilder822 withX(int x0) {
+
+        // And tweaked slightly for [databind#2415]
+        @JsonCreator
+        public ValueBuilder822(@JsonProperty("x") int x0) {
             this.x = x0;
-            return this;
         }
 
         @JsonAnySetter
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/ArrayDelegatorCreatorForCollectionTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/ArrayDelegatorCreatorForCollectionTest.java
index 62e4d63..34c7da6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/ArrayDelegatorCreatorForCollectionTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/ArrayDelegatorCreatorForCollectionTest.java
@@ -6,6 +6,7 @@
 import com.fasterxml.jackson.annotation.*;
 
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 // for [databind#1392] (regression in 2.7 due to separation of array-delegating creator)
 public class ArrayDelegatorCreatorForCollectionTest extends BaseMapTest
@@ -22,7 +23,8 @@
         ObjectMapper mapper = new ObjectMapper();
         Class<?> unmodSetType = Collections.unmodifiableSet(Collections.<String>emptySet()).getClass();
         mapper.addMixIn(unmodSetType, UnmodifiableSetMixin.class);
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+        mapper.activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
 
         final String EXPECTED_JSON = "[\""+unmodSetType.getName()+"\",[]]";
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/CreatorPropertiesTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/CreatorPropertiesTest.java
index 0e375dd..1f88381 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/CreatorPropertiesTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/CreatorPropertiesTest.java
@@ -96,8 +96,9 @@
         assertEquals(6, result.y);
 
         // but change if configuration changed
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.disable(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .disable(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES)
+                .build();
         // in which case fields are set directly:
         result = mapper.readValue(JSON, Lombok1371Bean.class);
         assertEquals(3, result.x);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/CreatorWithNamingStrategyTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/CreatorWithNamingStrategyTest.java
index 83f5970..45596bf 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/CreatorWithNamingStrategyTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/CreatorWithNamingStrategyTest.java
@@ -37,7 +37,7 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper()
+    private final ObjectMapper MAPPER = newJsonMapper()
             .setAnnotationIntrospector(new MyParamIntrospector())
             .setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
             ;
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreator1804Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreator1804Test.java
deleted file mode 100644
index 04e0423..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreator1804Test.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.fasterxml.jackson.databind.deser.creators;
-
-import java.util.List;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonValue;
-import com.fasterxml.jackson.databind.BaseMapTest;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-public class DelegatingArrayCreator1804Test extends BaseMapTest
-{
-    public static class MyTypeImpl extends MyType {
-        private final List<Integer> values;
-
-        MyTypeImpl(List<Integer> values) {
-            this.values = values;
-        }
-
-        @Override
-        public List<Integer> getValues() {
-            return values;
-        }
-    }
-
-    static abstract class MyType {
-        @JsonValue
-        public abstract List<Integer> getValues();
-
-        @JsonCreator(mode=JsonCreator.Mode.DELEGATING)
-        public static MyType of(List<Integer> values) {
-            return new MyTypeImpl(values);
-        }
-    }
-
-
-    public void testDelegatingArray1804() throws Exception {
-        ObjectMapper mapper = new ObjectMapper();
-        MyType thing = mapper.readValue("[]", MyType.class);
-        assertNotNull(thing);
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreator2324Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreator2324Test.java
deleted file mode 100644
index 18882cb..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreator2324Test.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.fasterxml.jackson.databind.deser.creators;
-
-import java.util.AbstractCollection;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-
-// for [databind#2324]
-public class DelegatingArrayCreator2324Test extends BaseMapTest
-{
-    @JsonDeserialize(as=ImmutableBag.class)
-    public interface Bag<T> extends Collection<T> { }
-
-    public static class ImmutableBag<T> extends AbstractCollection<T> implements Bag<T>  {
-        @Override
-        public Iterator<T> iterator() { return elements.iterator(); }
-
-        @Override
-        public int size() { return elements.size(); }
-
-        @JsonCreator(mode=JsonCreator.Mode.DELEGATING)
-        private ImmutableBag(Collection<T> elements ) {
-            this.elements = Collections.unmodifiableCollection(elements);
-        }
-
-        private final Collection<T> elements;
-    }
-
-    static class Value {
-        public String value;
-
-        public Value(String v) { value = v; }
-
-        @Override
-        public boolean equals(Object o) {
-            return value.equals(((Value) o).value);
-        }
-    }
-
-    static class WithBagOfStrings {
-        public Bag<String> getStrings() { return this.bagOfStrings; }
-        public void setStrings(Bag<String> bagOfStrings) { this.bagOfStrings = bagOfStrings; }
-        private Bag<String> bagOfStrings;
-    }
-
-    static class WithBagOfValues {
-        public Bag<Value> getValues() { return this.bagOfValues; }
-        public void setValues(Bag<Value> bagOfValues) { this.bagOfValues = bagOfValues; }
-        private Bag<Value> bagOfValues;
-    }    
-
-    private final ObjectMapper MAPPER = objectMapper();
-
-    public void testDeserializeBagOfStrings() throws Exception {
-        WithBagOfStrings result = MAPPER.readerFor(WithBagOfStrings.class)
-                .readValue("{\"strings\": [ \"a\", \"b\", \"c\"]}");
-        assertEquals(3, result.getStrings().size());
-    }
-
-    public void testDeserializeBagOfPOJOs() throws Exception {
-        WithBagOfValues result = MAPPER.readerFor(WithBagOfValues.class)
-                .readValue("{\"values\": [ \"a\", \"b\", \"c\"]}");
-        assertEquals(3, result.getValues().size());
-        assertEquals(new Value("a"),  result.getValues().iterator().next());
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreatorsTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreatorsTest.java
new file mode 100644
index 0000000..c0ae77c
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreatorsTest.java
@@ -0,0 +1,99 @@
+package com.fasterxml.jackson.databind.deser.creators;
+
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+public class DelegatingArrayCreatorsTest extends BaseMapTest
+{
+    public static class MyTypeImpl extends MyType {
+        private final List<Integer> values;
+
+        MyTypeImpl(List<Integer> values) {
+            this.values = values;
+        }
+
+        @Override
+        public List<Integer> getValues() {
+            return values;
+        }
+    }
+
+    static abstract class MyType {
+        @JsonValue
+        public abstract List<Integer> getValues();
+
+        @JsonCreator(mode=JsonCreator.Mode.DELEGATING)
+        public static MyType of(List<Integer> values) {
+            return new MyTypeImpl(values);
+        }
+    }
+
+    @JsonDeserialize(as=ImmutableBag2324.class)
+    public interface Bag2324<T> extends Collection<T> { }
+
+    public static class ImmutableBag2324<T> extends AbstractCollection<T> implements Bag2324<T>  {
+        @Override
+        public Iterator<T> iterator() { return elements.iterator(); }
+
+        @Override
+        public int size() { return elements.size(); }
+
+        @JsonCreator(mode=JsonCreator.Mode.DELEGATING)
+        private ImmutableBag2324(Collection<T> elements ) {
+            this.elements = Collections.unmodifiableCollection(elements);
+        }
+
+        private final Collection<T> elements;
+    }
+
+    static class Value2324 {
+        public String value;
+
+        public Value2324(String v) { value = v; }
+
+        @Override
+        public boolean equals(Object o) {
+            return value.equals(((Value2324) o).value);
+        }
+    }
+
+    static class WithBagOfStrings2324 {
+        public Bag2324<String> getStrings() { return this.bagOfStrings; }
+        public void setStrings(Bag2324<String> bagOfStrings) { this.bagOfStrings = bagOfStrings; }
+        private Bag2324<String> bagOfStrings;
+    }
+
+    static class WithBagOfValues2324 {
+        public Bag2324<Value2324> getValues() { return this.bagOfValues; }
+        public void setValues(Bag2324<Value2324> bagOfValues) { this.bagOfValues = bagOfValues; }
+        private Bag2324<Value2324> bagOfValues;
+    }
+
+    private final ObjectMapper MAPPER = sharedMapper();
+
+    // [databind#1804]
+    public void testDelegatingArray1804() throws Exception {
+        MyType thing = MAPPER.readValue("[]", MyType.class);
+        assertNotNull(thing);
+    }
+
+    // [databind#2324]
+    public void testDeserializeBagOfStrings() throws Exception {
+        WithBagOfStrings2324 result = MAPPER.readerFor(WithBagOfStrings2324.class)
+                .readValue("{\"strings\": [ \"a\", \"b\", \"c\"]}");
+        assertEquals(3, result.getStrings().size());
+    }
+
+    // [databind#2324]
+    public void testDeserializeBagOfPOJOs() throws Exception {
+        WithBagOfValues2324 result = MAPPER.readerFor(WithBagOfValues2324.class)
+                .readValue("{\"values\": [ \"a\", \"b\", \"c\"]}");
+        assertEquals(3, result.getValues().size());
+        assertEquals(new Value2324("a"),  result.getValues().iterator().next());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingCreatorAnnotations2016Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingCreatorAnnotations2016Test.java
index e892918..e603bb1 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingCreatorAnnotations2016Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingCreatorAnnotations2016Test.java
@@ -37,7 +37,7 @@
     /**********************************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     // [databind#2016]
     public void testDelegatingWithAs() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingCreatorAnnotations2021Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingCreatorAnnotations2021Test.java
index aa6eaa1..35ad729 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingCreatorAnnotations2021Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingCreatorAnnotations2021Test.java
@@ -47,7 +47,7 @@
     /**********************************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     // [databind#2021]
     public void testCustomDeserForDelegating() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/ImplicitNameMatch792Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/ImplicitNameMatch792Test.java
index 8eafb11..3946e81 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/ImplicitNameMatch792Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/ImplicitNameMatch792Test.java
@@ -89,7 +89,7 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = objectMapper();
+    private final ObjectMapper MAPPER = sharedMapper();
     
     public void testBindingOfImplicitCreatorNames() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/InnerClassCreatorTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/InnerClassCreatorTest.java
index eeb733e..c9f10a0 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/InnerClassCreatorTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/InnerClassCreatorTest.java
@@ -3,6 +3,7 @@
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
 
 // For [databind#1501], [databind#1502], [databind#1503]; mostly to
 // test that for non-static inner classes constructors are ignored
@@ -63,10 +64,10 @@
         try {
             MAPPER.readValue(ser, Something1501.class);
             fail("Should not pass");
-        } catch (JsonMappingException e) {
+        } catch (MismatchedInputException e) {
             verifyException(e, "Cannot construct instance");
             verifyException(e, "InnerSomething1501");
-            verifyException(e, "can only instantiate non-static inner class by using default");
+            verifyException(e, "non-static inner classes like this can only by instantiated using default");
         }
     }    
 
@@ -76,10 +77,10 @@
         try {
             MAPPER.readValue(ser, Something1502.class);
             fail("Should not pass");
-        } catch (JsonMappingException e) {
+        } catch (MismatchedInputException e) {
             verifyException(e, "Cannot construct instance");
             verifyException(e, "InnerSomething1502");
-            verifyException(e, "can only instantiate non-static inner class by using default");
+            verifyException(e, "non-static inner classes like this can only by instantiated using default");
         }
     }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreatorNullPrimitives.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreatorNullPrimitives.java
new file mode 100644
index 0000000..1a2d5e7
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreatorNullPrimitives.java
@@ -0,0 +1,73 @@
+package com.fasterxml.jackson.databind.deser.creators;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+
+import java.io.IOException;
+
+public class TestCreatorNullPrimitives extends BaseMapTest {
+
+    // [databind#2101]
+    static class JsonEntity {
+        protected final int x;
+        protected final int y;
+
+        @JsonCreator
+        private JsonEntity(@JsonProperty("x") int x, @JsonProperty("y") int y) {
+            this.x = x;
+            this.y = y;
+        }
+    }
+
+    static class NestedJsonEntity {
+        protected final JsonEntity entity;
+
+        @JsonCreator
+        private NestedJsonEntity(@JsonProperty("entity") JsonEntity entity) {
+            this.entity = entity;
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Unit tests
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = sharedMapper();
+
+    // [databind#2101]: ensure that the property is included in the path
+    public void testCreatorNullPrimitive() throws IOException {
+        final ObjectReader r = MAPPER.readerFor(JsonEntity.class)
+            .with(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
+        String json = aposToQuotes("{'x': 2}");
+        try {
+            r.readValue(json);
+            fail("Should not have succeeded");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Cannot map `null` into type int");
+            assertEquals(1, e.getPath().size());
+            assertEquals("y", e.getPath().get(0).getFieldName());
+        }
+    }
+
+    public void testCreatorNullPrimitiveInNestedObject() throws IOException {
+        final ObjectReader r = MAPPER.readerFor(NestedJsonEntity.class)
+                .with(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
+        String json = aposToQuotes("{ 'entity': {'x': 2}}");
+        try {
+            r.readValue(json);
+            fail("Should not have succeeded");
+        } catch (JsonMappingException e) {
+            verifyException(e, "Cannot map `null` into type int");
+            assertEquals(2, e.getPath().size());
+            assertEquals("y", e.getPath().get(1).getFieldName());
+            assertEquals("entity", e.getPath().get(0).getFieldName());
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreators.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreators.java
index 07854bc..5b62478 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreators.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreators.java
@@ -315,7 +315,7 @@
     
     public void testSimpleDoubleConstructor() throws Exception
     {
-        Double exp = new Double("0.25");
+        Double exp = Double.valueOf("0.25");
         DoubleConstructorBean bean = MAPPER.readValue(exp.toString(), DoubleConstructorBean.class);
         assertEquals(exp, bean.d);
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreators2.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreators2.java
index f7b2f86..0269514 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreators2.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreators2.java
@@ -9,6 +9,9 @@
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
+import com.fasterxml.jackson.databind.exc.ValueInstantiationException;
 
 public class TestCreators2 extends BaseMapTest
 {
@@ -190,7 +193,7 @@
         try {
             MAPPER.readValue("{}", BustedCtor.class);
             fail("Expected exception");
-        } catch (JsonMappingException e) {
+        } catch (ValueInstantiationException e) {
             verifyException(e, ": foobar");
             // also: should have nested exception
             Throwable t = e.getCause();
@@ -200,6 +203,8 @@
             assertNotNull(t);
             assertEquals(IllegalArgumentException.class, t.getClass());
             assertEquals("foobar", t.getMessage());
+        } catch (Exception e) {
+            fail("Should have caught ValueInstantiationException, got: "+e);
         }
     }
 
@@ -210,7 +215,6 @@
         assertEquals("abc", new String(test.bytes, "UTF-8"));
     }
 
-    // Test for [JACKSON-372]
     public void testMissingPrimitives() throws Exception
     {
         Primitives p = MAPPER.readValue("{}", Primitives.class);
@@ -238,11 +242,11 @@
         try {
             MAPPER.readValue("{ \"name\":\"foobar\" }", BeanFor438.class);
             fail("Should have failed");
-        } catch (Exception e0) {
+        } catch (JsonMappingException e0) {
             e = e0;
         }
-        if (!(e instanceof JsonMappingException)) {
-            fail("Should have received JsonMappingException, caught "+e.getClass().getName());
+        if (!(e instanceof ValueInstantiationException)) {
+            fail("Should have received ValueInstantiationException, caught "+e.getClass().getName());
         }
         verifyException(e, "don't like that name");
         // Ok: also, let's ensure root cause is directly linked, without other extra wrapping:
@@ -259,7 +263,7 @@
         try {
             MAPPER.readValue("{\"bar\":\"x\"}", BrokenCreatorBean.class);
             fail("Should have caught duplicate creator parameters");
-        } catch (JsonMappingException e) {
+        } catch (InvalidDefinitionException e) {
             verifyException(e, "duplicate creator property \"bar\"");
             verifyException(e, "for type `com.fasterxml.jackson.databind.");
             verifyException(e, "$BrokenCreatorBean`");
@@ -278,7 +282,7 @@
         try {
             MAPPER.readValue(quote("abc"), IgnoredCtor.class);
             fail("Should have caught missing constructor problem");
-        } catch (JsonMappingException e) {
+        } catch (MismatchedInputException e) {
             verifyException(e, "no String-argument constructor/factory method");
         }
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreators3.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreators3.java
index d00030c..e2f505a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreators3.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreators3.java
@@ -131,22 +131,22 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
     
     public void testCreator541() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.disable(
+        ObjectMapper mapper = jsonMapperBuilder()
+                .disable(
                 MapperFeature.AUTO_DETECT_CREATORS,
                 MapperFeature.AUTO_DETECT_FIELDS,
                 MapperFeature.AUTO_DETECT_GETTERS,
                 MapperFeature.AUTO_DETECT_IS_GETTERS,
                 MapperFeature.AUTO_DETECT_SETTERS,
-                MapperFeature.USE_GETTERS_AS_SETTERS
-        );
-        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
-        mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
-        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);  
+                MapperFeature.USE_GETTERS_AS_SETTERS)
+                .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+                .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
+                .serializationInclusion(JsonInclude.Include.NON_NULL)
+        .build();
 
         final String JSON = "{\n"
                 + "    \"foo\": {\n"
@@ -181,7 +181,7 @@
     // [databind#421]
     public void testMultiCtor421() throws Exception
     {
-        final ObjectMapper mapper = newObjectMapper();
+        final ObjectMapper mapper = newJsonMapper();
         mapper.setAnnotationIntrospector(new MyParamIntrospector());
 
         MultiCtor bean = mapper.readValue(aposToQuotes("{'a':'123','b':'foo'}"), MultiCtor.class);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreatorsDelegating.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreatorsDelegating.java
index 85b028f..3c608b6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreatorsDelegating.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreatorsDelegating.java
@@ -4,6 +4,7 @@
 
 import com.fasterxml.jackson.annotation.JacksonInject;
 import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
 
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonToken;
@@ -82,13 +83,39 @@
         }
     }
 
+    // [databind#2353]: allow delegating and properties-based
+    static class SuperToken2353 {
+        public long time;
+        public String username;
+
+        @JsonCreator(mode=JsonCreator.Mode.DELEGATING) // invoked when a string is passed
+        public static SuperToken2353 from(String username) {
+            SuperToken2353 token = new SuperToken2353();
+            token.username = username;
+            token.time = System.currentTimeMillis();
+            return token;
+        }
+
+        @JsonCreator(mode=JsonCreator.Mode.PROPERTIES) // invoked when an object is passed, pre-validating property existence
+        public static SuperToken2353 create(
+                @JsonProperty("name") String username,
+                @JsonProperty("time") long time)
+        {
+            SuperToken2353 token = new SuperToken2353();
+            token.username = username;
+            token.time = time;
+
+            return token;
+        }
+    }
+
     /*
     /**********************************************************
     /* Test methods
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
     
     public void testBooleanDelegate() throws Exception
     {
@@ -179,4 +206,17 @@
         bean = MAPPER.readValue(EMPTY_JSON, MapBean.class);
         assertEquals(0, bean.map.size());
     }
+
+    // [databind#2353]: allow delegating and properties-based
+    public void testMultipleCreators2353() throws Exception
+    {
+        // first, test delegating
+        SuperToken2353 result = MAPPER.readValue(quote("Bob"), SuperToken2353.class);
+        assertEquals("Bob", result.username);
+
+        // and then properties-based
+        result = MAPPER.readValue(aposToQuotes("{'name':'Billy', 'time':123}"), SuperToken2353.class);
+        assertEquals("Billy", result.username);
+        assertEquals(123L, result.time);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestValueInstantiator.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestValueInstantiator.java
index a53ab8f..e575aaf 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestValueInstantiator.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestValueInstantiator.java
@@ -15,8 +15,9 @@
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
 /**
- * Test custom instantiators.
+ * Test custom value instantiators.
  */
+@SuppressWarnings("serial")
 public class TestValueInstantiator extends BaseMapTest
 {
     static class MyBean
@@ -67,14 +68,12 @@
     {
         public String name;
     }
-    
-    @SuppressWarnings("serial")
+
     static class MyList extends ArrayList<Object>
     {
         public MyList(boolean b) { super(); }
     }
 
-    @SuppressWarnings("serial")
     static class MyMap extends HashMap<String,Object>
     {
         public MyMap(boolean b) { super(); }
@@ -128,7 +127,7 @@
         public Object createFromObjectWith(DeserializationContext ctxt, Object[] args) {
             try {
                 Class<?> cls = (Class<?>) args[0];
-                return cls.newInstance();
+                return cls.getDeclaredConstructor().newInstance();
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
@@ -285,8 +284,7 @@
             return new AnnotatedBean("foo", 3);
         }
     }
-    
-    @SuppressWarnings("serial")
+
     static class MyModule extends SimpleModule
     {
         public MyModule(Class<?> cls, ValueInstantiator inst)
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/dos/HugeIntegerCoerceTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/dos/HugeIntegerCoerceTest.java
index 18e580b..78a7f08 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/dos/HugeIntegerCoerceTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/dos/HugeIntegerCoerceTest.java
@@ -1,7 +1,6 @@
 package com.fasterxml.jackson.databind.deser.dos;
 
-import com.fasterxml.jackson.core.*;
-
+import com.fasterxml.jackson.core.exc.InputCoercionException;
 import com.fasterxml.jackson.databind.*;
 
 // for [databind#2157]
@@ -27,7 +26,7 @@
         try {
             /*ABC value =*/ MAPPER.readValue(BIG_POS_INTEGER, ABC.class);
             fail("Should not pass");
-        } catch (JsonParseException e) {
+        } catch (InputCoercionException e) {
             verifyException(e, "out of range of int");
             verifyException(e, "Integer with "+BIG_NUM_LEN+" digits");
         }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/IgnorePropertyOnDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/IgnorePropertyOnDeserTest.java
index 5255d4b..b746253 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/filter/IgnorePropertyOnDeserTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/IgnorePropertyOnDeserTest.java
@@ -41,7 +41,7 @@
     /****************************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     // [databind#1217]
     public void testIgnoreOnProperty1217() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsForContentTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsForContentTest.java
index dfb3d37..66350c0 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsForContentTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsForContentTest.java
@@ -33,20 +33,20 @@
         @JsonSetter // leave with defaults
         public T values;
     }
-    
+
     /*
     /**********************************************************
     /* Test methods, fail-on-null
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     // Tests to verify that we can set default settings for failure
     public void testFailOnNullFromDefaults() throws Exception
     {
         final String JSON = aposToQuotes("{'values':[null]}");
-        TypeReference<?> listType = new TypeReference<NullContentUndefined<List<String>>>() { };
+        TypeReference<NullContentUndefined<List<String>>> listType = new TypeReference<NullContentUndefined<List<String>>>() { };
 
         // by default fine to get nulls
         NullContentUndefined<List<String>> result = MAPPER.readValue(JSON, listType);
@@ -55,17 +55,18 @@
         assertNull(result.values.get(0));
 
         // but not when overridden globally:
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL));
         try {
             mapper.readValue(JSON, listType);
             fail("Should not pass");
         } catch (InvalidNullException e) {
             verifyException(e, "property \"values\"");
+            assertEquals(String.class, e.getTargetType());
         }
 
         // or configured for type:
-        mapper = newObjectMapper();
+        mapper = newJsonMapper();
         mapper.configOverride(List.class)
                 .setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL));
         try {
@@ -73,12 +74,13 @@
             fail("Should not pass");
         } catch (InvalidNullException e) {
             verifyException(e, "property \"values\"");
+            assertEquals(String.class, e.getTargetType());
         }
     }
     
     public void testFailOnNullWithCollections() throws Exception
     {
-        TypeReference<?> typeRef = new TypeReference<NullContentFail<List<Integer>>>() { };
+        TypeReference<NullContentFail<List<Integer>>> typeRef = new TypeReference<NullContentFail<List<Integer>>>() { };
 
         // first, ok if assigning non-null to not-nullable, null for nullable
         NullContentFail<List<Integer>> result = MAPPER.readValue(aposToQuotes("{'nullsOk':[null]}"),
@@ -96,6 +98,7 @@
             fail("Should not pass");
         } catch (InvalidNullException e) {
             verifyException(e, "property \"noNulls\"");
+            assertEquals(Integer.class, e.getTargetType());
         }
 
         // List<String>
@@ -104,6 +107,7 @@
             fail("Should not pass");
         } catch (InvalidNullException e) {
             verifyException(e, "property \"noNulls\"");
+            assertEquals(String.class, e.getTargetType());
         }
     }
 
@@ -116,6 +120,7 @@
             fail("Should not pass");
         } catch (InvalidNullException e) {
             verifyException(e, "property \"noNulls\"");
+            assertEquals(Object.class, e.getTargetType());
         }
 
         // String[]
@@ -124,6 +129,7 @@
             fail("Should not pass");
         } catch (InvalidNullException e) {
             verifyException(e, "property \"noNulls\"");
+            assertEquals(String.class, e.getTargetType());
         }
     }
 
@@ -137,6 +143,7 @@
             fail("Should not pass");
         } catch (InvalidNullException e) {
             verifyException(e, "property \"noNulls\"");
+            assertEquals(Boolean.TYPE, e.getTargetType());
         }
         // int[]
         try {
@@ -144,6 +151,7 @@
             fail("Should not pass");
         } catch (InvalidNullException e) {
             verifyException(e, "property \"noNulls\"");
+            assertEquals(Integer.TYPE, e.getTargetType());
         }
         // double[]
         try {
@@ -151,6 +159,7 @@
             fail("Should not pass");
         } catch (InvalidNullException e) {
             verifyException(e, "property \"noNulls\"");
+            assertEquals(Double.TYPE, e.getTargetType());
         }
     }
 
@@ -163,6 +172,7 @@
             fail("Should not pass");
         } catch (InvalidNullException e) {
             verifyException(e, "property \"noNulls\"");
+            assertEquals(String.class, e.getTargetType());
         }
 
         // Then: EnumMap<Enum,String>
@@ -172,6 +182,7 @@
             fail("Should not pass");
         } catch (InvalidNullException e) {
             verifyException(e, "property \"noNulls\"");
+            assertEquals(String.class, e.getTargetType());
         }
     }
 
@@ -205,17 +216,17 @@
     public void testNullsAsEmptyUsingDefaults() throws Exception
     {
         final String JSON = aposToQuotes("{'values':[null]}");
-        TypeReference<?> listType = new TypeReference<NullContentUndefined<List<Integer>>>() { };
+        TypeReference<NullContentUndefined<List<Integer>>> listType = new TypeReference<NullContentUndefined<List<Integer>>>() { };
 
         // Let's see defaulting in action
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY));
         NullContentUndefined<List<Integer>> result = mapper.readValue(JSON, listType);
         assertEquals(1, result.values.size());
         assertEquals(Integer.valueOf(0), result.values.get(0));
 
         // or configured for type:
-        mapper = newObjectMapper();
+        mapper = newJsonMapper();
         mapper.configOverride(List.class)
                 .setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY));
         result = mapper.readValue(JSON, listType);
@@ -297,16 +308,16 @@
     public void testNullsSkipUsingDefaults() throws Exception
     {
         final String JSON = aposToQuotes("{'values':[null]}");
-        TypeReference<?> listType = new TypeReference<NullContentUndefined<List<Long>>>() { };
+        TypeReference<NullContentUndefined<List<Long>>> listType = new TypeReference<NullContentUndefined<List<Long>>>() { };
 
         // Let's see defaulting in action
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP));
         NullContentUndefined<List<Long>> result = mapper.readValue(JSON, listType);
         assertEquals(0, result.values.size());
 
         // or configured for type:
-        mapper = newObjectMapper();
+        mapper = newJsonMapper();
         mapper.configOverride(List.class)
                 .setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP));
         result = mapper.readValue(JSON, listType);
@@ -317,16 +328,16 @@
     public void testNullsSkipWithOverrides() throws Exception
     {
         final String JSON = aposToQuotes("{'values':[null]}");
-        TypeReference<?> listType = new TypeReference<NullContentSkip<List<Long>>>() { };
+        TypeReference<NullContentSkip<List<Long>>> listType = new TypeReference<NullContentSkip<List<Long>>>() { };
 
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         // defaults call for fail; but POJO specifies "skip"; latter should win
         mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL));
         NullContentSkip<List<Long>> result = mapper.readValue(JSON, listType);
         assertEquals(0, result.values.size());
 
         // ditto for per-type defaults
-        mapper = newObjectMapper();
+        mapper = newJsonMapper();
         mapper.configOverride(List.class)
                 .setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.FAIL));
         result = mapper.readValue(JSON, listType);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsForEnumsTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsForEnumsTest.java
new file mode 100644
index 0000000..9f246e6
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsForEnumsTest.java
@@ -0,0 +1,92 @@
+package com.fasterxml.jackson.databind.deser.filter;
+
+import java.util.EnumMap;
+import java.util.EnumSet;
+
+import com.fasterxml.jackson.annotation.JsonSetter;
+import com.fasterxml.jackson.annotation.Nulls;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class NullConversionsForEnumsTest extends BaseMapTest
+{
+    static class NullValueAsEmpty<T> {
+        @JsonSetter(nulls=Nulls.AS_EMPTY)
+        public T value;
+    }
+
+    static class NullContentAsEmpty<T> {
+        @JsonSetter(contentNulls=Nulls.AS_EMPTY)
+        public T values;
+    }
+
+    static class NullContentSkip<T> {
+        @JsonSetter(contentNulls=Nulls.SKIP)
+        public T values;
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods, for container values as empty
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = newJsonMapper();
+
+    public void testEnumSetAsEmpty() throws Exception
+    {
+        NullValueAsEmpty<EnumSet<ABC>> result = MAPPER.readValue(aposToQuotes("{'value': null }"),
+                new TypeReference<NullValueAsEmpty<EnumSet<ABC>>>() { });
+        assertNotNull(result.value);
+        assertEquals(0, result.value.size());
+    }
+
+    public void testEnumMapAsEmpty() throws Exception
+    {
+        NullValueAsEmpty<EnumMap<ABC, String>> result = MAPPER.readValue(aposToQuotes("{'value': null }"),
+                new TypeReference<NullValueAsEmpty<EnumMap<ABC, String>>>() { });
+        assertNotNull(result.value);
+        assertEquals(0, result.value.size());
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods, for container contents, null as empty
+    /**********************************************************
+     */
+
+    // // NOTE: no "empty" value for Enums, so can't use with EnumSet, only EnumMap
+
+    public void testEnumMapNullsAsEmpty() throws Exception
+    {
+        NullContentAsEmpty<EnumMap<ABC, String>> result = MAPPER.readValue(aposToQuotes("{'values': {'B':null} }"),
+                new TypeReference<NullContentAsEmpty<EnumMap<ABC, String>>>() { });
+        assertNotNull(result.values);
+        assertEquals(1, result.values.size());
+        assertEquals("", result.values.get(ABC.B));
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods, for container contents, skip nulls
+    /**********************************************************
+     */
+
+    
+    public void testEnumSetSkipNulls() throws Exception
+    {
+        NullContentSkip<EnumSet<ABC>> result = MAPPER.readValue(aposToQuotes("{'values': [ null ]}"),
+                new TypeReference<NullContentSkip<EnumSet<ABC>>>() { });
+        assertNotNull(result.values);
+        assertEquals(0, result.values.size());
+    }
+
+    public void testEnumMapSkipNulls() throws Exception
+    {
+        NullContentSkip<EnumMap<ABC, String>> result = MAPPER.readValue(aposToQuotes("{'values': {'B':null} }"),
+                new TypeReference<NullContentSkip<EnumMap<ABC, String>>>() { });
+        assertNotNull(result.values);
+        assertEquals(0, result.values.size());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsGenericTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsGenericTest.java
index 87df5f9..b8d5325 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsGenericTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsGenericTest.java
@@ -39,7 +39,7 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     public void testNullsToEmptyPojo() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsPojoTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsPojoTest.java
index b022fc6..e1b1969 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsPojoTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsPojoTest.java
@@ -43,7 +43,7 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     public void testFailOnNull() throws Exception
     {
@@ -70,7 +70,7 @@
         NullsForString def = MAPPER.readValue(json, NullsForString.class);
         assertNull(def.getName());
         
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.configOverride(String.class)
             .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.FAIL));
         try {
@@ -98,7 +98,7 @@
         NullsForString def = MAPPER.readValue(json, NullsForString.class);
         assertNull(def.getName());
 
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.configOverride(String.class)
             .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
         NullsForString named = mapper.readValue(json, NullsForString.class);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsSkipTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsSkipTest.java
index 9fe93a3..041e6bc 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsSkipTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsSkipTest.java
@@ -52,7 +52,7 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     public void testSkipNullField() throws Exception
     {
@@ -103,7 +103,7 @@
         StringValue result = MAPPER.readValue(json, StringValue.class);
         assertNull(result.value);
 
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.configOverride(String.class)
             .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SKIP));
         result = mapper.readValue(json, StringValue.class);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsViaCreator2458Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsViaCreator2458Test.java
new file mode 100644
index 0000000..5c10c2b
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/NullConversionsViaCreator2458Test.java
@@ -0,0 +1,53 @@
+package com.fasterxml.jackson.databind.deser.filter;
+
+import java.util.List;
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonSetter;
+import com.fasterxml.jackson.annotation.Nulls;
+
+import com.fasterxml.jackson.databind.*;
+
+public class NullConversionsViaCreator2458Test extends BaseMapTest
+{
+    // [databind#2458]
+    static class Pojo {
+        List<String> _value;
+
+        @JsonCreator
+        public Pojo(@JsonProperty("value") List<String> v) {
+            this._value = Objects.requireNonNull(v, "value");
+        }
+
+        protected Pojo() { }
+
+        public List<String> value() {
+            return _value;
+        }
+
+        public void setOther(List<String> v) { }
+    }
+
+    private final ObjectMapper MAPPER_WITH_AS_EMPTY = jsonMapperBuilder()
+            .defaultSetterInfo(JsonSetter.Value.construct(Nulls.AS_EMPTY,
+                    Nulls.AS_EMPTY))
+            .build();
+
+    // [databind#2458]
+    public void testMissingToEmptyViaCreator() throws Exception {
+        Pojo pojo = MAPPER_WITH_AS_EMPTY.readValue("{}", Pojo.class);
+        assertNotNull(pojo);
+        assertNotNull(pojo.value());
+        assertEquals(0, pojo.value().size());
+    }
+
+    // [databind#2458]
+    public void testNullToEmptyViaCreator() throws Exception {
+        Pojo pojo = MAPPER_WITH_AS_EMPTY.readValue("{\"value\":null}", Pojo.class);
+        assertNotNull(pojo);
+        assertNotNull(pojo.value());
+        assertEquals(0, pojo.value().size());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerLocation1440Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerLocation1440Test.java
index 14464e7..01413b4 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerLocation1440Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerLocation1440Test.java
@@ -125,7 +125,7 @@
 +"'invalid_4': 'target_invalid_4','status': 'target_status','context': 'target_context'}}"
 );
 
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
         final DeserializationProblemLogger logger = new DeserializationProblemLogger();
         mapper.addHandler(logger);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerTest.java
index 0bd73f5..1705763 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerTest.java
@@ -10,8 +10,8 @@
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
 import com.fasterxml.jackson.databind.deser.ValueInstantiator;
-import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
 import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
+import com.fasterxml.jackson.databind.exc.ValueInstantiationException;
 import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
 
 /**
@@ -92,14 +92,14 @@
         public InstantiationProblemHandler(Object v0) {
             value = v0;
         }
-    
+
         @Override
         public Object handleInstantiationProblem(DeserializationContext ctxt,
                 Class<?> instClass, Object argument, Throwable t)
             throws IOException
         {
-            if (!(t instanceof InvalidDefinitionException)) {
-                throw new IllegalArgumentException("Should have gotten `InvalidDefinitionException`, instead got: "+t);
+            if (!(t instanceof ValueInstantiationException)) {
+                throw new IllegalArgumentException("Should have gotten `ValueInstantiationException`, instead got: "+t);
             }
             return value;
         }
@@ -109,7 +109,7 @@
         extends DeserializationProblemHandler
     {
         protected final Object value;
-    
+
         public MissingInstantiationHandler(Object v0) {
             value = v0;
         }
@@ -135,7 +135,7 @@
 
         @Override
         public Object handleUnexpectedToken(DeserializationContext ctxt,
-                Class<?> targetType, JsonToken t, JsonParser p,
+                JavaType targetType, JsonToken t, JsonParser p,
                 String failureMsg)
             throws IOException
         {
@@ -232,11 +232,11 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     public void testWeirdKeyHandling() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper()
+        ObjectMapper mapper = newJsonMapper()
             .addHandler(new WeirdKeyHandler(7));
         IntKeyMapWrapper w = mapper.readValue("{\"stuff\":{\"foo\":\"abc\"}}",
                 IntKeyMapWrapper.class);
@@ -248,7 +248,7 @@
 
     public void testWeirdNumberHandling() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper()
+        ObjectMapper mapper = newJsonMapper()
             .addHandler(new WeirdNumberHandler(SingleValuedEnum.A))
             ;
         SingleValuedEnum result = mapper.readValue("3", SingleValuedEnum.class);
@@ -257,7 +257,7 @@
 
     public void testWeirdStringHandling() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper()
+        ObjectMapper mapper = newJsonMapper()
             .addHandler(new WeirdStringHandler(SingleValuedEnum.A))
             ;
         SingleValuedEnum result = mapper.readValue("\"B\"", SingleValuedEnum.class);
@@ -272,7 +272,7 @@
 
     public void testInvalidTypeId() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper()
+        ObjectMapper mapper = newJsonMapper()
             .addHandler(new UnknownTypeIdHandler(BaseImpl.class));
         BaseWrapper w = mapper.readValue("{\"value\":{\"type\":\"foo\",\"a\":4}}",
                 BaseWrapper.class);
@@ -282,7 +282,7 @@
 
     public void testInvalidClassAsId() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper()
+        ObjectMapper mapper = newJsonMapper()
             .addHandler(new UnknownTypeIdHandler(Base2Impl.class));
         Base2Wrapper w = mapper.readValue("{\"value\":{\"clazz\":\"com.fizz\",\"a\":4}}",
                 Base2Wrapper.class);
@@ -294,7 +294,7 @@
 
     public void testMissingTypeId() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper()
+        ObjectMapper mapper = newJsonMapper()
             .addHandler(new MissingTypeIdHandler(BaseImpl.class));
         BaseWrapper w = mapper.readValue("{\"value\":{\"a\":4}}",
                 BaseWrapper.class);
@@ -304,7 +304,7 @@
 
     public void testMissingClassAsId() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper()
+        ObjectMapper mapper = newJsonMapper()
             .addHandler(new MissingTypeIdHandler(Base2Impl.class));
         Base2Wrapper w = mapper.readValue("{\"value\":{\"a\":4}}",
                 Base2Wrapper.class);
@@ -328,7 +328,7 @@
 
     public void testInstantiationExceptionHandling() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper()
+        ObjectMapper mapper = newJsonMapper()
             .addHandler(new InstantiationProblemHandler(BustedCtor.INST));
         BustedCtor w = mapper.readValue("{ }",
                 BustedCtor.class);
@@ -337,7 +337,7 @@
 
     public void testMissingInstantiatorHandling() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper()
+        ObjectMapper mapper = newJsonMapper()
             .addHandler(new MissingInstantiationHandler(new NoDefaultCtor(13)))
             ;
         NoDefaultCtor w = mapper.readValue("{ \"x\" : true }", NoDefaultCtor.class);
@@ -347,7 +347,7 @@
 
     public void testUnexpectedTokenHandling() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper()
+        ObjectMapper mapper = newJsonMapper()
             .addHandler(new WeirdTokenHandler(Integer.valueOf(13)))
         ;
         Integer v = mapper.readValue("true", Integer.class);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerUnknownTypeId2221Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerUnknownTypeId2221Test.java
index 7cd1b4a..3271bcd 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerUnknownTypeId2221Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerUnknownTypeId2221Test.java
@@ -10,6 +10,7 @@
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
 import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 // for [databind#2221]
 public class ProblemHandlerUnknownTypeId2221Test extends BaseMapTest
@@ -84,7 +85,7 @@
 
     public void testWithDeserializationProblemHandler() throws Exception {
         final ObjectMapper mapper = new ObjectMapper()
-                .enableDefaultTyping();
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance);
         mapper.addHandler(new DeserializationProblemHandler() {
             @Override
             public JavaType handleUnknownTypeId(DeserializationContext ctxt, JavaType baseType, String subTypeId, TypeIdResolver idResolver, String failureMsg) throws IOException {
@@ -100,7 +101,7 @@
     public void testWithDisabledFAIL_ON_INVALID_SUBTYPE() throws Exception {
         final ObjectMapper mapper = new ObjectMapper()
                 .disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)
-                .enableDefaultTyping()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance)
         ;
         GenericContent processableContent = mapper.readValue(JSON, GenericContent.class);
         assertNotNull(processableContent.getInnerObjects());
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/RecursiveIgnorePropertiesTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/RecursiveIgnorePropertiesTest.java
index e3a2c7f..60624cc 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/filter/RecursiveIgnorePropertiesTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/RecursiveIgnorePropertiesTest.java
@@ -31,7 +31,7 @@
     /**********************************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     public void testRecursiveForDeser() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/TestUnknownPropertyDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/TestUnknownPropertyDeserialization.java
index dacf423..6f6ea1a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/filter/TestUnknownPropertyDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/TestUnknownPropertyDeserialization.java
@@ -125,7 +125,7 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     /**
      * By default we should just get an exception if an unknown property
@@ -146,7 +146,7 @@
      */
     public void testUnknownHandlingIgnoreWithHandler() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.clearProblemHandlers();
         mapper.addHandler(new MyHandler());
         TestBean result = mapper.readValue(new StringReader(JSON_UNKNOWN_FIELD), TestBean.class);
@@ -162,7 +162,7 @@
      */
     public void testUnknownHandlingIgnoreWithHandlerAndObjectReader() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.clearProblemHandlers();
         TestBean result = mapper.readerFor(TestBean.class).withHandler(new MyHandler()).readValue(new StringReader(JSON_UNKNOWN_FIELD));
         assertNotNull(result);
@@ -177,7 +177,7 @@
      */
     public void testUnknownHandlingIgnoreWithFeature() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
         TestBean result = null;
         try {
@@ -271,7 +271,7 @@
 
     public void testIssue987() throws Exception
     {
-        ObjectMapper jsonMapper = newObjectMapper();
+        ObjectMapper jsonMapper = newJsonMapper();
         jsonMapper.addHandler(new DeserializationProblemHandler() {
             @Override
             public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p, JsonDeserializer<?> deserializer, Object beanOrClass, String propertyName) throws IOException, JsonProcessingException {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/inject/InvalidInjectionTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/inject/InvalidInjectionTest.java
index a6e2543..b46a6df 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/inject/InvalidInjectionTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/inject/InvalidInjectionTest.java
@@ -24,8 +24,8 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
-    
+    private final ObjectMapper MAPPER = newJsonMapper();
+
     public void testInvalidDup() throws Exception
     {
         try {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/inject/TestInjectables.java b/src/test/java/com/fasterxml/jackson/databind/deser/inject/TestInjectables.java
index 49acd07..8c72eb4 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/inject/TestInjectables.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/inject/TestInjectables.java
@@ -90,11 +90,11 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
     
     public void testSimple() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.setInjectableValues(new InjectableValues.Std()
             .addValue(String.class, "stuffValue")
             .addValue("myId", "xyz")
@@ -135,7 +135,7 @@
         final Object methodInjected = "methodInjected";
         final Object fieldInjected = "fieldInjected";
 
-        ObjectMapper mapper = newObjectMapper()
+        ObjectMapper mapper = newJsonMapper()
                         .setInjectableValues(new InjectableValues.Std()
                                 .addValue("constructor_injected", constructorInjected)
                                 .addValue("method_injected", methodInjected)
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTZTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTZTest.java
index f4cd977..d5038ee 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTZTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTZTest.java
@@ -543,8 +543,7 @@
         try {
             Date date = read(mapper, input, java.util.Date.class);
             fail("Input "+input+" should not have been accepted but was deserialized into "+FORMAT.format(date));
-        }
-        catch(Exception e) {
+        } catch (Exception e) {
             // Is it the expected exception ?
             if (!exceptionType.isAssignableFrom(e.getClass()) ) {
                 fail("Wrong exception thrown when reading "+input+", actual: "+e.getClass().getName() + "("+e.getMessage()+"), expected: "+exceptionType.getName());
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTest.java
index 5ec830e..2feba30 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTest.java
@@ -90,7 +90,7 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     public void testDateUtil() throws Exception
     {
@@ -623,7 +623,7 @@
 
         // Standard mapper with timezone UTC: shared instance should be ok.
         // ... but, Travis manages to have fails, so insist on newly created
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         Date dateUTC = mapper.readValue(json, Date.class);  // 1970-01-01T00:00:00.000+00:00
     
         // Mapper with timezone GMT-2
@@ -725,7 +725,7 @@
     /**********************************************************
      */
 
-    public void testLenientCalendar() throws Exception
+    public void testLenientJDKDateTypes() throws Exception
     {
         final String JSON = aposToQuotes("{'value':'2015-11-32'}");
 
@@ -743,8 +743,10 @@
             verifyException(e, "from String \"2015-11-32\"");
             verifyException(e, "expected format");
         }
+    }
 
-        // similarly with Date...
+    public void testLenientJDKDateTypesViaTypeOverride() throws Exception
+    {
         ObjectMapper mapper = new ObjectMapper();
         mapper.configOverride(java.util.Date.class)
             .setFormat(JsonFormat.Value.forLeniency(Boolean.FALSE));
@@ -758,6 +760,38 @@
         }
     }
 
+    public void testLenientJDKDateTypesViaGlobal() throws Exception
+    {
+        final String JSON = quote("2015-11-32");
+
+        // with lenient, can parse fine
+        Calendar value = MAPPER.readValue(JSON, Calendar.class);
+        assertEquals(Calendar.DECEMBER, value.get(Calendar.MONTH));
+        assertEquals(2, value.get(Calendar.DAY_OF_MONTH));
+
+        // but not so if default leniency disabled
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.setDefaultLeniency(false);
+        try {
+            mapper.readValue(JSON, java.util.Date.class);
+            fail("Should not pass with invalid (with strict) date value");
+        } catch (MismatchedInputException e) {
+            verifyException(e, "Cannot deserialize value of type `java.util.Date`");
+            verifyException(e, "from String \"2015-11-32\"");
+            verifyException(e, "expected format");
+        }
+    
+        // Unless we actually had per-type override too
+        mapper = new ObjectMapper();
+        mapper.configOverride(Calendar.class)
+            .setFormat(JsonFormat.Value.forLeniency(Boolean.TRUE));
+        mapper.setDefaultLeniency(false);
+
+        value = mapper.readValue(JSON, Calendar.class);
+        assertEquals(Calendar.DECEMBER, value.get(Calendar.MONTH));
+        assertEquals(2, value.get(Calendar.DAY_OF_MONTH));
+    }
+
     /*
     /**********************************************************
     /* Tests to verify failing cases
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumAltIdTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumAltIdTest.java
index 76f1882..1b1e7ec 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumAltIdTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumAltIdTest.java
@@ -41,11 +41,9 @@
      */
 
     protected final ObjectMapper MAPPER = new ObjectMapper();
-    protected final ObjectMapper MAPPER_IGNORE_CASE;
-    {
-        MAPPER_IGNORE_CASE = new ObjectMapper();
-        MAPPER_IGNORE_CASE.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);
-    }
+    protected final ObjectMapper MAPPER_IGNORE_CASE = jsonMapperBuilder()
+            .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
+            .build();
 
     protected final ObjectReader READER_DEFAULT = MAPPER.reader();
     protected final ObjectReader READER_IGNORE_CASE = MAPPER_IGNORE_CASE.reader();
@@ -57,7 +55,8 @@
             READER_DEFAULT.forType(TestEnum.class).readValue("\"Jackson\"");
             fail("InvalidFormatException expected");
         } catch (InvalidFormatException e) {
-            verifyException(e, "value not one of declared Enum instance names: [JACKSON, OK, RULES]");
+            verifyException(e, "not one of the values accepted for Enum class");
+            verifyException(e, "[JACKSON, OK, RULES]");
         }
     }
     
@@ -68,7 +67,8 @@
             r.readValue("\"A\"");
             fail("InvalidFormatException expected");
         } catch (InvalidFormatException e) {
-            verifyException(e, "value not one of declared Enum instance names: [a, b, c]");
+            verifyException(e, "not one of the values accepted for Enum class");
+            verifyException(e,"[a, b, c]");
         }
     }
 
@@ -126,7 +126,8 @@
                     .readValue(JSON);
             fail("Should not pass");
         } catch (InvalidFormatException e) {
-            verifyException(e, "value not one of declared Enum instance names: [JACKSON, OK, RULES]");
+            verifyException(e, "not one of the values accepted for Enum class");
+            verifyException(e, "[JACKSON, OK, RULES]");
         }
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumDeserializationTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumDeserializationTest.java
index ff0a29c..7cdcc38 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumDeserializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumDeserializationTest.java
@@ -7,12 +7,15 @@
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.type.TypeReference;
+
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer;
 import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
 import com.fasterxml.jackson.databind.exc.InvalidFormatException;
 import com.fasterxml.jackson.databind.exc.MismatchedInputException;
+import com.fasterxml.jackson.databind.exc.ValueInstantiationException;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.databind.module.SimpleModule;
 
 @SuppressWarnings("serial")
@@ -183,6 +186,35 @@
         }
     }
 
+    // for [databind#2164]
+    public enum TestEnum2164 {
+        A, B;
+
+        @JsonCreator
+        public static TestEnum2164 fromString(String input) {
+            throw new IllegalArgumentException("2164");
+        }
+    }
+
+    // for [databind#2309]
+    static enum Enum2309 {
+        NON_NULL("NON_NULL"),
+        NULL(null),
+        OTHER("OTHER")
+        ;
+
+        private String value;
+
+        private Enum2309(String value) {
+            this.value = value;
+        }
+
+        @Override
+        public String toString() {
+            return value;
+        }
+    }        
+
     /*
     /**********************************************************
     /* Test methods
@@ -215,7 +247,7 @@
             /*Object result =*/ MAPPER.readValue("\"NO-SUCH-VALUE\"", TestEnum.class);
             fail("Expected an exception for bogus enum value...");
         } catch (MismatchedInputException jex) {
-            verifyException(jex, "value not one of declared");
+            verifyException(jex, "not one of the values accepted for Enum class");
         }
         jp.close();
     }
@@ -284,17 +316,17 @@
         } catch (MismatchedInputException e) {
             verifyException(e, "Cannot deserialize");
             // 26-Jan-2017, tatu: as per [databind#1505], should fail bit differently
-            verifyException(e, "value not one of declared Enum");
+            verifyException(e, "not one of the values accepted for Enum class");
         }
     }
 
     public void testEnumsWithIndex() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX);
-        String json = m.writeValueAsString(TestEnum.RULES);
+        String json = MAPPER.writer()
+                .with(SerializationFeature.WRITE_ENUMS_USING_INDEX)
+                .writeValueAsString(TestEnum.RULES);
         assertEquals(String.valueOf(TestEnum.RULES.ordinal()), json);
-        TestEnum result = m.readValue(json, TestEnum.class);
+        TestEnum result = MAPPER.readValue(json, TestEnum.class);
         assertSame(TestEnum.RULES, result);
     }
 
@@ -391,14 +423,14 @@
 
     // [databind#381]
     public void testUnwrappedEnum() throws Exception {
-        final ObjectMapper mapper = newObjectMapper();
-        mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-        
-        assertEquals(TestEnum.JACKSON, mapper.readValue("[" + quote("JACKSON") + "]", TestEnum.class));
+        assertEquals(TestEnum.JACKSON,
+                MAPPER.readerFor(TestEnum.class)
+                    .with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
+                    .readValue("[" + quote("JACKSON") + "]"));
     }
     
     public void testUnwrappedEnumException() throws Exception {
-        final ObjectMapper mapper = newObjectMapper();
+        final ObjectMapper mapper = newJsonMapper();
         mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
         try {
             Object v = mapper.readValue("[" + quote("JACKSON") + "]",
@@ -422,10 +454,12 @@
         assertSame(TestEnum.values()[1], en);
 
         // [databind#1690]: unless prevented
-        final ObjectMapper mapper = newObjectMapper();
-        mapper.disable(MapperFeature.ALLOW_COERCION_OF_SCALARS);
         try {
-            en = mapper.readValue(quote("1"), TestEnum.class);
+            en = JsonMapper.builder()
+                    .configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false)
+                    .build()
+                    .readerFor(TestEnum.class)
+                    .readValue(quote("1"));
             fail("Should not pass");
         } catch (MismatchedInputException e) {
             verifyException(e, "Cannot deserialize value of type");
@@ -517,7 +551,7 @@
     }
 
     public void testExceptionFromCustomEnumKeyDeserializer() throws Exception {
-        ObjectMapper mapper = newObjectMapper()
+        ObjectMapper mapper = newJsonMapper()
                 .registerModule(new EnumModule());
         try {
             mapper.readValue("{\"TWO\": \"dumpling\"}",
@@ -527,4 +561,39 @@
             assertTrue(e.getMessage().contains("Undefined AnEnum"));
         }
     }
+
+    // [databind#2164]
+    public void testWrapExceptions() throws Exception
+    {
+        // By default, wrap:
+        try {
+            MAPPER.readerFor(TestEnum2164.class)
+                .readValue(quote("B"));
+            fail("Should not pass");
+        } catch (ValueInstantiationException e) {
+            verifyException(e, "2164");
+        }
+
+        // But can disable:
+        try {
+            MAPPER.readerFor(TestEnum2164.class)
+                .without(DeserializationFeature.WRAP_EXCEPTIONS)
+                .readValue(quote("B"));
+            fail("Should not pass");
+        } catch (JsonMappingException e) {
+            fail("Wrong exception, should not wrap, got: "+e);
+        } catch (IllegalArgumentException e) {
+            verifyException(e, "2164");
+        }
+    }
+
+    // [databind#2309]
+    public void testEnumToStringNull2309() throws Exception
+    {
+        Enum2309 value = MAPPER.readerFor(Enum2309.class)
+                .with(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
+                .readValue(quote("NON_NULL"));
+        assertEquals(Enum2309.NON_NULL, value);
+    }
+
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumMapDeserializationTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumMapDeserializationTest.java
index bf30d14..d458c06 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumMapDeserializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/EnumMapDeserializationTest.java
@@ -1,12 +1,15 @@
 package com.fasterxml.jackson.databind.deser.jdk;
 
 import java.util.EnumMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
 import com.fasterxml.jackson.annotation.*;
 
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 @SuppressWarnings("serial")
 public class EnumMapDeserializationTest extends BaseMapTest
@@ -75,6 +78,22 @@
         }
     }
 
+    // [databind#2457]
+    enum MyEnum2457 {
+        A,
+        B() {
+            // just to ensure subclass construction
+            @Override
+            public void foo() { }
+        };
+
+        // needed to force subclassing
+        public void foo() { }
+
+        @Override
+        public String toString() { return name() + " as string"; }
+    }
+
     /*
     /**********************************************************
     /* Test methods, basic
@@ -157,8 +176,10 @@
         enumMap.put(Enum1859.B, "stuff");
         Pojo1859 input = new Pojo1859(enumMap);
 
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.NON_FINAL, "@type");
+        ObjectMapper mapper = JsonMapper.builder()
+                .activateDefaultTypingAsProperty(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL, "@type")
+                .build();
 
         // 05-Mar-2018, tatu: Original issue had this; should not make difference:
          /*
@@ -220,4 +241,21 @@
         assertEquals(1, value2.size());
         assertEquals("value", value2.get(null));
     }
+
+    // [databind#2457]
+    public void testCustomEnumAsRootMapKey() throws Exception
+    {
+        final ObjectMapper mapper = newJsonMapper();
+        final Map<MyEnum2457, String> map = new LinkedHashMap<>();
+        map.put(MyEnum2457.A, "1");
+        map.put(MyEnum2457.B, "2");
+        assertEquals(aposToQuotes("{'A':'1','B':'2'}"),
+                mapper.writeValueAsString(map));
+
+        // But should be able to override
+        assertEquals(aposToQuotes("{'"+MyEnum2457.A.toString()+"':'1','"+MyEnum2457.B.toString()+"':'2'}"),
+                mapper.writer()
+                    .with(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
+                    .writeValueAsString(map));
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKCollectionsDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKCollectionsDeserTest.java
index 875c61c..272cb94 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKCollectionsDeserTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKCollectionsDeserTest.java
@@ -7,6 +7,7 @@
 import com.fasterxml.jackson.core.type.TypeReference;
 
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 /**
  * Tests for special collection/map types via `java.util.Collections`
@@ -31,7 +32,7 @@
     // And then a round-trip test for singleton collections
     public void testSingletonCollections() throws Exception
     {
-        final TypeReference<?> xbeanListType = new TypeReference<List<XBean>>() { };
+        final TypeReference<List<XBean>> xbeanListType = new TypeReference<List<XBean>>() { };
 
         String json = MAPPER.writeValueAsString(Collections.singleton(new XBean(3)));
         Collection<XBean> result = MAPPER.readValue(json, xbeanListType);
@@ -49,8 +50,10 @@
     // [databind#1868]: Verify class name serialized as is
     public void testUnmodifiableSet() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY)
+                .build();
 
         Set<String> theSet = Collections.unmodifiableSet(Collections.singleton("a"));
         String json = mapper.writeValueAsString(theSet);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberDeserTest.java
index 2fc0b1c..e316367 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberDeserTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberDeserTest.java
@@ -131,8 +131,9 @@
             verifyException(e, "Cannot coerce String \"null\"");
         }
 
-        ObjectMapper noCoerceMapper = new ObjectMapper();
-        noCoerceMapper.disable(MapperFeature.ALLOW_COERCION_OF_SCALARS);
+        ObjectMapper noCoerceMapper = jsonMapperBuilder()
+                .disable(MapperFeature.ALLOW_COERCION_OF_SCALARS)
+                .build();
         try {
             noCoerceMapper.readValue(NULL_JSON, Integer.TYPE);
             fail("Should not have passed");
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberLeniencyTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberLeniencyTest.java
new file mode 100644
index 0000000..b7269cb
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberLeniencyTest.java
@@ -0,0 +1,38 @@
+package com.fasterxml.jackson.databind.deser.jdk;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
+
+public class JDKNumberLeniencyTest extends BaseMapTest
+{
+    final ObjectMapper VANILLA_MAPPER = sharedMapper();
+
+    final ObjectMapper STRICT_MAPPER = jsonMapperBuilder()
+            .disable(MapperFeature.ALLOW_COERCION_OF_SCALARS)
+//            .defaultLeniency(false)
+            .build();
+
+    public void testBooleanLeniencyInts() throws Exception
+    {
+        // First: read from integers fine by default
+        assertEquals(Boolean.TRUE, VANILLA_MAPPER.readValue("1", Boolean.class));
+        assertEquals(Boolean.TRUE,
+                VANILLA_MAPPER.readValue("{\"b\" : 3}", BooleanWrapper.class).b);
+
+        // But not with strict handling, first by global settings
+        _verifyBooleanCoercionFailure(STRICT_MAPPER, "0", Boolean.class);
+        _verifyBooleanCoercionFailure(STRICT_MAPPER, "{\"b\" : 1}", BooleanWrapper.class);
+    }
+
+    protected void _verifyBooleanCoercionFailure(ObjectMapper mapper, String json, Class<?> type)
+            throws Exception
+    {
+        try {
+            mapper.readValue(json, type);
+            fail("Should not allow read in strict mode");
+        } catch (MismatchedInputException e) {
+            verifyException(e, "Cannot coerce");
+            verifyException(e, "for type `java.lang.Boolean`");
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKStringLikeTypesTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKStringLikeTypesTest.java
index 7f65dd3..b4e5892 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKStringLikeTypesTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKStringLikeTypesTest.java
@@ -359,34 +359,34 @@
 
     public void testUUIDAux() throws Exception
     {
-        // [JACKSON-393] fix:
         final UUID value = UUID.fromString("76e6d183-5f68-4afa-b94a-922c1fdb83f8");
 
         // first, null should come as null
-        TokenBuffer buf = new TokenBuffer(null, false);
-        buf.writeObject(null);
-        assertNull(MAPPER.readValue(buf.asParser(), UUID.class));
-        buf.close();
+        try (TokenBuffer buf = new TokenBuffer(null, false)) {
+            buf.writeObject(null);
+            assertNull(MAPPER.readValue(buf.asParser(), UUID.class));
+        }
 
         // then, UUID itself come as is:
-        buf = new TokenBuffer(null, false);
-        buf.writeObject(value);
-        assertSame(value, MAPPER.readValue(buf.asParser(), UUID.class));
-
-        // and finally from byte[]
-        // oh crap; JDK UUID just... sucks. Not even byte[] accessors or constructors? Huh?
-        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-        DataOutputStream out = new DataOutputStream(bytes);
-        out.writeLong(value.getMostSignificantBits());
-        out.writeLong(value.getLeastSignificantBits());
-        byte[] data = bytes.toByteArray();
-        assertEquals(16, data.length);
-        
-        buf.writeObject(data);
-
-        UUID value2 = MAPPER.readValue(buf.asParser(), UUID.class);
-        
-        assertEquals(value, value2);
-        buf.close();
+        try (TokenBuffer buf = new TokenBuffer(null, false)) {
+            buf.writeObject(value);
+            assertSame(value, MAPPER.readValue(buf.asParser(), UUID.class));
+    
+            // and finally from byte[]
+            // oh crap; JDK UUID just... sucks. Not even byte[] accessors or constructors? Huh?
+            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+            DataOutputStream out = new DataOutputStream(bytes);
+            out.writeLong(value.getMostSignificantBits());
+            out.writeLong(value.getLeastSignificantBits());
+            out.close();
+            byte[] data = bytes.toByteArray();
+            assertEquals(16, data.length);
+            
+            buf.writeObject(data);
+    
+            UUID value2 = MAPPER.readValue(buf.asParser(), UUID.class);
+            
+            assertEquals(value, value2);
+        }
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapDeserializationTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapDeserializationTest.java
index 4b56d28..a14bc01 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapDeserializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapDeserializationTest.java
@@ -244,7 +244,7 @@
     {
         // to get typing, must use type reference
         String JSON = "{ \"a\" : \"b\" }";
-        Map<String,Integer> result = MAPPER.readValue
+        TreeMap<String,String> result = MAPPER.readValue
             (JSON, new TypeReference<TreeMap<String,String>>() { });
 
         assertNotNull(result);
@@ -320,7 +320,7 @@
         String JSON = "{ \"KEY2\" : \"WHATEVER\" }";
 
         // to get typing, must use type reference
-        Map<Enum<?>,Enum<?>> result = MAPPER.readValue
+        Map<Key,Key> result = MAPPER.readValue
             (JSON, new TypeReference<Map<Key,Key>>() { });
 
         assertNotNull(result);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapKeyDeserializationTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapKeyDeserializationTest.java
index 32a616c..0cd9773 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapKeyDeserializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapKeyDeserializationTest.java
@@ -47,8 +47,8 @@
 
     public void testBooleanMapKeyDeserialization() throws Exception
     {
-        TypeReference<?> type = new TypeReference<MapWrapper<Boolean, String>>() { };
-        MapWrapper<byte[], String> result = MAPPER.readValue(aposToQuotes("{'map':{'true':'foobar'}}"), type);
+        TypeReference<MapWrapper<Boolean, String>> type = new TypeReference<MapWrapper<Boolean, String>>() { };
+        MapWrapper<?,?> result = MAPPER.readValue(aposToQuotes("{'map':{'true':'foobar'}}"), type);
                 
         assertEquals(1, result.map.size());
         Assert.assertEquals(Boolean.TRUE, result.map.entrySet().iterator().next().getKey());
@@ -60,48 +60,48 @@
 
     public void testByteMapKeyDeserialization() throws Exception
     {
-        TypeReference<?> type = new TypeReference<MapWrapper<Byte, String>>() { };
-        MapWrapper<byte[], String> result = MAPPER.readValue(aposToQuotes("{'map':{'13':'foobar'}}"), type);
+        TypeReference<MapWrapper<Byte, String>> type = new TypeReference<MapWrapper<Byte, String>>() { };
+        MapWrapper<?,?> result = MAPPER.readValue(aposToQuotes("{'map':{'13':'foobar'}}"), type);
         assertEquals(1, result.map.size());
         Assert.assertEquals(Byte.valueOf((byte) 13), result.map.entrySet().iterator().next().getKey());
     }
 
     public void testShortMapKeyDeserialization() throws Exception
     {
-        TypeReference<?> type = new TypeReference<MapWrapper<Short, String>>() { };
-        MapWrapper<byte[], String> result = MAPPER.readValue(aposToQuotes("{'map':{'13':'foobar'}}"), type);
+        TypeReference<MapWrapper<Short, String>> type = new TypeReference<MapWrapper<Short, String>>() { };
+        MapWrapper<?,?> result = MAPPER.readValue(aposToQuotes("{'map':{'13':'foobar'}}"), type);
         assertEquals(1, result.map.size());
         Assert.assertEquals(Short.valueOf((short) 13), result.map.entrySet().iterator().next().getKey());
     }
 
     public void testIntegerMapKeyDeserialization() throws Exception
     {
-        TypeReference<?> type = new TypeReference<MapWrapper<Integer, String>>() { };
-        MapWrapper<byte[], String> result = MAPPER.readValue(aposToQuotes("{'map':{'-3':'foobar'}}"), type);
+        TypeReference<MapWrapper<Integer, String>> type = new TypeReference<MapWrapper<Integer, String>>() { };
+        MapWrapper<?,?> result = MAPPER.readValue(aposToQuotes("{'map':{'-3':'foobar'}}"), type);
         assertEquals(1, result.map.size());
         Assert.assertEquals(Integer.valueOf(-3), result.map.entrySet().iterator().next().getKey());
     }
 
     public void testLongMapKeyDeserialization() throws Exception
     {
-        TypeReference<?> type = new TypeReference<MapWrapper<Long, String>>() { };
-        MapWrapper<byte[], String> result = MAPPER.readValue(aposToQuotes("{'map':{'42':'foobar'}}"), type);
+        TypeReference<MapWrapper<Long, String>> type = new TypeReference<MapWrapper<Long, String>>() { };
+        MapWrapper<?,?> result = MAPPER.readValue(aposToQuotes("{'map':{'42':'foobar'}}"), type);
         assertEquals(1, result.map.size());
         Assert.assertEquals(Long.valueOf(42), result.map.entrySet().iterator().next().getKey());
     }
 
     public void testFloatMapKeyDeserialization() throws Exception
     {
-        TypeReference<?> type = new TypeReference<MapWrapper<Float, String>>() { };
-        MapWrapper<byte[], String> result = MAPPER.readValue(aposToQuotes("{'map':{'3.5':'foobar'}}"), type);
+        TypeReference<MapWrapper<Float, String>> type = new TypeReference<MapWrapper<Float, String>>() { };
+        MapWrapper<?,?> result = MAPPER.readValue(aposToQuotes("{'map':{'3.5':'foobar'}}"), type);
         assertEquals(1, result.map.size());
         Assert.assertEquals(Float.valueOf(3.5f), result.map.entrySet().iterator().next().getKey());
     }
 
     public void testDoubleMapKeyDeserialization() throws Exception
     {
-        TypeReference<?> type = new TypeReference<MapWrapper<Double, String>>() { };
-        MapWrapper<byte[], String> result = MAPPER.readValue(aposToQuotes("{'map':{'0.25':'foobar'}}"), type);
+        TypeReference<MapWrapper<Double, String>> type = new TypeReference<MapWrapper<Double, String>>() { };
+        MapWrapper<?,?> result = MAPPER.readValue(aposToQuotes("{'map':{'0.25':'foobar'}}"), type);
         assertEquals(1, result.map.size());
         Assert.assertEquals(Double.valueOf(0.25), result.map.entrySet().iterator().next().getKey());
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapRelatedTypesDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapRelatedTypesDeserTest.java
index bc8dc16..34a4588 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapRelatedTypesDeserTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapRelatedTypesDeserTest.java
@@ -8,7 +8,7 @@
 public class MapRelatedTypesDeserTest
     extends BaseMapTest
 {
-    private final ObjectMapper MAPPER = new ObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     /*
     /**********************************************************
@@ -71,7 +71,7 @@
     // JDK singletonMap
     public void testSingletonMapRoundtrip() throws Exception
     {
-        final TypeReference<?> type = new TypeReference<Map<String,IntWrapper>>() { };
+        final TypeReference<Map<String,IntWrapper>> type = new TypeReference<Map<String,IntWrapper>>() { };
 
         String json = MAPPER.writeValueAsString(Collections.singletonMap("value", new IntWrapper(5)));
         Map<String,IntWrapper> result = MAPPER.readValue(json, type);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/TestEmptyArrayBlockingQueueDeser.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/TestEmptyArrayBlockingQueueDeser.java
new file mode 100644
index 0000000..5b5c732
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/TestEmptyArrayBlockingQueueDeser.java
@@ -0,0 +1,35 @@
+package com.fasterxml.jackson.databind.deser.jdk;
+
+import java.util.Collection;
+import java.util.concurrent.ArrayBlockingQueue;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.*;
+
+public class TestEmptyArrayBlockingQueueDeser extends BaseMapTest
+{
+    static class RemoteEntity{
+        private Collection<Double> values = new ArrayBlockingQueue<>(20);
+
+        public Collection<Double> getValues() {
+            return values;
+        }
+    }
+
+    static class Entity{
+        private ArrayBlockingQueue<Double> values;
+
+        public Collection<Double> getValues() {
+            return values;
+        }
+    }
+
+    private final ObjectMapper MAPPER = newJsonMapper();
+
+    public void testEmptyBlockingQueue() throws Exception
+    {
+        String json = MAPPER.writeValueAsString(new RemoteEntity());
+        Entity entity = MAPPER.readValue(json, Entity.class);
+        assertEquals(0, entity.values.size());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/UntypedDeserializationTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/UntypedDeserializationTest.java
index 3b28b9d..b0a5c7e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/UntypedDeserializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/UntypedDeserializationTest.java
@@ -9,12 +9,14 @@
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
 import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
 import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
 import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
 import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
 import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 /**
  * Unit tests for verifying "raw" (or "untyped") data binding from JSON to JDK objects;
@@ -114,6 +116,11 @@
         public Object value;
     }
 
+    // [databind#2115]
+    static class SerContainer {
+        public java.io.Serializable value;
+    }
+
     /*
     /**********************************************************
     /* Test methods
@@ -214,25 +221,6 @@
         assertEquals(2, l.size());
         assertEquals(Integer.valueOf(2), l.get(1));
     }
-    
-    // Allow 'upgrade' of big integers into Long, BigInteger
-    public void testObjectSerializeWithLong() throws IOException
-    {
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(DefaultTyping.JAVA_LANG_OBJECT, As.PROPERTY);
-        final long VALUE = 1337800584532L;
-
-        String serialized = "{\"timestamp\":"+VALUE+"}";
-        // works fine as node
-        JsonNode deserialized = mapper.readTree(serialized);
-        assertEquals(VALUE, deserialized.get("timestamp").asLong());
-        // and actually should work in Maps too
-        Map<?,?> deserMap = mapper.readValue(serialized, Map.class);
-        Number n = (Number) deserMap.get("timestamp");
-        assertNotNull(n);
-        assertSame(Long.class, n.getClass());
-        assertEquals(Long.valueOf(VALUE), n);
-    }
 
     public void testUntypedWithCustomScalarDesers() throws IOException
     {
@@ -383,4 +371,51 @@
                 .readValue(JSON);
         assertEquals(Long.valueOf(3), w.value);
     }
+
+    // [databind#2115]: Consider `java.io.Serializable` as sort of alias of `java.lang.Object`
+    // since all natural target types do implement `Serializable` so assignment works
+    public void testSerializable() throws Exception
+    {
+        final String JSON1 = aposToQuotes("{ 'value' : 123 }");
+        SerContainer cont = MAPPER.readValue(JSON1, SerContainer.class);
+        assertEquals(Integer.valueOf(123), cont.value);
+
+        cont = MAPPER.readValue(aposToQuotes("{ 'value' : true }"), SerContainer.class);
+        assertEquals(Boolean.TRUE, cont.value);
+
+        // But also via Map value, even key
+        Map<?,?> map = MAPPER.readValue(JSON1, new TypeReference<Map<String, Serializable>>() { });
+        assertEquals(1, map.size());
+        assertEquals(Integer.valueOf(123), map.get("value"));
+
+        map = MAPPER.readValue(JSON1, new TypeReference<Map<Serializable, Object>>() { });
+        assertEquals(1, map.size());
+        assertEquals("value", map.keySet().iterator().next());
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods, polymorphic
+    /**********************************************************
+     */
+
+    // Allow 'upgrade' of big integers into Long, BigInteger
+    public void testObjectSerializeWithLong() throws IOException
+    {
+        final ObjectMapper mapper = newJsonMapper();
+        mapper.activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                DefaultTyping.JAVA_LANG_OBJECT, As.PROPERTY);
+        final long VALUE = 1337800584532L;
+
+        String serialized = "{\"timestamp\":"+VALUE+"}";
+        // works fine as node
+        JsonNode deserialized = mapper.readTree(serialized);
+        assertEquals(VALUE, deserialized.get("timestamp").asLong());
+        // and actually should work in Maps too
+        Map<?,?> deserMap = mapper.readValue(serialized, Map.class);
+        Number n = (Number) deserMap.get("timestamp");
+        assertNotNull(n);
+        assertSame(Long.class, n.getClass());
+        assertEquals(Long.valueOf(VALUE), n);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/UtilCollectionsTypesTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/UtilCollectionsTypesTest.java
index 79d91d8..4d94aa1 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/UtilCollectionsTypesTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/UtilCollectionsTypesTest.java
@@ -5,14 +5,16 @@
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.databind.BaseMapTest;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 // Unit tests for [databind#1868], [databind#1880], [databind#2265]
 public class UtilCollectionsTypesTest extends BaseMapTest
 {
-   private final ObjectMapper DEFAULT_MAPPER = new ObjectMapper();
-   {
-       DEFAULT_MAPPER.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
-   }
+   private final ObjectMapper DEFAULT_MAPPER = JsonMapper.builder()
+           .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                   ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY)
+           .build();
 
    /*
    /**********************************************************
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/merge/ArrayMergeTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/merge/ArrayMergeTest.java
index 908ddc5..d8bbbf4 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/merge/ArrayMergeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/merge/ArrayMergeTest.java
@@ -26,10 +26,10 @@
     /********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper()
+    private final ObjectMapper MAPPER = jsonMapperBuilder()
             // 26-Oct-2016, tatu: Make sure we'll report merge problems by default
             .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)
-    ;
+            .build();
 
     public void testObjectArrayMerging() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/merge/CollectionMergeTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/merge/CollectionMergeTest.java
index 3305d37..0859143 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/merge/CollectionMergeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/merge/CollectionMergeTest.java
@@ -52,10 +52,10 @@
     /********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper()
+    private final ObjectMapper MAPPER = jsonMapperBuilder()
             // 26-Oct-2016, tatu: Make sure we'll report merge problems by default
             .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)
-    ;
+            .build();
 
     public void testCollectionMerging() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/merge/MapMerge1844Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/merge/MapMerge1844Test.java
index e5fd75d..26f2c60 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/merge/MapMerge1844Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/merge/MapMerge1844Test.java
@@ -36,7 +36,7 @@
     // for [databind#1844]
     public void testMap1844() throws Exception
     {
-        final ObjectMapper mapper = newObjectMapper();
+        final ObjectMapper mapper = newJsonMapper();
         mapper.setDefaultMergeable(true);
 
         final String f1 = aposToQuotes(
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/merge/MapMergeTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/merge/MapMergeTest.java
index 647d934..a66a960 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/merge/MapMergeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/merge/MapMergeTest.java
@@ -46,12 +46,12 @@
     /********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper()
+    private final ObjectMapper MAPPER = jsonMapperBuilder()
             // 26-Oct-2016, tatu: Make sure we'll report merge problems by default
             .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)
-    ;
+            .build();
 
-    private final ObjectMapper MAPPER_SKIP_NULLS = newObjectMapper()
+    private final ObjectMapper MAPPER_SKIP_NULLS = newJsonMapper()
             .setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.SKIP));
     ;
     
@@ -166,7 +166,7 @@
 
     public void testDisabledMergeViaGlobal() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         // disable merging, globally; does not affect main level
         mapper.setDefaultMergeable(false);
 
@@ -183,7 +183,7 @@
 
     public void testDisabledMergeByType() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         // disable merging for "untyped", that is, `Object.class`
         mapper.configOverride(Object.class)
             .setMergeable(false);
@@ -199,7 +199,7 @@
         // and for extra points, disable by default but ENABLE for type,
         // which should once again allow merging
 
-        mapper = newObjectMapper();
+        mapper = newJsonMapper();
         mapper.setDefaultMergeable(false);
         mapper.configOverride(Object.class)
             .setMergeable(true);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/merge/MapPolymorphicMerge2336Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/merge/MapPolymorphicMerge2336Test.java
new file mode 100644
index 0000000..859bbc9
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/merge/MapPolymorphicMerge2336Test.java
@@ -0,0 +1,119 @@
+package com.fasterxml.jackson.databind.deser.merge;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import com.fasterxml.jackson.annotation.*;
+
+import com.fasterxml.jackson.databind.*;
+
+public class MapPolymorphicMerge2336Test extends BaseMapTest
+{
+    private final ObjectMapper MAPPER = sharedMapper();
+
+    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "discriminator")
+    @JsonSubTypes({@JsonSubTypes.Type(value = SomeClassA.class, name = "FirstConcreteImpl")})
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    public static abstract class SomeBaseClass {
+        private String name;
+
+        @JsonCreator
+        public SomeBaseClass(@JsonProperty("name") String name) {
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+    }
+
+    @JsonTypeName("FirstConcreteImpl")
+    public static class SomeClassA extends SomeBaseClass {
+        private Integer a;
+        private Integer b;
+
+        @JsonCreator
+        public SomeClassA(@JsonProperty("name") String name, @JsonProperty("a") Integer a, @JsonProperty("b") Integer b) {
+            super(name);
+            this.a = a;
+            this.b = b;
+        }
+
+        public Integer getA() {
+            return a;
+        }
+
+        public void setA(Integer a) {
+            this.a = a;
+        }
+
+        public Integer getB() {
+            return b;
+        }
+
+        public void setB(Integer b) {
+            this.b = b;
+        }
+    }
+
+    public static class SomeOtherClass {
+        String someprop;
+
+        @JsonCreator
+        public SomeOtherClass(@JsonProperty("someprop") String someprop) {
+            this.someprop = someprop;
+        }
+
+        @JsonMerge
+        Map<String, SomeBaseClass> data = new LinkedHashMap<>();
+
+        public void addValue(String key, SomeBaseClass value) {
+            data.put(key, value);
+        }
+
+        public Map<String, SomeBaseClass> getData() {
+            return data;
+        }
+
+        public void setData(
+                Map<String, SomeBaseClass> data) {
+            this.data = data;
+        }
+    }
+
+    // [databind#2336]
+    public void testPolymorphicMapMerge() throws Exception
+    {
+        // first let's just get some valid JSON
+        SomeOtherClass baseValue = new SomeOtherClass("house");
+        baseValue.addValue("SOMEKEY", new SomeClassA("fred", 1, null));
+
+        // now create a reader specifically for merging
+        ObjectReader reader = MAPPER.readerForUpdating(baseValue);
+
+        
+        SomeOtherClass toBeMerged = new SomeOtherClass("house");
+        toBeMerged.addValue("SOMEKEY", new SomeClassA("jim", null, 2));
+        String jsonForMerging = MAPPER.writeValueAsString(toBeMerged);
+
+        assertEquals("fred", baseValue.data.get("SOMEKEY").getName());
+        
+        // now try to do the merge and it blows up
+        SomeOtherClass mergedResult = reader.readValue(jsonForMerging);
+
+        // First of all, should update main POJO (since it's "value to update")
+        assertSame(baseValue, mergedResult);
+        // as well as Map within
+        assertSame(baseValue.data, mergedResult.data);
+
+        assertEquals(1, mergedResult.data.size());
+        // but entry value has changed by necessity
+        assertEquals(SomeClassA.class, mergedResult.data.get("SOMEKEY").getClass());
+
+        assertEquals("jim", mergedResult.data.get("SOMEKEY").getName());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/merge/MergeWithNullTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/merge/MergeWithNullTest.java
index bc80ad3..c447cf2 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/merge/MergeWithNullTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/merge/MergeWithNullTest.java
@@ -66,10 +66,10 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper()
+    private final ObjectMapper MAPPER = jsonMapperBuilder()
             // 26-Oct-2016, tatu: Make sure we'll report merge problems by default
             .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)
-    ;
+            .build();
 
     public void testBeanMergingWithNullDefault() throws Exception
     {
@@ -83,7 +83,7 @@
 
         // First: via specific type override
         // important! We'll specify for value type to be merged
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.configOverride(AB.class)
             .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SKIP));
         config = mapper.readerForUpdating(new ConfigDefault(137, -3))
@@ -93,7 +93,7 @@
         assertEquals(-3, config.loc.b);
 
         // Second: by global defaults
-        mapper = newObjectMapper();
+        mapper = newJsonMapper();
         mapper.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SKIP));
         config = mapper.readerForUpdating(new ConfigDefault(12, 34))
                 .readValue(aposToQuotes("{'loc':null}"));
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/merge/NodeMergeTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/merge/NodeMergeTest.java
index 435ecdb..73a8620 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/merge/NodeMergeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/merge/NodeMergeTest.java
@@ -8,10 +8,10 @@
 
 public class NodeMergeTest extends BaseMapTest
 {
-    private final static ObjectMapper MAPPER = newObjectMapper()
+    private final static ObjectMapper MAPPER = jsonMapperBuilder()
             // 26-Oct-2016, tatu: Make sure we'll report merge problems by default
             .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)
-    ;
+            .build();
 
     static class ObjectNodeWrapper {
         @JsonMerge
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/merge/PropertyMergeTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/merge/PropertyMergeTest.java
index 826d465..c718713 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/merge/PropertyMergeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/merge/PropertyMergeTest.java
@@ -87,16 +87,36 @@
         public int value;
     }
 
+    // [databind#2280]
+    static class ConstructorArgsPojo {
+        static class MergeablePojo {
+            public String foo;
+            public String bar;
+
+            public MergeablePojo(String foo, String bar) {
+                this.foo = foo;
+                this.bar = bar;
+            }
+        }
+
+        public MergeablePojo mergeableBean;
+
+        @JsonCreator
+        public ConstructorArgsPojo(@JsonMerge @JsonProperty("mergeableBean") MergeablePojo mergeableBean) {
+            this.mergeableBean = mergeableBean;
+        }
+    }
+
     /*
     /********************************************************
     /* Test methods, POJO merging
     /********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper()
+    private final ObjectMapper MAPPER = jsonMapperBuilder()
             // 26-Oct-2016, tatu: Make sure we'll report merge problems by default
             .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)
-    ;
+            .build();
 
     public void testBeanMergingViaProp() throws Exception
     {
@@ -118,7 +138,7 @@
         assertEquals(0, config.loc.b); // not passed, nor merge from original
 
         // but with type-overrides
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.configOverride(AB.class).setMergeable(true);
         config = mapper.readValue(aposToQuotes("{'loc':{'a':3}}"), NonMergeConfig.class);
         assertEquals(3, config.loc.a);
@@ -128,7 +148,7 @@
     public void testBeanMergingViaGlobal() throws Exception
     {
         // but with type-overrides
-        ObjectMapper mapper = newObjectMapper()
+        ObjectMapper mapper = newJsonMapper()
                 .setDefaultMergeable(true);
         NonMergeConfig config = mapper.readValue(aposToQuotes("{'loc':{'a':3}}"), NonMergeConfig.class);
         assertEquals(3, config.loc.a);
@@ -155,6 +175,24 @@
 
     /*
     /********************************************************
+    /* Test methods, Creators
+    /********************************************************
+     */
+
+    // [databind#2280]
+    public void testBeanMergeUsingConstructors() throws Exception {
+        ConstructorArgsPojo input = new ConstructorArgsPojo(new ConstructorArgsPojo.MergeablePojo("foo", "bar"));
+
+        ConstructorArgsPojo result = MAPPER.setDefaultMergeable(true)
+                .readerForUpdating(input)
+                .readValue(aposToQuotes("{'mergeableBean': {'foo': 'newFoo'}}"));
+
+        assertEquals("newFoo", result.mergeableBean.foo);
+        assertEquals("bar", result.mergeableBean.bar);
+    }
+
+    /*
+    /********************************************************
     /* Test methods, as array
     /********************************************************
      */
@@ -216,9 +254,9 @@
 
     public void testInvalidPropertyMerge() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper()
-                .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE);
-        
+        ObjectMapper mapper = jsonMapperBuilder()
+                .disable(MapperFeature.IGNORE_MERGE_FOR_UNMERGEABLE)
+                .build();
         try {
             mapper.readValue("{\"value\":3}", CantMergeInts.class);
             fail("Should not pass");
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/merge/UpdateValueTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/merge/UpdateValueTest.java
index ce38f86..d0535ae 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/merge/UpdateValueTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/merge/UpdateValueTest.java
@@ -36,7 +36,7 @@
         }
     }
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
     
     // [databind#318] (and Scala module issue #83]
     public void testValueUpdateWithCreator() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/validate/FullStreamReadTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/validate/FullStreamReadTest.java
new file mode 100644
index 0000000..7802870
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/validate/FullStreamReadTest.java
@@ -0,0 +1,301 @@
+package com.fasterxml.jackson.databind.deser.validate;
+
+import java.util.*;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.json.JsonReadFeature;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
+
+/**
+ * Test for validating {@link com.fasterxml.jackson.databind.DeserializationFeature#FAIL_ON_TRAILING_TOKENS}.
+ */
+public class FullStreamReadTest extends BaseMapTest
+{
+    private final static String JSON_OK_ARRAY = " [ 1, 2, 3]    ";
+    private final static String JSON_OK_ARRAY_WITH_COMMENT = JSON_OK_ARRAY + " // stuff ";
+
+    private final static String JSON_FAIL_ARRAY = JSON_OK_ARRAY + " [ ]";
+
+    private final static String JSON_OK_NULL = " null  ";
+    private final static String JSON_OK_NULL_WITH_COMMENT = " null /* stuff */ ";
+    private final static String JSON_FAIL_NULL = JSON_OK_NULL + " false";
+    
+    /*
+    /**********************************************************
+    /* Test methods, config
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = newJsonMapper();
+
+    public void testMapperAcceptTrailing() throws Exception
+    {
+        assertFalse(MAPPER.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS));
+
+        // by default, should be ok to read, all
+        _verifyArray(MAPPER.readTree(JSON_OK_ARRAY));
+        _verifyArray(MAPPER.readTree(JSON_OK_ARRAY_WITH_COMMENT));
+        _verifyArray(MAPPER.readTree(JSON_FAIL_ARRAY));
+
+        // and also via "untyped"
+        _verifyCollection(MAPPER.readValue(JSON_OK_ARRAY, List.class));
+        _verifyCollection(MAPPER.readValue(JSON_OK_ARRAY_WITH_COMMENT, List.class));
+        _verifyCollection(MAPPER.readValue(JSON_FAIL_ARRAY, List.class));
+
+        // ditto for getting `null` and some other token
+
+        assertTrue(MAPPER.readTree(JSON_OK_NULL).isNull());
+        assertTrue(MAPPER.readTree(JSON_OK_NULL_WITH_COMMENT).isNull());
+        assertTrue(MAPPER.readTree(JSON_FAIL_NULL).isNull());
+
+        assertNull(MAPPER.readValue(JSON_OK_NULL, Object.class));
+        assertNull(MAPPER.readValue(JSON_OK_NULL_WITH_COMMENT, Object.class));
+        assertNull(MAPPER.readValue(JSON_FAIL_NULL, Object.class));
+    }
+
+    public void testMapperFailOnTrailing() throws Exception
+    {
+        // but things change if we enforce checks
+        ObjectMapper strict = newJsonMapper()
+                .enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
+        assertTrue(strict.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS));
+
+        // some still ok
+        _verifyArray(strict.readTree(JSON_OK_ARRAY));
+        _verifyCollection(strict.readValue(JSON_OK_ARRAY, List.class));
+
+        // but if real content exists, will fail
+        try {
+            strict.readTree(JSON_FAIL_ARRAY);
+            fail("Should not have passed");
+        } catch (MismatchedInputException e) {
+            verifyException(e, "Trailing token (of type START_ARRAY)");
+            verifyException(e, "value (bound as `com.fasterxml.jackson.databind.JsonNode`)");
+        }
+
+        try {
+            strict.readValue(JSON_FAIL_ARRAY, List.class);
+            fail("Should not have passed");
+        } catch (MismatchedInputException e) {
+            verifyException(e, "Trailing token (of type START_ARRAY)");
+            verifyException(e, "value (bound as `java.util.List`)");
+        }
+
+        // others fail conditionally: will fail on comments unless enabled
+
+        try {
+            strict.readValue(JSON_OK_ARRAY_WITH_COMMENT, List.class);
+            fail("Should not have passed");
+        } catch (JsonParseException e) {
+            verifyException(e, "Unexpected character");
+            verifyException(e, "maybe a (non-standard) comment");
+        }
+        try {
+            strict.readTree(JSON_OK_ARRAY_WITH_COMMENT);
+            fail("Should not have passed");
+        } catch (JsonParseException e) {
+            verifyException(e, "Unexpected character");
+            verifyException(e, "maybe a (non-standard) comment");
+        }
+
+        ObjectReader strictWithComments = strict.reader()
+                .with(JsonReadFeature.ALLOW_JAVA_COMMENTS);
+        _verifyArray(strictWithComments.readTree(JSON_OK_ARRAY_WITH_COMMENT));
+        _verifyCollection((List<?>) strictWithComments.forType(List.class)
+                .readValue(JSON_OK_ARRAY_WITH_COMMENT));
+    }
+
+    public void testMapperFailOnTrailingWithNull() throws Exception
+    {
+        final ObjectMapper strict = newJsonMapper()
+                .enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
+
+        // some still ok
+        JsonNode n = strict.readTree(JSON_OK_NULL);
+        assertNotNull(n);
+        assertTrue(n.isNull());
+
+        // but if real content exists, will fail
+        try {
+            strict.readTree(JSON_FAIL_NULL);
+            fail("Should not have passed");
+        } catch (MismatchedInputException e) {
+            verifyException(e, "Trailing token (of type VALUE_FALSE)");
+            verifyException(e, "value (bound as `com.fasterxml.jackson.databind.JsonNode`)");
+        }
+
+        try {
+            strict.readValue(JSON_FAIL_NULL, List.class);
+            fail("Should not have passed");
+        } catch (MismatchedInputException e) {
+            verifyException(e, "Trailing token (of type VALUE_FALSE)");
+            verifyException(e, "value (bound as `java.util.List`)");
+        }
+
+        // others fail conditionally: will fail on comments unless enabled
+
+        try {
+            strict.readValue(JSON_OK_NULL_WITH_COMMENT, Object.class);
+            fail("Should not have passed");
+        } catch (JsonParseException e) {
+            verifyException(e, "Unexpected character");
+            verifyException(e, "maybe a (non-standard) comment");
+        }
+        try {
+            strict.readTree(JSON_OK_NULL_WITH_COMMENT);
+            fail("Should not have passed");
+        } catch (JsonParseException e) {
+            verifyException(e, "Unexpected character");
+            verifyException(e, "maybe a (non-standard) comment");
+        }
+
+        ObjectReader strictWithComments = strict.reader()
+                .with(JsonReadFeature.ALLOW_JAVA_COMMENTS);
+        n = strictWithComments.readTree(JSON_OK_NULL);
+        assertNotNull(n);
+        assertTrue(n.isNull());
+
+        Object ob = strictWithComments.forType(List.class)
+                .readValue(JSON_OK_NULL_WITH_COMMENT);
+        assertNull(ob);
+    }
+    
+    public void testReaderAcceptTrailing() throws Exception
+    {
+        ObjectReader R = MAPPER.reader();
+        assertFalse(R.isEnabled(DeserializationFeature.FAIL_ON_TRAILING_TOKENS));
+
+        _verifyArray(R.readTree(JSON_OK_ARRAY));
+        _verifyArray(R.readTree(JSON_OK_ARRAY_WITH_COMMENT));
+        _verifyArray(R.readTree(JSON_FAIL_ARRAY));
+        ObjectReader rColl = R.forType(List.class);
+        _verifyCollection((List<?>)rColl.readValue(JSON_OK_ARRAY));
+        _verifyCollection((List<?>)rColl.readValue(JSON_OK_ARRAY_WITH_COMMENT));
+        _verifyCollection((List<?>)rColl.readValue(JSON_FAIL_ARRAY));
+    }
+
+    public void testReaderFailOnTrailing() throws Exception
+    {
+        ObjectReader strictR = MAPPER.reader().with(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
+        ObjectReader strictRForList = strictR.forType(List.class);
+        _verifyArray(strictR.readTree(JSON_OK_ARRAY));
+        _verifyCollection((List<?>)strictRForList.readValue(JSON_OK_ARRAY));
+
+        // Will fail hard if there is a trailing token
+        try {
+            strictRForList.readValue(JSON_FAIL_ARRAY);
+            fail("Should not have passed");
+        } catch (MismatchedInputException e) {
+            verifyException(e, "Trailing token (of type START_ARRAY)");
+            verifyException(e, "value (bound as `java.util.List`)");
+        }
+        try {
+            strictR.readTree(JSON_FAIL_ARRAY);
+            fail("Should not have passed");
+        } catch (MismatchedInputException e) {
+            verifyException(e, "Trailing token (of type START_ARRAY)");
+            verifyException(e, "value (bound as `com.fasterxml.jackson.databind.JsonNode`)");
+        }
+
+        // ... also verify that same happens with "value to update"
+        try {
+            strictR.withValueToUpdate(new ArrayList<Object>())
+                .readValue(JSON_FAIL_ARRAY);
+            fail("Should not have passed");
+        } catch (MismatchedInputException e) {
+            verifyException(e, "Trailing token (of type START_ARRAY)");
+            verifyException(e, "value (bound as `java.util.ArrayList`)");
+        }
+
+        // others conditionally: will fail on comments unless enabled
+
+        try {
+            strictRForList.readValue(JSON_OK_ARRAY_WITH_COMMENT);
+            fail("Should not have passed");
+        } catch (JsonParseException e) {
+            verifyException(e, "Unexpected character");
+            verifyException(e, "maybe a (non-standard) comment");
+        }
+        try {
+            strictR.readTree(JSON_OK_ARRAY_WITH_COMMENT);
+            fail("Should not have passed");
+        } catch (JsonParseException e) {
+            verifyException(e, "Unexpected character");
+            verifyException(e, "maybe a (non-standard) comment");
+        }
+
+        // but works if comments enabled etc
+
+        ObjectReader strictRWithComments = strictR.with(JsonReadFeature.ALLOW_JAVA_COMMENTS);
+        
+        _verifyCollection((List<?>)strictRWithComments.forType(List.class).readValue(JSON_OK_ARRAY_WITH_COMMENT));
+        _verifyArray(strictRWithComments.readTree(JSON_OK_ARRAY_WITH_COMMENT));
+    }
+
+    public void testReaderFailOnTrailingWithNull() throws Exception
+    {
+        ObjectReader strictR = MAPPER.reader().with(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
+        ObjectReader strictRForList = strictR.forType(List.class);
+        JsonNode n = strictR.readTree(JSON_OK_NULL);
+        assertTrue(n.isNull());
+
+        // Will fail hard if there is a trailing token
+        try {
+            strictRForList.readValue(JSON_FAIL_NULL);
+            fail("Should not have passed");
+        } catch (MismatchedInputException e) {
+            verifyException(e, "Trailing token (of type VALUE_FALSE)");
+            verifyException(e, "value (bound as `java.util.List`)");
+        }
+
+        try {
+            strictR.readTree(JSON_FAIL_NULL);
+            fail("Should not have passed");
+        } catch (MismatchedInputException e) {
+            verifyException(e, "Trailing token (of type VALUE_FALSE)");
+            verifyException(e, "value (bound as `com.fasterxml.jackson.databind.JsonNode`)");
+        }
+
+        // others conditionally: will fail on comments unless enabled
+
+        try {
+            strictRForList.readValue(JSON_OK_NULL_WITH_COMMENT);
+            fail("Should not have passed");
+        } catch (JsonParseException e) {
+            verifyException(e, "Unexpected character");
+            verifyException(e, "maybe a (non-standard) comment");
+        }
+        try {
+            strictR.readTree(JSON_OK_NULL_WITH_COMMENT);
+            fail("Should not have passed");
+        } catch (JsonParseException e) {
+            verifyException(e, "Unexpected character");
+            verifyException(e, "maybe a (non-standard) comment");
+        }
+
+        // but works if comments enabled etc
+
+        ObjectReader strictRWithComments = strictR.with(JsonReadFeature.ALLOW_JAVA_COMMENTS);
+        Object ob = strictRWithComments.forType(List.class).readValue(JSON_OK_NULL_WITH_COMMENT);
+        assertNull(ob);
+    }
+    
+    private void _verifyArray(JsonNode n) throws Exception
+    {
+        assertTrue(n.isArray());
+        assertEquals(3, n.size());
+    }
+
+    private void _verifyCollection(List<?> coll) throws Exception
+    {
+        assertEquals(3, coll.size());
+        assertEquals(Integer.valueOf(1), coll.get(0));
+        assertEquals(Integer.valueOf(2), coll.get(1));
+        assertEquals(Integer.valueOf(3), coll.get(2));
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/exc/BasicExceptionTest.java b/src/test/java/com/fasterxml/jackson/databind/exc/BasicExceptionTest.java
index 3c4d2bb..75e1198 100644
--- a/src/test/java/com/fasterxml/jackson/databind/exc/BasicExceptionTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/exc/BasicExceptionTest.java
@@ -1,20 +1,19 @@
 package com.fasterxml.jackson.databind.exc;
 
 import java.io.StringWriter;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Map;
 
 import com.fasterxml.jackson.core.*;
-import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
 public class BasicExceptionTest extends BaseMapTest
 {
-    final ObjectMapper MAPPER = new ObjectMapper();
-    final JsonFactory JSON_F = MAPPER.getFactory();
+    private final ObjectMapper MAPPER = newJsonMapper();
+    private final JsonFactory JSON_F = MAPPER.getFactory();
 
     public void testBadDefinition() throws Exception
     {
@@ -114,18 +113,30 @@
     }
 
     // [databind#2128]: ensure Location added once and only once
+    // [databind#2482]: ensure Location is the original one
     public void testLocationAddition() throws Exception
     {
+        String problemJson = "{\n\t\"userList\" : [\n\t{\n\t user : \"1\"\n\t},\n\t{\n\t \"user\" : \"2\"\n\t}\n\t]\n}";
         try {
-            /*Map<?,?> map =*/ MAPPER.readValue("{\"value\":\"foo\"}",
-                    new TypeReference<Map<ABC, Integer>>() { });
+            MAPPER.readValue(problemJson, Users.class);
             fail("Should not pass");
-        } catch (MismatchedInputException e) {
+        } catch (JsonMappingException e) { // becomes "generic" due to wrapping for passing path info
             String msg = e.getMessage();
             String[] str = msg.split(" at \\[");
             if (str.length != 2) {
                 fail("Should only get one 'at [' marker, got "+(str.length-1)+", source: "+msg);
             }
+            JsonLocation loc = e.getLocation();
+//          String expectedLocation = "line: 4, column: 4";
+            assertEquals(4, loc.getLineNr());
+            assertEquals(4, loc.getColumnNr());
         }
     }
+    static class User {
+        public String user;
+    }
+
+    static class Users {
+        public ArrayList<User> userList;
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/exc/DeserExceptionTypeTest.java b/src/test/java/com/fasterxml/jackson/databind/exc/DeserExceptionTypeTest.java
index 3b794c2..33a5be9 100644
--- a/src/test/java/com/fasterxml/jackson/databind/exc/DeserExceptionTypeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/exc/DeserExceptionTypeTest.java
@@ -6,6 +6,7 @@
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.exc.MismatchedInputException;
 import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
+import com.fasterxml.jackson.databind.testutil.BrokenStringReader;
 
 /**
  * Unit test for verifying that exceptions are properly handled (caught,
diff --git a/src/test/java/com/fasterxml/jackson/databind/exc/StackTraceElementTest.java b/src/test/java/com/fasterxml/jackson/databind/exc/StackTraceElementTest.java
index 2ed2786..65d7374 100644
--- a/src/test/java/com/fasterxml/jackson/databind/exc/StackTraceElementTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/exc/StackTraceElementTest.java
@@ -26,7 +26,7 @@
     // for [databind#1794] where extra `declaringClass` is serialized from private field.
     public void testCustomStackTraceDeser() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
 
         String json = mapper
diff --git a/src/test/java/com/fasterxml/jackson/databind/exc/TestExceptionsDuringWriting.java b/src/test/java/com/fasterxml/jackson/databind/exc/TestExceptionsDuringWriting.java
index 6c96343..87e7fa3 100644
--- a/src/test/java/com/fasterxml/jackson/databind/exc/TestExceptionsDuringWriting.java
+++ b/src/test/java/com/fasterxml/jackson/databind/exc/TestExceptionsDuringWriting.java
@@ -6,6 +6,7 @@
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.testutil.BrokenStringWriter;
 
 /**
  * Unit test for verifying that exceptions are properly handled (caught,
diff --git a/src/test/java/com/fasterxml/jackson/databind/ext/TestJava7Types.java b/src/test/java/com/fasterxml/jackson/databind/ext/TestJava7Types.java
index b18b8d1..ef89629 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ext/TestJava7Types.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ext/TestJava7Types.java
@@ -5,10 +5,8 @@
 
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
-/**
- * @since 2.7
- */
 public class TestJava7Types extends BaseMapTest
 {
     public void testPathRoundtrip() throws Exception
@@ -30,8 +28,10 @@
     // [databind#1688]:
     public void testPolymorphicPath() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(DefaultTyping.NON_FINAL);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        DefaultTyping.NON_FINAL)
+                .build();
         Path input = Paths.get("/tmp", "foo.txt");
 
         String json = mapper.writeValueAsString(new Object[] { input });
diff --git a/src/test/java/com/fasterxml/jackson/databind/format/BooleanFormatTest.java b/src/test/java/com/fasterxml/jackson/databind/format/BooleanFormatTest.java
index 5794cf2..04946b2 100644
--- a/src/test/java/com/fasterxml/jackson/databind/format/BooleanFormatTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/format/BooleanFormatTest.java
@@ -50,13 +50,13 @@
     /**********************************************************
      */
 
-    private final static ObjectMapper MAPPER = newObjectMapper();
+    private final static ObjectMapper MAPPER = newJsonMapper();
 
     public void testShapeViaDefaults() throws Exception
     {
         assertEquals(aposToQuotes("{'b':true}"),
                 MAPPER.writeValueAsString(new BooleanWrapper(true)));
-        ObjectMapper m = newObjectMapper();
+        ObjectMapper m = newJsonMapper();
         m.configOverride(Boolean.class)
             .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.NUMBER));
         assertEquals(aposToQuotes("{'b':1}"),
diff --git a/src/test/java/com/fasterxml/jackson/databind/format/CollectionFormatShapeTest.java b/src/test/java/com/fasterxml/jackson/databind/format/CollectionFormatShapeTest.java
index 6eea8fe..36adbde 100644
--- a/src/test/java/com/fasterxml/jackson/databind/format/CollectionFormatShapeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/format/CollectionFormatShapeTest.java
@@ -40,7 +40,7 @@
     /**********************************************************
      */
 
-    private final static ObjectMapper MAPPER = newObjectMapper();    
+    private final static ObjectMapper MAPPER = newJsonMapper();    
 
     public void testListAsObjectRoundtrip() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/format/DateFormatTest.java b/src/test/java/com/fasterxml/jackson/databind/format/DateFormatTest.java
index f94bd02..546fcf9 100644
--- a/src/test/java/com/fasterxml/jackson/databind/format/DateFormatTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/format/DateFormatTest.java
@@ -18,7 +18,7 @@
 
     public void testTypeDefaults() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         mapper.configOverride(Date.class)
             .setFormat(JsonFormat.Value.forPattern("yyyy.dd.MM"));
         // First serialize, should result in this (in UTC):
diff --git a/src/test/java/com/fasterxml/jackson/databind/format/EnumFormatShapeTest.java b/src/test/java/com/fasterxml/jackson/databind/format/EnumFormatShapeTest.java
index 9a376a1..92267bd 100644
--- a/src/test/java/com/fasterxml/jackson/databind/format/EnumFormatShapeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/format/EnumFormatShapeTest.java
@@ -97,7 +97,7 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     // Tests for JsonFormat.shape
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/format/MapEntryFormatTest.java b/src/test/java/com/fasterxml/jackson/databind/format/MapEntryFormatTest.java
index ce875a5..c85e5db 100644
--- a/src/test/java/com/fasterxml/jackson/databind/format/MapEntryFormatTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/format/MapEntryFormatTest.java
@@ -103,7 +103,7 @@
     /**********************************************************
      */
     
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     public void testInclusion() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java b/src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java
deleted file mode 100644
index 5ccb0fb..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/interop/IllegalTypesCheckTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package com.fasterxml.jackson.databind.interop;
-
-import java.util.*;
-
-import org.springframework.jacksontest.BogusApplicationContext;
-import org.springframework.jacksontest.BogusPointcutAdvisor;
-import org.springframework.jacksontest.GrantedAuthority;
-
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
-
-import com.mchange.v2.c3p0.jacksontest.ComboPooledDataSource;
-
-/**
- * Test case(s) to guard against handling of types that are illegal to handle
- * due to security constraints.
- */
-public class IllegalTypesCheckTest extends BaseMapTest
-{
-    static class Bean1599 {
-        public int id;
-        public Object obj;
-    }
-
-    static class PolyWrapper {
-        @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,
-                include = JsonTypeInfo.As.WRAPPER_ARRAY)
-        public Object v;
-    }
-
-    static class Authentication1872 {
-         public List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
-    }
-
-    /*
-    /**********************************************************
-    /* Unit tests
-    /**********************************************************
-     */
-
-    private final ObjectMapper MAPPER = objectMapper();
-
-    // // // Tests for [databind#1599]
-
-    public void testXalanTypes1599() throws Exception
-    {
-        final String clsName = "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";
-        final String JSON = aposToQuotes(
- "{'id': 124,\n"
-+" 'obj':[ '"+clsName+"',\n"
-+"  {\n"
-+"    'transletBytecodes' : [ 'AAIAZQ==' ],\n"
-+"    'transletName' : 'a.b',\n"
-+"    'outputProperties' : { }\n"
-+"  }\n"
-+" ]\n"
-+"}"
-        );
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping();
-        try {
-            mapper.readValue(JSON, Bean1599.class);
-            fail("Should not pass");
-        } catch (JsonMappingException e) {
-            _verifySecurityException(e, clsName);
-        }
-    }
-
-    // // // Tests for [databind#1737]
-
-    public void testJDKTypes1737() throws Exception
-    {
-        _testIllegalType(java.util.logging.FileHandler.class);
-        _testIllegalType(java.rmi.server.UnicastRemoteObject.class);
-    }
-
-    // // // Tests for [databind#1855]
-    public void testJDKTypes1855() throws Exception
-    {
-        // apparently included by JDK?
-        _testIllegalType("com.sun.org.apache.bcel.internal.util.ClassLoader");
-
-        // also: we can try some form of testing, even if bit contrived...
-        _testIllegalType(BogusPointcutAdvisor.class);
-        _testIllegalType(BogusApplicationContext.class);
-    }
-
-    // 17-Aug-2017, tatu: Ideally would test handling of 3rd party types, too,
-    //    but would require adding dependencies. This may be practical when
-    //    checking done by separate module, but for now let's not do that for databind.
-
-    /*
-    public void testSpringTypes1737() throws Exception
-    {
-        _testIllegalType("org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor");
-        _testIllegalType("org.springframework.beans.factory.config.PropertyPathFactoryBean");
-    }
-    */
-
-    // // // Tests for [databind#1872]
-    public void testJDKTypes1872() throws Exception
-    {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
-
-        String json = aposToQuotes(String.format("{'@class':'%s','authorities':['java.util.ArrayList',[]]}",
-                Authentication1872.class.getName()));
-        Authentication1872 result = mapper.readValue(json, Authentication1872.class);
-        assertNotNull(result);
-    }
-
-    // [databind#1931]
-    public void testC3P0Types() throws Exception
-    {
-        _testIllegalType(ComboPooledDataSource.class); // [databind#1931]
-    }
-
-    private void _testIllegalType(Class<?> nasty) throws Exception {
-        _testIllegalType(nasty.getName());
-    }
-
-    private void _testIllegalType(String clsName) throws Exception
-    {
-        // While usually exploited via default typing let's not require
-        // it here; mechanism still the same
-        String json = aposToQuotes(
-                "{'v':['"+clsName+"','/tmp/foobar.txt']}"
-                );
-        try {
-            MAPPER.readValue(json, PolyWrapper.class);
-            fail("Should not pass");
-        } catch (JsonMappingException e) {
-            _verifySecurityException(e, clsName);
-        }
-    }
-
-    protected void _verifySecurityException(Throwable t, String clsName) throws Exception
-    {
-        _verifyException(t, InvalidDefinitionException.class,
-            "Illegal type",
-            "to deserialize",
-            "prevented for security reasons");
-        verifyException(t, clsName);
-    }
-
-    protected void _verifyException(Throwable t, Class<?> expExcType,
-            String... patterns) throws Exception
-    {
-        Class<?> actExc = t.getClass();
-        if (!expExcType.isAssignableFrom(actExc)) {
-            fail("Expected Exception of type '"+expExcType.getName()+"', got '"
-                    +actExc.getName()+"', message: "+t.getMessage());
-        }
-        for (String pattern : patterns) {
-            verifyException(t, pattern);
-        }
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/AutoDetect1947Test.java b/src/test/java/com/fasterxml/jackson/databind/introspect/AutoDetect1947Test.java
index c048917..6956e96 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/AutoDetect1947Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/AutoDetect1947Test.java
@@ -30,12 +30,13 @@
     }
     public void testDisablingAll() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper()
+        ObjectMapper mapper = jsonMapperBuilder()
                 .disable(MapperFeature.AUTO_DETECT_SETTERS)
                 .disable(MapperFeature.AUTO_DETECT_FIELDS)
                 .disable(MapperFeature.AUTO_DETECT_GETTERS)
                 .disable(MapperFeature.AUTO_DETECT_CREATORS)
-                .disable(MapperFeature.AUTO_DETECT_IS_GETTERS);
+                .disable(MapperFeature.AUTO_DETECT_IS_GETTERS)
+                .build();
         String json = mapper.writeValueAsString(new Entity1947());
         JsonNode n = mapper.readTree(json);
         assertEquals(1, n.size());
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/BeanNamingTest.java b/src/test/java/com/fasterxml/jackson/databind/introspect/BeanNamingTest.java
index d01de89..943a827 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/BeanNamingTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/BeanNamingTest.java
@@ -26,8 +26,9 @@
         assertEquals(aposToQuotes("{'a':3}"),
                 mapper.writeValueAsString(new ABean()));
 
-        mapper = new ObjectMapper();
-        mapper.enable(MapperFeature.USE_STD_BEAN_NAMING);
+        mapper = jsonMapperBuilder()
+                .enable(MapperFeature.USE_STD_BEAN_NAMING)
+                .build();
         assertEquals(aposToQuotes("{'URL':'http://foo'}"),
                 mapper.writeValueAsString(new URLBean()));
         assertEquals(aposToQuotes("{'a':3}"),
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/IgnoredFieldPresentInCreatorProperty2001Test.java b/src/test/java/com/fasterxml/jackson/databind/introspect/IgnoredFieldPresentInCreatorProperty2001Test.java
index a551c0a..65098e5 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/IgnoredFieldPresentInCreatorProperty2001Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/IgnoredFieldPresentInCreatorProperty2001Test.java
@@ -21,7 +21,7 @@
     }
 
     public void testIgnoredFieldPresentInPropertyCreator() throws Exception {
-        Foo deserialized = newObjectMapper().readValue("{\"query\": \"bar\"}", Foo.class);
+        Foo deserialized = newJsonMapper().readValue("{\"query\": \"bar\"}", Foo.class);
         assertEquals("bar", deserialized.query);
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollectorTest.java b/src/test/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollectorTest.java
index 378b135..774cde4 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollectorTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollectorTest.java
@@ -359,8 +359,9 @@
 
     public void testGlobalVisibilityForGetters()
     {
-        ObjectMapper m = new ObjectMapper();
-        m.configure(MapperFeature.AUTO_DETECT_GETTERS, false);
+        ObjectMapper m = jsonMapperBuilder()
+                .configure(MapperFeature.AUTO_DETECT_GETTERS, false)
+                .build();
         POJOPropertiesCollector coll = collector(m, SimpleGetterVisibility.class, true);
         // should be 1, expect that we disabled getter auto-detection, so
         Map<String, POJOPropertyBuilder> props = coll.getPropertyMap();
@@ -426,8 +427,9 @@
     public void testUseAnnotationsFalse() throws Exception
     {
         // note: need a separate mapper, need to reconfigure
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.configure(MapperFeature.USE_ANNOTATIONS, false);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .configure(MapperFeature.USE_ANNOTATIONS, false)
+                .build();
         BasicBeanDescription beanDesc = mapper.getSerializationConfig().introspect(mapper.constructType(Jackson703.class));
         assertNotNull(beanDesc);
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestInferredMutators.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestInferredMutators.java
index 0707790..8399490 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestInferredMutators.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestInferredMutators.java
@@ -33,7 +33,9 @@
         ObjectMapper mapper = new ObjectMapper();
         // default value is 'enabled', for backwards compatibility
         assertTrue(mapper.isEnabled(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS));
-        mapper.disable(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS);
+        mapper = jsonMapperBuilder()
+                .disable(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS)
+                .build();
         try {
             /*p =*/ mapper.readValue("{\"x\":2}", FixedPoint.class);
             fail("Should not try to use final field");
@@ -53,8 +55,9 @@
         assertEquals(2, p.x);
 
         // but without it, should fail:
-        mapper = new ObjectMapper();
-        mapper.disable(MapperFeature.INFER_PROPERTY_MUTATORS);
+        mapper = jsonMapperBuilder()
+                .disable(MapperFeature.INFER_PROPERTY_MUTATORS)
+                .build();
         try {
             p = mapper.readValue(JSON,  Point.class);
             fail("Should not succeeed");
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestNamingStrategyStd.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestNamingStrategyStd.java
index f231f0c..aaa0b15 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestNamingStrategyStd.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestNamingStrategyStd.java
@@ -338,6 +338,39 @@
                 FirstNameBean.class);

         assertEquals("Billy", result.firstName);

     }

+    /*

+    /**********************************************************

+    /* Test methods for LOWER_DOT_CASE

+    /**********************************************************

+     */

+

+    public void testLowerCaseWithDotsStrategyStandAlone()

+    {

+        assertEquals("some.value",

+            PropertyNamingStrategy.LOWER_DOT_CASE.nameForField(null, null, "someValue"));

+        assertEquals("some.value",

+            PropertyNamingStrategy.LOWER_DOT_CASE.nameForField(null, null, "SomeValue"));

+        assertEquals("url",

+            PropertyNamingStrategy.LOWER_DOT_CASE.nameForField(null, null, "URL"));

+        assertEquals("url.stuff",

+            PropertyNamingStrategy.LOWER_DOT_CASE.nameForField(null, null, "URLStuff"));

+        assertEquals("some.url.stuff",

+            PropertyNamingStrategy.LOWER_DOT_CASE.nameForField(null, null, "SomeURLStuff"));

+    }

+

+    public void testSimpleLowerCaseWithDots() throws Exception

+    {

+        final ObjectMapper m = jsonMapperBuilder()

+            .propertyNamingStrategy(PropertyNamingStrategy.LOWER_DOT_CASE)

+            .build();

+

+        final FirstNameBean input = new FirstNameBean("Bob");

+        assertEquals(aposToQuotes("{'first.name':'Bob'}"), m.writeValueAsString(input));

+

+        FirstNameBean result = m.readValue(aposToQuotes("{'first.name':'Billy'}"),

+                FirstNameBean.class);

+        assertEquals("Billy", result.firstName);

+    }

 

     /*

     /**********************************************************

@@ -365,17 +398,19 @@
 

     public void testExplicitRename() throws Exception

     {

-        ObjectMapper m = new ObjectMapper();

-        m.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

-        m.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);

+        ObjectMapper m = jsonMapperBuilder()

+                .propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)

+                .enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)

+                .build();

         // by default, renaming will not take place on explicitly named fields

         assertEquals(aposToQuotes("{'firstName':'Peter','lastName':'Venkman','user_age':'35'}"),

                 m.writeValueAsString(new ExplicitBean()));

 

-        m = new ObjectMapper();

-        m.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

-        m.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);

-        m.enable(MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING);

+        m = jsonMapperBuilder()

+                .propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)

+                .enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)

+                .enable(MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING)

+                .build();

         // w/ feature enabled, ALL property names should get re-written

         assertEquals(aposToQuotes("{'first_name':'Peter','last_name':'Venkman','user_age':'35'}"),

                 m.writeValueAsString(new ExplicitBean()));

diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestPropertyConflicts.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestPropertyConflicts.java
index 5bd431a..9439c64 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestPropertyConflicts.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestPropertyConflicts.java
@@ -116,8 +116,9 @@
 
     public void testInferredNameConflictsWithGetters() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.setAnnotationIntrospector(new InferingIntrospector());
+        ObjectMapper mapper = jsonMapperBuilder()
+                .annotationIntrospector(new InferingIntrospector())
+                .build();
         String json = mapper.writeValueAsString(new Infernal());
         assertEquals(aposToQuotes("{'name':'Bob'}"), json);
     }
@@ -131,15 +132,15 @@
     }
 
     public void testIssue541() throws Exception {
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.disable(
+        ObjectMapper mapper = jsonMapperBuilder()
+                .disable(
                 MapperFeature.AUTO_DETECT_CREATORS,
                 MapperFeature.AUTO_DETECT_FIELDS,
                 MapperFeature.AUTO_DETECT_GETTERS,
                 MapperFeature.AUTO_DETECT_IS_GETTERS,
                 MapperFeature.AUTO_DETECT_SETTERS,
                 MapperFeature.USE_GETTERS_AS_SETTERS
-        );
+                        ).build();
         Bean541 data = mapper.readValue("{\"str\":\"the string\"}", Bean541.class);
         if (data == null) {
             throw new IllegalStateException("data is null");
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TransientTest.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TransientTest.java
index 882c399..c00bcea 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/TransientTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TransientTest.java
@@ -63,8 +63,9 @@
                 MAPPER.writeValueAsString(new SimplePrunableTransient()));
 
         // but may change that
-        ObjectMapper m = new ObjectMapper()
-            .enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER);
+        ObjectMapper m = jsonMapperBuilder()
+            .enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER)
+            .build();
         assertEquals(aposToQuotes("{'x':42}"),
                 m.writeValueAsString(new ClassyTransient()));
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/VisibilityForSerializationTest.java b/src/test/java/com/fasterxml/jackson/databind/introspect/VisibilityForSerializationTest.java
index 949ba6e..ce98b2e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/introspect/VisibilityForSerializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/introspect/VisibilityForSerializationTest.java
@@ -91,8 +91,9 @@
 
         // Then auto-detection disabled. But note: we MUST create a new
         // mapper, since old version of serializer may be cached by now
-        m = new ObjectMapper();
-        m.configure(MapperFeature.AUTO_DETECT_GETTERS, false);
+        m = jsonMapperBuilder()
+                .configure(MapperFeature.AUTO_DETECT_GETTERS, false)
+                .build();
         result = writeAndMap(m, new GetterClass());
         assertEquals(1, result.size());
         assertTrue(result.containsKey("x"));
@@ -107,7 +108,9 @@
         assertTrue(result.containsKey("x"));
 
         // And then class-level auto-detection enabling, should override defaults
-        m.configure(MapperFeature.AUTO_DETECT_GETTERS, true);
+        m = jsonMapperBuilder()
+                .configure(MapperFeature.AUTO_DETECT_GETTERS, true)
+                .build();
         result = writeAndMap(m, new EnabledGetterClass());
         assertEquals(2, result.size());
         assertTrue(result.containsKey("x"));
@@ -116,10 +119,11 @@
 
     public void testPerClassAutoDetectionForIsGetter() throws IOException
     {
-        ObjectMapper m = new ObjectMapper();
+        ObjectMapper m = jsonMapperBuilder()
         // class level should override
-        m.configure(MapperFeature.AUTO_DETECT_GETTERS, true);
-        m.configure(MapperFeature.AUTO_DETECT_IS_GETTERS, false);
+                .configure(MapperFeature.AUTO_DETECT_GETTERS, true)
+                .configure(MapperFeature.AUTO_DETECT_IS_GETTERS, false)
+                .build();
         Map<String,Object> result = writeAndMap(m, new EnabledIsGetterClass());
         assertEquals(0, result.size());
         assertFalse(result.containsKey("ok"));
@@ -131,24 +135,27 @@
         ObjectMapper m = new ObjectMapper();
         assertTrue(m.isEnabled(MapperFeature.AUTO_DETECT_SETTERS));
         assertTrue(m.isEnabled(MapperFeature.AUTO_DETECT_GETTERS));
-        m.configure(MapperFeature.AUTO_DETECT_SETTERS, false)
-            .configure(MapperFeature.AUTO_DETECT_GETTERS, false);
+        m = jsonMapperBuilder()
+                .configure(MapperFeature.AUTO_DETECT_SETTERS, false)
+                .configure(MapperFeature.AUTO_DETECT_GETTERS, false)
+                .build();
         assertFalse(m.isEnabled(MapperFeature.AUTO_DETECT_SETTERS));
         assertFalse(m.isEnabled(MapperFeature.AUTO_DETECT_GETTERS));
     }
 
     public void testVisibilityFeatures() throws Exception
     {
-        ObjectMapper om = new ObjectMapper();
+        ObjectMapper om = jsonMapperBuilder()
         // Only use explicitly specified values to be serialized/deserialized (i.e., JSONProperty).
-        om.configure(MapperFeature.AUTO_DETECT_FIELDS, false);
-        om.configure(MapperFeature.AUTO_DETECT_GETTERS, false);
-        om.configure(MapperFeature.AUTO_DETECT_SETTERS, false);
-        om.configure(MapperFeature.AUTO_DETECT_IS_GETTERS, false);
-        om.configure(MapperFeature.USE_GETTERS_AS_SETTERS, false);
-        om.configure(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS, true);
-        om.configure(MapperFeature.INFER_PROPERTY_MUTATORS, false);
-        om.configure(MapperFeature.USE_ANNOTATIONS, true);
+                .configure(MapperFeature.AUTO_DETECT_FIELDS, false)
+                .configure(MapperFeature.AUTO_DETECT_GETTERS, false)
+            .configure(MapperFeature.AUTO_DETECT_SETTERS, false)
+            .configure(MapperFeature.AUTO_DETECT_IS_GETTERS, false)
+            .configure(MapperFeature.USE_GETTERS_AS_SETTERS, false)
+            .configure(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS, true)
+            .configure(MapperFeature.INFER_PROPERTY_MUTATORS, false)
+            .configure(MapperFeature.USE_ANNOTATIONS, true)
+            .build();
 
         JavaType javaType = om.getTypeFactory().constructType(TCls.class);        
         BeanDescription desc = (BeanDescription) om.getSerializationConfig().introspect(javaType);
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsonschema/NewSchemaTest.java b/src/test/java/com/fasterxml/jackson/databind/jsonschema/NewSchemaTest.java
index e62a025..14acfe1 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsonschema/NewSchemaTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsonschema/NewSchemaTest.java
@@ -202,8 +202,8 @@
     /* Test methods
     /**********************************************************
      */
-    
-    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     /* Silly little test for simply triggering traversal, without attempting to
      * verify what is being reported. Smoke test that should trigger problems
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsonschema/SchemaWithUUIDTest.java b/src/test/java/com/fasterxml/jackson/databind/jsonschema/SchemaWithUUIDTest.java
new file mode 100644
index 0000000..2387960
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsonschema/SchemaWithUUIDTest.java
@@ -0,0 +1,37 @@
+package com.fasterxml.jackson.databind.jsonschema;
+
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicReference;
+
+import com.fasterxml.jackson.databind.*;
+
+import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
+import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonStringFormatVisitor;
+import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonValueFormat;
+
+public class SchemaWithUUIDTest extends BaseMapTest
+{
+    private final ObjectMapper MAPPER = newJsonMapper();
+
+    public void testUUIDSchema() throws Exception
+    {
+        final AtomicReference<JsonValueFormat> format = new AtomicReference<>();
+
+        MAPPER.acceptJsonFormatVisitor(UUID.class, new JsonFormatVisitorWrapper.Base() {
+            @Override
+            public JsonStringFormatVisitor expectStringFormat(JavaType type) {
+                return new JsonStringFormatVisitor() {
+                    @Override
+                    public void enumTypes(Set<String> enums) { }
+
+                    @Override
+                    public void format(JsonValueFormat f) {
+                        format.set(f);
+                    }
+                };
+            }
+        });
+        assertEquals(JsonValueFormat.UUID, format.get());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/GenericNestedType2331Test.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/GenericNestedType2331Test.java
new file mode 100644
index 0000000..0059efe
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/GenericNestedType2331Test.java
@@ -0,0 +1,40 @@
+package com.fasterxml.jackson.databind.jsontype;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.databind.*;
+
+// [databind#2331]
+public class GenericNestedType2331Test extends BaseMapTest
+{
+    static class SuperNode<T> { }
+    static class SuperTestClass { }
+    
+    @SuppressWarnings("serial")
+    static class Node<T extends SuperTestClass & Cloneable> extends SuperNode<Node<T>> implements Serializable {
+
+        public List<Node<T>> children;
+
+        public Node() {
+            children = new ArrayList<Node<T>>();
+        }
+
+        /**
+         * The Wildcard here seems to be the Issue.
+         * If we remove this full getter, everything is working as expected.
+         */
+        public List<? extends SuperNode<Node<T>>> getChildren() {
+            return children;
+        }
+    }    
+    
+    public void testGeneric2331() throws Exception {
+        Node root = new Node();
+        root.children.add(new Node());
+
+        String json = newJsonMapper().writeValueAsString(root);
+        assertNotNull(json);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/NoTypeInfoTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/NoTypeInfoTest.java
index 65054d5..55d60b0 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/NoTypeInfoTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/NoTypeInfoTest.java
@@ -4,6 +4,7 @@
 
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class NoTypeInfoTest extends BaseMapTest
 {
@@ -24,8 +25,9 @@
 
     public void testWithIdNone() throws Exception
     {
-        final ObjectMapper mapper = newObjectMapper();
-        mapper.enableDefaultTyping();
+        final ObjectMapper mapper = jsonMapperBuilder()
+            .activateDefaultTyping(NoCheckSubTypeValidator.instance)
+            .build();
         // serialize without type info
         String json = mapper.writeValueAsString(new NoType());
         assertEquals("{\"a\":3}", json);
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/PolymorphicViaRefTypeTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/PolymorphicViaRefTypeTest.java
index 5610d8a..ffd2fe6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/PolymorphicViaRefTypeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/PolymorphicViaRefTypeTest.java
@@ -7,6 +7,7 @@
 
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class PolymorphicViaRefTypeTest extends BaseMapTest
 {
@@ -61,8 +62,10 @@
 
     public void testAtomicRefViaDefaultTyping() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(DefaultTyping.NON_FINAL);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        DefaultTyping.NON_FINAL)
+                .build();
         AtomicStringWrapper data = new AtomicStringWrapper("foo");
         String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(data);
         AtomicStringWrapper result = mapper.readValue(json, AtomicStringWrapper.class);
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/SubTypeResolution1964Test.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/SubTypeResolution1964Test.java
index 616e316..fa9ef01 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/SubTypeResolution1964Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/SubTypeResolution1964Test.java
@@ -72,7 +72,7 @@
     /**********************************************************************
      */
 
-    final ObjectMapper MAPPER = newObjectMapper();
+    final ObjectMapper MAPPER = newJsonMapper();
 
     // [databind#1964]
     public void testTypeCompatibility1964() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestAbstractTypeNames.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestAbstractTypeNames.java
index b98ce41..4070ac6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestAbstractTypeNames.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestAbstractTypeNames.java
@@ -9,6 +9,7 @@
 
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 /**
  * Unit tests for checking how combination of interfaces, implementation
@@ -126,8 +127,10 @@
     // [JACKSON-584]: change anonymous non-static inner type into static type:
     public void testInnerClassWithType() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(DefaultTyping.NON_FINAL);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        DefaultTyping.NON_FINAL)
+                .build();
         String json = mapper.writeValueAsString(new BeanWithAnon());
         BeanWithAnon result = mapper.readValue(json, BeanWithAnon.class);
         assertEquals(BeanWithAnon.class, result.getClass());
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestBaseTypeAsDefault.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestBaseTypeAsDefault.java
index 407d1e4..b678f92 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestBaseTypeAsDefault.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestBaseTypeAsDefault.java
@@ -37,11 +37,13 @@
     /**********************************************************
      */
 
-    protected ObjectMapper MAPPER_WITH_BASE = new ObjectMapper()
-                .enable(MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL);
+    protected ObjectMapper MAPPER_WITH_BASE = jsonMapperBuilder()
+                .enable(MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL)
+                .build();
 
-    protected ObjectMapper MAPPER_WITHOUT_BASE = new ObjectMapper()
-            .disable(MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL);
+    protected ObjectMapper MAPPER_WITHOUT_BASE = jsonMapperBuilder()
+            .disable(MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL)
+            .build();
     
     public void testPositiveForParent() throws IOException {
         Object o = MAPPER_WITH_BASE.readerFor(Parent.class).readValue("{}");
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestGenericListSerialization.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestGenericListSerialization.java
index 7982ed2..3f25e3f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestGenericListSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestGenericListSerialization.java
@@ -48,15 +48,15 @@
 
     public void testSubTypesFor356() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        
         JSONResponse<List<Parent>> input = new JSONResponse<List<Parent>>();
 
         List<Parent> embedded = new ArrayList<Parent>();
         embedded.add(new Child1());
         embedded.add(new Child2());
         input.setResult(embedded);
-        mapper.configure(MapperFeature.USE_STATIC_TYPING, true);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .configure(MapperFeature.USE_STATIC_TYPING, true)
+                .build();
 
         JavaType rootType = TypeFactory.defaultInstance().constructType(new TypeReference<JSONResponse<List<Parent>>>() { });
         byte[] json = mapper.writerFor(rootType).writeValueAsBytes(input);
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestScalars.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestScalars.java
index 89481bf..06865ff 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestScalars.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestScalars.java
@@ -49,7 +49,7 @@
     /**********************************************************
      */
 
-    final ObjectMapper MAPPER = newObjectMapper();
+    final ObjectMapper MAPPER = newJsonMapper();
     
     /**
      * Ensure that per-property dynamic types work, both for "native" types
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java
index 5517a2c..0ffd456 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java
@@ -1,6 +1,5 @@
 package com.fasterxml.jackson.databind.jsontype;
 
-
 import com.fasterxml.jackson.core.Version;
 
 import java.util.*;
@@ -15,6 +14,7 @@
 import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
 import com.fasterxml.jackson.databind.jsontype.NamedType;
 import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class TestSubtypes extends com.fasterxml.jackson.databind.BaseMapTest
 {
@@ -263,7 +263,8 @@
 
         // and then with defaults
         mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        mapper.activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                ObjectMapper.DefaultTyping.NON_FINAL);
         mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
         json = mapper.writeValueAsString(new EmptyNonFinal());
         assertEquals("[\"com.fasterxml.jackson.databind.jsontype.TestSubtypes$EmptyNonFinal\",{}]", json);
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedArraySerialization.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedArraySerialization.java
index 3b416bd..f6333f6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedArraySerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedArraySerialization.java
@@ -148,8 +148,9 @@
         assertEquals(EXP, MAPPER.writeValueAsString(input));
 
         // then with static typing enabled:
-        ObjectMapper m = new ObjectMapper();
-        m.configure(MapperFeature.USE_STATIC_TYPING, true);
+        ObjectMapper m = jsonMapperBuilder()
+                .configure(MapperFeature.USE_STATIC_TYPING, true)
+                .build();
         assertEquals(EXP, m.writeValueAsString(input));
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedContainerSerialization.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedContainerSerialization.java
index 5c3bd75..8ba9111 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedContainerSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedContainerSerialization.java
@@ -139,7 +139,7 @@
             List<Issue508A> l2 = new ArrayList<Issue508A>();
             l2.add(new Issue508A());
             l.add(l2);
-            TypeReference<?> typeRef = new TypeReference<List<List<Issue508A>>>() {};
+            TypeReference<List<List<Issue508A>>> typeRef = new TypeReference<List<List<Issue508A>>>() {};
             String json = mapper.writerFor(typeRef).writeValueAsString(l);
 
             List<?> output = mapper.readValue(json, typeRef);
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedDeserialization.java
index c1ea52c..68e77e2 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedDeserialization.java
@@ -6,7 +6,9 @@
 import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
 import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
 import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
+import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
 public class TestTypedDeserialization
@@ -55,7 +57,7 @@
         public void setName(String n) { name = n; }
     }
 
-    // for [JACKSON-319] -- allow "empty" beans
+    // Allow "empty" beans
     @JsonTypeName("fishy")
     static class Fish extends Animal
     {
@@ -66,6 +68,29 @@
         }
     }
 
+    // [databind#2467]: Allow missing "content" for as-array deserialization
+    @JsonDeserialize(using = NullAnimalDeserializer.class)
+    static class NullAnimal extends Animal
+    {
+        public static final NullAnimal NULL_INSTANCE = new NullAnimal();
+
+        public NullAnimal() {
+            super(null);
+        }
+    }
+
+    static class NullAnimalDeserializer extends JsonDeserializer<NullAnimal> {
+        @Override
+        public NullAnimal getNullValue(final DeserializationContext context) {
+            return NullAnimal.NULL_INSTANCE;
+        }
+
+        @Override
+        public NullAnimal deserialize(final JsonParser parser, final DeserializationContext context) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
     static class AnimalContainer {
         public Animal animal;
     }
@@ -239,6 +264,29 @@
         Issue506NumberBean output = mapper.readValue(json, Issue506NumberBean.class);
         assertEquals(input.number, output.number);
     }
+
+    // [databind#2467]: Allow missing "content" for as-array deserialization
+    public void testTypeAsArrayWithNullableType() throws Exception
+    {
+        ObjectMapper m = new ObjectMapper();
+        m.addMixIn(Animal.class, TypeWithArray.class);
+        Animal a = m.readValue(
+                "[\""+Fish.class.getName()+"\"]", Animal.class);
+        assertNull(a);
+    }
+
+    // [databind#2467]
+    public void testTypeAsArrayWithCustomDeserializer() throws Exception
+    {
+        ObjectMapper m = new ObjectMapper();
+        m.addMixIn(Animal.class, TypeWithArray.class);
+        Animal a = m.readValue(
+                "[\""+NullAnimal.class.getName()+"\"]", Animal.class);
+        assertNotNull(a);
+        assertEquals(NullAnimal.class, a.getClass());
+        NullAnimal c = (NullAnimal) a;
+        assertNull(c.name);
+    }
 }
 
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedSerialization.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedSerialization.java
index 7b04c45..e96a06a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedSerialization.java
@@ -151,7 +151,7 @@
         // ensure we'll use mapper with default configs
         ObjectMapper m = new ObjectMapper();
         // ... so this should NOT be needed...
-        m.disableDefaultTyping();
+        m.deactivateDefaultTyping();
         
         Animal[] animals = new Animal[] { new Cat("Miuku", "white"), new Dog("Murre", 9) };
         Map<String,Object> map = new HashMap<String,Object>();
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java
index bb4cd9b..15d95f8 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java
@@ -11,6 +11,7 @@
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ser.BeanSerializerFactory;
 import com.fasterxml.jackson.databind.ser.ResolvableSerializer;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class TestWithGenerics extends BaseMapTest
 {
@@ -108,15 +109,15 @@
         public CustomJsonSerializerFactory() { super(null); }
 
         @Override
-        protected JsonSerializer<Object> constructBeanSerializer(SerializerProvider prov,
-                BeanDescription beanDesc)
+        protected JsonSerializer<Object> constructBeanOrAddOnSerializer(SerializerProvider prov,
+                JavaType type, BeanDescription beanDesc, boolean staticTyping)
             throws JsonMappingException
         {                
-            return new CustomJsonSerializer(super.constructBeanSerializer(prov, beanDesc) );
+            return new CustomJsonSerializer(super.constructBeanOrAddOnSerializer(prov, type, beanDesc, staticTyping) );
         }
     }
 
-    // [Issue#543]
+    // [databind#543]
     static class ContainerWithTwoAnimals<U extends Animal,V extends Animal> extends ContainerWithField<U> {
          public V otherAnimal;
         
@@ -166,7 +167,8 @@
     public void testJackson387() throws Exception
     {
         ObjectMapper om = new ObjectMapper();
-        om.enableDefaultTyping( ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT, JsonTypeInfo.As.PROPERTY );
+        om.activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT, JsonTypeInfo.As.PROPERTY );
         om.setSerializationInclusion(JsonInclude.Include.NON_NULL );
         om.enable( SerializationFeature.INDENT_OUTPUT);
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TypeRefinementForMapTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TypeRefinementForMapTest.java
index 711c77c..a61c25d 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TypeRefinementForMapTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TypeRefinementForMapTest.java
@@ -9,6 +9,7 @@
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class TypeRefinementForMapTest extends BaseMapTest
 {
@@ -120,7 +121,10 @@
     {
         final String TEST_INSTANCE_SERIALIZED =
                 "{\"mapProperty\":[\"java.util.HashMap\",{\"Compound|Key\":\"Value\"}]}";
-        ObjectMapper mapper = new ObjectMapper().enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL)
+                .build();
 
         TestClass testInstance = mapper.readValue(TEST_INSTANCE_SERIALIZED, TestClass.class);
         assertEquals(1, testInstance.mapProperty.size());
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/DefaultTypeResolver2472Test.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/DefaultTypeResolver2472Test.java
new file mode 100644
index 0000000..1cabea1
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/DefaultTypeResolver2472Test.java
@@ -0,0 +1,32 @@
+package com.fasterxml.jackson.databind.jsontype.deftyping;
+
+import java.util.Arrays;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.ObjectMapper.DefaultTypeResolverBuilder;
+import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
+
+// [databind#2472]
+public class DefaultTypeResolver2472Test extends BaseMapTest
+{
+    public void testLegacyCtor2472() throws Exception
+    {
+        @SuppressWarnings({ "deprecation", "serial" })
+        TypeResolverBuilder<?> legacyTyper = new DefaultTypeResolverBuilder(DefaultTyping.NON_FINAL) { };
+        legacyTyper.init(JsonTypeInfo.Id.CLASS, null);
+        legacyTyper.inclusion(JsonTypeInfo.As.PROPERTY);
+
+        final ObjectMapper mapper = JsonMapper.builder().build();
+        mapper.setDefaultTyping(legacyTyper);
+
+        String json = mapper.writeValueAsString(Arrays.asList("foo"));
+        assertNotNull(json);
+
+        Object ob = mapper.readValue(json, Object.class);
+        assertNotNull(ob);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/DefaultWithBaseType1093Test.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/DefaultWithBaseType1093Test.java
new file mode 100644
index 0000000..bee9701
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/DefaultWithBaseType1093Test.java
@@ -0,0 +1,50 @@
+package com.fasterxml.jackson.databind.jsontype.deftyping;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
+
+// Tests to verify functionality to pass "base type" for serializing
+// polymorphic types (ones where output contains Type Id to allow later
+// deserialization deserialization), separate from fully forcing
+// actual type of value being serialized.
+public class DefaultWithBaseType1093Test extends BaseMapTest
+{
+    // [databind#1093]
+    static class Point1093 {
+        public int x, y;
+
+        protected Point1093() { }
+        public Point1093(int _x, int _y) {
+            x = _x;
+            y = _y;
+        }
+    }
+
+    // [databind#1093]
+    public void testWithDefaultTyping() throws Exception
+    {
+        ObjectMapper m = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT)
+                .build();
+
+        final Point1093 input = new Point1093(28, 12);
+
+        _testWithDefaultTyping(input, m.readerFor(Object.class),
+                m.writer().forType(Object.class));
+        _testWithDefaultTyping(input, m.readerFor(Object.class),
+                m.writerFor(Object.class));
+    }
+
+    private void _testWithDefaultTyping(Point1093 input, ObjectReader r,
+            ObjectWriter w) throws Exception
+    {
+        String json = w.writeValueAsString(input);
+        
+        Point1093 result = (Point1093) r.readValue(json);
+
+        assertEquals(input.x, result.x);
+        assertEquals(input.y, result.y);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForArrays.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForArrays.java
index cd6d34e..11bde67 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForArrays.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForArrays.java
@@ -8,6 +8,8 @@
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class TestDefaultForArrays extends BaseMapTest
 {
@@ -44,8 +46,10 @@
      */
     public void testArrayTypingSimple() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping(DefaultTyping.NON_CONCRETE_AND_ARRAYS);
+        ObjectMapper m = jsonMapperBuilder().
+                activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        DefaultTyping.NON_CONCRETE_AND_ARRAYS)
+                .build();
         ArrayBean bean = new ArrayBean(new String[0]);
         String json = m.writeValueAsString(bean);
         ArrayBean result = m.readValue(json, ArrayBean.class);
@@ -56,8 +60,10 @@
     // And let's try it with deeper array as well
     public void testArrayTypingNested() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping(DefaultTyping.NON_CONCRETE_AND_ARRAYS);
+        ObjectMapper m = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        DefaultTyping.NON_CONCRETE_AND_ARRAYS)
+                .build();
         ArrayBean bean = new ArrayBean(new String[0][0]);
         String json = m.writeValueAsString(bean);
         ArrayBean result = m.readValue(json, ArrayBean.class);
@@ -68,9 +74,10 @@
     public void testNodeInArray() throws Exception
     {
         JsonNode node = new ObjectMapper().readTree("{\"a\":3}");
-
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping(DefaultTyping.JAVA_LANG_OBJECT);
+        ObjectMapper m = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        DefaultTyping.JAVA_LANG_OBJECT)
+                .build();
         Object[] obs = new Object[] { node };
         String json = m.writeValueAsString(obs);
         Object[] result = m.readValue(json, Object[].class);
@@ -90,18 +97,31 @@
         assertEquals("{}", json);
         
         JsonNode node = new ObjectMapper().readTree("{\"a\":[]}");
-        
-        m.enableDefaultTyping(DefaultTyping.JAVA_LANG_OBJECT);
+
+        m = jsonMapperBuilder()
+                .disable(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS)
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        DefaultTyping.JAVA_LANG_OBJECT)
+                .build();
+        m.activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                DefaultTyping.JAVA_LANG_OBJECT);
+
         Object[] obs = new Object[] { node };
         json = m.writeValueAsString(obs);
         Object[] result = m.readValue(json, Object[].class);
-        assertEquals("{}", result[0].toString());
+
+        assertEquals(1, result.length);
+        Object elem = result[0];
+        assertTrue(elem instanceof ObjectNode);
+        assertEquals(0, ((ObjectNode) elem).size());
     }
 
     public void testArraysOfArrays() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY)
+                .build();
 
         Object value = new Object[][] { new Object[] {} };
         String json = mapper.writeValueAsString(value);
@@ -115,7 +135,8 @@
     public void testArrayTypingForPrimitiveArrays() throws Exception
     {
         ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping(DefaultTyping.NON_CONCRETE_AND_ARRAYS);
+        m.activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                DefaultTyping.NON_CONCRETE_AND_ARRAYS);
         _testArrayTypingForPrimitiveArrays(m, new int[] { 1, 2, 3 });
         _testArrayTypingForPrimitiveArrays(m, new long[] { 1, 2, 3 });
         _testArrayTypingForPrimitiveArrays(m, new short[] { 1, 2, 3 });
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForEnums.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForEnums.java
index b716c24..de474a0 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForEnums.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForEnums.java
@@ -4,6 +4,8 @@
 
 import com.fasterxml.jackson.databind.BaseMapTest;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class TestDefaultForEnums
     extends BaseMapTest
@@ -42,8 +44,9 @@
         assertEquals(TimeUnit.SECONDS, result.timeUnit);
         
         // then with type info
-        m = new ObjectMapper();
-        m.enableDefaultTyping();
+        m = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance)
+                .build();
         json = m.writeValueAsString(bean);
         result = m.readValue(json, TimeUnitBean.class);
 
@@ -52,9 +55,9 @@
     
     public void testSimpleEnumsInObjectArray() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping();
-        
+        ObjectMapper m = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance)
+                .build();
         // Typing is needed for enums
         String json = m.writeValueAsString(new Object[] { TestEnum.A });
         assertEquals("[[\"com.fasterxml.jackson.databind.jsontype.deftyping.TestDefaultForEnums$TestEnum\",\"A\"]]", json);
@@ -67,8 +70,9 @@
 
     public void testSimpleEnumsAsField() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping();
+        ObjectMapper m = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance)
+                .build();
         String json = m.writeValueAsString(new EnumHolder(TestEnum.B));
         assertEquals("{\"value\":[\"com.fasterxml.jackson.databind.jsontype.deftyping.TestDefaultForEnums$TestEnum\",\"B\"]}", json);
         EnumHolder holder = m.readValue(json, EnumHolder.class);
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForLists.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForLists.java
index b061be6..c2eeb49 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForLists.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForLists.java
@@ -6,16 +6,11 @@
 
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class TestDefaultForLists
     extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Helper types
-    /**********************************************************
-     */
-
     /**
      * Wrapper bean needed before there is a way to force
      * type of the root value. Long is used because it is a final
@@ -66,15 +61,17 @@
     /* Unit tests
     /**********************************************************
      */
+
+    private final ObjectMapper POLY_MAPPER = jsonMapperBuilder()
+            .activateDefaultTyping(NoCheckSubTypeValidator.instance)
+            .build();
     
     public void testListOfLongs() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping();
         ListOfLongs input = new ListOfLongs(1L, 2L, 3L);
-        String json = m.writeValueAsString(input);
+        String json = POLY_MAPPER.writeValueAsString(input);
         assertEquals("{\"longs\":[\"java.util.ArrayList\",[1,2,3]]}", json);
-        ListOfLongs output = m.readValue(json, ListOfLongs.class);
+        ListOfLongs output = POLY_MAPPER.readValue(json, ListOfLongs.class);
 
         assertNotNull(output.longs);
         assertEquals(3, output.longs.size());
@@ -91,12 +88,10 @@
      */
     public void testListOfNumbers() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping();
         ListOfNumbers input = new ListOfNumbers(Long.valueOf(1L), Integer.valueOf(2), Double.valueOf(3.0));
-        String json = m.writeValueAsString(input);
+        String json = POLY_MAPPER.writeValueAsString(input);
         assertEquals("{\"nums\":[\"java.util.ArrayList\",[[\"java.lang.Long\",1],2,3.0]]}", json);
-        ListOfNumbers output = m.readValue(json, ListOfNumbers.class);
+        ListOfNumbers output = POLY_MAPPER.readValue(json, ListOfNumbers.class);
 
         assertNotNull(output.nums);
         assertEquals(3, output.nums.size());
@@ -107,16 +102,14 @@
 
     public void testDateTypes() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping();
         ObjectListBean input = new ObjectListBean();
         List<Object> inputList = new ArrayList<Object>();
         inputList.add(TimeZone.getTimeZone("EST"));
         inputList.add(Locale.CHINESE);
         input.values = inputList;
-        String json = m.writeValueAsString(input);
+        String json = POLY_MAPPER.writeValueAsString(input);
 
-        ObjectListBean output = m.readValue(json, ObjectListBean.class);
+        ObjectListBean output = POLY_MAPPER.readValue(json, ObjectListBean.class);
         List<Object> outputList = output.values;
         assertEquals(2, outputList.size());
         assertTrue(outputList.get(0) instanceof TimeZone);
@@ -126,7 +119,7 @@
     public void testJackson628() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(DefaultTyping.NON_FINAL);
+        mapper.activateDefaultTyping(NoCheckSubTypeValidator.instance, DefaultTyping.NON_FINAL);
         ArrayList<Foo> data = new ArrayList<Foo>();
         String json = mapper.writeValueAsString(data);
         List<?> output = mapper.readValue(json, List.class);
@@ -136,7 +129,8 @@
     public void testJackson667() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL,
+        mapper.activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                ObjectMapper.DefaultTyping.NON_FINAL,
                 JsonTypeInfo.As.PROPERTY);
         String json = mapper.writeValueAsString(new SetBean("abc"));
         SetBean bean = mapper.readValue(json, SetBean.class);
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForMaps.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForMaps.java
index c1fca0a..4b04997 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForMaps.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForMaps.java
@@ -8,6 +8,7 @@
 import com.fasterxml.jackson.databind.jsontype.NamedType;
 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
 import com.fasterxml.jackson.databind.jsontype.impl.TypeNameIdResolver;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
 public class TestDefaultForMaps 
@@ -72,7 +73,8 @@
     {
         ObjectMapper serMapper = new ObjectMapper();
 
-        TypeResolverBuilder<?> serializerTyper = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL);
+        TypeResolverBuilder<?> serializerTyper = ObjectMapper.DefaultTypeResolverBuilder.construct(
+                ObjectMapper.DefaultTyping.NON_FINAL, serMapper.getPolymorphicTypeValidator());
         serializerTyper = serializerTyper.init(JsonTypeInfo.Id.NAME, createTypeNameIdResolver(true));
         serializerTyper = serializerTyper.inclusion(JsonTypeInfo.As.PROPERTY);
         serMapper.setDefaultTyping(serializerTyper);
@@ -87,7 +89,9 @@
 
         // Then deserialize: need separate mapper to initialize type id resolver appropriately
         ObjectMapper deserMapper = new ObjectMapper();
-        TypeResolverBuilder<?> deserializerTyper = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL);
+        TypeResolverBuilder<?> deserializerTyper = ObjectMapper.DefaultTypeResolverBuilder.construct(
+                ObjectMapper.DefaultTyping.NON_FINAL, serMapper.getPolymorphicTypeValidator());
+
         deserializerTyper = deserializerTyper.init(JsonTypeInfo.Id.NAME, createTypeNameIdResolver(false));
         deserializerTyper = deserializerTyper.inclusion(JsonTypeInfo.As.PROPERTY);
         deserMapper.setDefaultTyping(deserializerTyper);
@@ -121,7 +125,8 @@
     public void testList() throws Exception
     {
         final ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, JsonTypeInfo.As.PROPERTY);
+        mapper.activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, JsonTypeInfo.As.PROPERTY);
         ItemList child = new ItemList();
         child.value = "I am child";
 
@@ -137,7 +142,8 @@
     public void testMap() throws Exception
     {
         final ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, JsonTypeInfo.As.PROPERTY);
+        mapper.activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, JsonTypeInfo.As.PROPERTY);
         ItemMap child = new ItemMap();
         child.value = "I am child";
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForObject.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForObject.java
index 5f0a23a..e9be622 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForObject.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForObject.java
@@ -6,6 +6,8 @@
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 import com.fasterxml.jackson.databind.util.TokenBuffer;
 
 public class TestDefaultForObject
@@ -20,6 +22,11 @@
         protected StringBean(String n)  { name = n; }
     }
 
+    final static class FinalStringBean extends StringBean {
+        protected FinalStringBean() { this(null); }
+        public FinalStringBean(String n)  { super(n); }
+    }
+
     enum Choice { YES, NO; }
 
     /**
@@ -89,8 +96,9 @@
      */
     public void testBeanAsObject() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping();
+        ObjectMapper m = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance)
+                .build();
         // note: need to wrap, to get declared as Object
         String str = m.writeValueAsString(new Object[] { new StringBean("abc") });
 
@@ -108,9 +116,11 @@
     // with 2.5, another test to check that "as-property" is valid option
     public void testBeanAsObjectUsingAsProperty() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.NON_FINAL,
-                ".hype");
+        ObjectMapper m = JsonMapper.builder()
+                .activateDefaultTypingAsProperty(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL,
+                        ".hype")
+                .build();
         // note: need to wrap, to get declared as Object
         String json = m.writeValueAsString(new StringBean("abc"));
         
@@ -138,10 +148,11 @@
             // let's use whatever is currently thrown exception... may change tho
             verifyException(e, "cannot construct");
         }
-        
         // and then that we will succeed with default type info
-        m = new ObjectMapper();
-        m.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE);
+        m = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE)
+                .build();
         serial = m.writeValueAsString(input);
         AbstractBean[] beans = m.readValue(serial, AbstractBean[].class);
         assertEquals(1, beans.length);
@@ -155,22 +166,28 @@
      */
     public void testNonFinalBean() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        // first: use "object or abstract" typing: should produce no type info:        
-        m.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE);
+        ObjectMapper m = JsonMapper.builder()
+                // first: use "object or abstract" typing: should produce no type info:
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE)
+                .build();
         StringBean bean = new StringBean("x");
         assertEquals("{\"name\":\"x\"}", m.writeValueAsString(bean));
         // then non-final, and voila:
-        m = new ObjectMapper();
-        m.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        m = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL)
+                .build();
         assertEquals("[\""+StringBean.class.getName()+"\",{\"name\":\"x\"}]",
             m.writeValueAsString(bean));
     }
 
     public void testNullValue() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        ObjectMapper m = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL)
+                .build();
         BeanHolder h = new BeanHolder();
         String json = m.writeValueAsString(h);
         assertNotNull(json);
@@ -189,8 +206,9 @@
         assertEquals("[\"MAYBE\"]", serializeAsString(input2));
 
         // and then with it
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping();
+        ObjectMapper m = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance)
+                .build();
 
         String json = m.writeValueAsString(input);
         assertEquals("[[\""+Choice.class.getName()+"\",\"YES\"]]", json);
@@ -213,8 +231,9 @@
     {
         EnumSet<Choice> set = EnumSet.of(Choice.NO);
         Object[] input = new Object[] { set };
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping();
+        ObjectMapper m = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance)
+                .build();
         String json = m.writeValueAsString(input);
         Object[] output = m.readValue(json, Object[].class);
         assertEquals(1, output.length);
@@ -232,8 +251,9 @@
         EnumMap<Choice,String> map = new EnumMap<Choice,String>(Choice.class);
         map.put(Choice.NO, "maybe");
         Object[] input = new Object[] { map };
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping();
+        ObjectMapper m = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance)
+                .build();
         String json = m.writeValueAsString(input);
         Object[] output = m.readValue(json, Object[].class);
         assertEquals(1, output.length);
@@ -247,8 +267,10 @@
 
     public void testJackson311() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        ObjectMapper mapper = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL)
+                .build();
         String json = mapper.writeValueAsString(new PolymorphicType("hello", 2));
         PolymorphicType value = mapper.readValue(json, PolymorphicType.class);
         assertEquals("hello", value.foo);
@@ -258,8 +280,10 @@
     // Also, let's ensure TokenBuffer gets properly handled
     public void testTokenBuffer() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        ObjectMapper mapper = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL)
+                .build();
 
         // Ok, first test JSON Object containing buffer:
         TokenBuffer buf = new TokenBuffer(mapper, false);
@@ -311,13 +335,12 @@
         buf.close();
     }
 
-    /**
-     * Test for [JACKSON-352]
-     */
     public void testIssue352() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping (ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, JsonTypeInfo.As.PROPERTY);
+        ObjectMapper mapper = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, JsonTypeInfo.As.PROPERTY)
+                .build();
         DiscussBean d1 = new DiscussBean();
         d1.subject = "mouse";
         d1.weight=88;
@@ -334,24 +357,47 @@
     // Test to ensure we can also use "As.PROPERTY" inclusion and custom property name
     public void testFeature432() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, "*CLASS*");
+        ObjectMapper mapper = JsonMapper.builder()
+                .activateDefaultTypingAsProperty(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, "*CLASS*")
+                .build();
         String json = mapper.writeValueAsString(new BeanHolder(new StringBean("punny")));
         assertEquals("{\"bean\":{\"*CLASS*\":\"com.fasterxml.jackson.databind.jsontype.deftyping.TestDefaultForObject$StringBean\",\"name\":\"punny\"}}", json);
     }
 
     public void testNoGoWithExternalProperty() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
         try {
-            mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT,
-                    JsonTypeInfo.As.EXTERNAL_PROPERTY);
+            /*ObjectMapper mapper =*/ JsonMapper.builder()
+                    .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT,
+                        JsonTypeInfo.As.EXTERNAL_PROPERTY)
+                    .build();
             fail("Should not have passed");
         } catch (IllegalArgumentException e) {
             verifyException(e, "Cannot use includeAs of EXTERNAL_PROPERTY");
         }
     }
-    
+
+    // [databind#2349]
+    public void testWithFinalClass() throws Exception
+    {
+        // First: type info NOT included
+        ObjectMapper mapper = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL)
+                .build();
+        assertEquals(aposToQuotes("{'name':'abc'}"),
+                mapper.writeValueAsString(new FinalStringBean("abc")));
+
+        mapper = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.EVERYTHING)
+                .build();
+        assertEquals(aposToQuotes("['"+FinalStringBean.class.getName()+"',{'name':'abc'}]"),
+                mapper.writeValueAsString(new FinalStringBean("abc")));
+    }
+
     /*
     /**********************************************************
     /* Helper methods
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForScalars.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForScalars.java
index 7bb7b5c..d87255a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForScalars.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForScalars.java
@@ -7,6 +7,7 @@
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 /**
  * Unit tests to verify that Java/JSON scalar values (non-structured values)
@@ -17,7 +18,7 @@
 {
     static class Jackson417Bean {
         public String foo = "bar";
-        public java.io.Serializable bar = new Integer(13);
+        public java.io.Serializable bar = Integer.valueOf(13);
     }
 
     // [databind#1395]: prevent attempts at including type info for primitives
@@ -25,12 +26,28 @@
         public long key;
     }
 
+    // Basic `ObjectWrapper` from base uses delegating ctor, won't work well; should
+    // figure out why, but until then we'll use separate impl
+    protected static class ObjectWrapperForPoly {
+        Object object;
+
+        protected ObjectWrapperForPoly() { }
+        public ObjectWrapperForPoly(final Object o) {
+            object = o;
+        }
+        public Object getObject() { return object; }
+    }
+
     /*
     /**********************************************************
     /* Test methods
     /**********************************************************
      */
-    
+
+    private final ObjectMapper DEFAULT_TYPING_MAPPER = jsonMapperBuilder()
+        .activateDefaultTyping(NoCheckSubTypeValidator.instance)
+        .build();
+
     /**
      * Unit test to verify that limited number of core types do NOT include
      * type information, even if declared as Object. This is only done for types
@@ -39,32 +56,26 @@
      */
     public void testNumericScalars() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping();
-
         // no typing for Integer, Double, yes for others
-        assertEquals("[123]", m.writeValueAsString(new Object[] { Integer.valueOf(123) }));
-        assertEquals("[[\"java.lang.Long\",37]]", m.writeValueAsString(new Object[] { Long.valueOf(37) }));
-        assertEquals("[0.25]", m.writeValueAsString(new Object[] { Double.valueOf(0.25) }));
-        assertEquals("[[\"java.lang.Float\",0.5]]", m.writeValueAsString(new Object[] { Float.valueOf(0.5f) }));
+        assertEquals("[123]", DEFAULT_TYPING_MAPPER.writeValueAsString(new Object[] { Integer.valueOf(123) }));
+        assertEquals("[[\"java.lang.Long\",37]]", DEFAULT_TYPING_MAPPER.writeValueAsString(new Object[] { Long.valueOf(37) }));
+        assertEquals("[0.25]", DEFAULT_TYPING_MAPPER.writeValueAsString(new Object[] { Double.valueOf(0.25) }));
+        assertEquals("[[\"java.lang.Float\",0.5]]", DEFAULT_TYPING_MAPPER.writeValueAsString(new Object[] { Float.valueOf(0.5f) }));
     }
 
     public void testDateScalars() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping();
-
         long ts = 12345678L;
         assertEquals("[[\"java.util.Date\","+ts+"]]",
-                m.writeValueAsString(new Object[] { new Date(ts) }));
+                DEFAULT_TYPING_MAPPER.writeValueAsString(new Object[] { new Date(ts) }));
 
         // Calendar is trickier... hmmh. Need to ensure round-tripping
         Calendar c = Calendar.getInstance();
         c.setTimeInMillis(ts);
-        String json = m.writeValueAsString(new Object[] { c });
+        String json = DEFAULT_TYPING_MAPPER.writeValueAsString(new Object[] { c });
         assertEquals("[[\""+c.getClass().getName()+"\","+ts+"]]", json);
         // and let's make sure it also comes back same way:
-        Object[] result = m.readValue(json, Object[].class);
+        Object[] result = DEFAULT_TYPING_MAPPER.readValue(json, Object[].class);
         assertEquals(1, result.length);
         assertTrue(result[0] instanceof Calendar);
         assertEquals(ts, ((Calendar) result[0]).getTimeInMillis());
@@ -72,12 +83,9 @@
 
     public void testMiscScalars() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping();
-
         // no typing for Strings, booleans
-        assertEquals("[\"abc\"]", m.writeValueAsString(new Object[] { "abc" }));
-        assertEquals("[true,null,false]", m.writeValueAsString(new Boolean[] { true, null, false }));
+        assertEquals("[\"abc\"]", DEFAULT_TYPING_MAPPER.writeValueAsString(new Object[] { "abc" }));
+        assertEquals("[true,null,false]", DEFAULT_TYPING_MAPPER.writeValueAsString(new Boolean[] { true, null, false }));
     }
 
     /**
@@ -86,8 +94,10 @@
      */
     public void testScalarArrays() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping(ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT);
+        ObjectMapper m = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT)
+                .build();
         Object[] input = new Object[] {
                 "abc", new Date(1234567), null, Integer.valueOf(456)
         };
@@ -101,11 +111,9 @@
 
     public void test417() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.enableDefaultTyping();
         Jackson417Bean input = new Jackson417Bean();
-        String json = m.writeValueAsString(input);
-        Jackson417Bean result = m.readValue(json, Jackson417Bean.class);
+        String json = DEFAULT_TYPING_MAPPER.writeValueAsString(input);
+        Jackson417Bean result = DEFAULT_TYPING_MAPPER.readValue(json, Jackson417Bean.class);
         assertEquals(input.foo, result.foo);
         assertEquals(input.bar, result.bar);
     }
@@ -136,4 +144,15 @@
         assertNotNull(result);
         assertEquals(2, result.size());
     }
+
+    // [databind#2236]: do need type info for NaN
+    public void testDefaultTypingWithNaN() throws Exception
+    {
+        final ObjectWrapperForPoly INPUT = new ObjectWrapperForPoly(Double.POSITIVE_INFINITY);
+        final String json = DEFAULT_TYPING_MAPPER.writeValueAsString(INPUT);
+        final ObjectWrapperForPoly result = DEFAULT_TYPING_MAPPER.readValue(json, ObjectWrapperForPoly.class);
+        assertEquals(Double.class, result.getObject().getClass());
+        assertEquals(INPUT.getObject().toString(), result.getObject().toString());
+        assertTrue(((Double) result.getObject()).isInfinite());
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForTreeNodes.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForTreeNodes.java
index 39a2cee..b196740 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForTreeNodes.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultForTreeNodes.java
@@ -2,6 +2,7 @@
 
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class TestDefaultForTreeNodes extends BaseMapTest
 {
@@ -18,11 +19,11 @@
     /**********************************************************
      */
 
-    private final ObjectMapper DEFAULT_MAPPER = new ObjectMapper();
-    {
-        DEFAULT_MAPPER.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
-    }
-    
+    private final ObjectMapper DEFAULT_MAPPER = jsonMapperBuilder()
+            .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY)
+            .build();
+
     public void testValueAsStringWithDefaultTyping() throws Exception
     {
         Foo foo = new Foo("baz");
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultWithCreators.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultWithCreators.java
index b75b478..ffbba7e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultWithCreators.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/deftyping/TestDefaultWithCreators.java
@@ -6,6 +6,8 @@
 
 import com.fasterxml.jackson.databind.BaseMapTest;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class TestDefaultWithCreators
     extends BaseMapTest
@@ -65,8 +67,10 @@
 
     public void testWithCreators() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        ObjectMapper mapper = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL)
+                .build();
         UrlJob input = new UrlJob(123L, "http://foo", 3);
         String json = mapper.writeValueAsString(input);
         assertNotNull(json);
@@ -83,8 +87,9 @@
     public void testWithCreatorAndJsonValue() throws Exception
     {
         final byte[] BYTES = new byte[] { 1, 2, 3, 4, 5 };
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping();
+        ObjectMapper mapper = JsonMapper.builder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance)
+                .build();
         String json = mapper.writeValueAsString(new Bean1385Wrapper(
                 new Bean1385(BYTES)
         ));
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest1288.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeCustomResolverTest.java
similarity index 98%
rename from src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest1288.java
rename to src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeCustomResolverTest.java
index d756d40..f063767 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest1288.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeCustomResolverTest.java
@@ -13,8 +13,9 @@
 import com.fasterxml.jackson.databind.jsontype.impl.TypeIdResolverBase;
 
 @SuppressWarnings("hiding")
-public class ExternalTypeIdTest1288 extends BaseMapTest
+public class ExternalTypeCustomResolverTest extends BaseMapTest
 {
+    // [databind#1288]
     public static class ClassesWithoutBuilder {
         
         public static class CreditCardDetails implements PaymentDetails {
@@ -497,7 +498,8 @@
         }
     }
 
-    public void testVisibleExternalTypeId1288() throws Exception
+    // [databind#1288]
+    public void testVisibleExternalTypeIdCustomResolver() throws Exception
     {
         // given
         final String asJson1 = "{\"form_of_payment\":\"INDIVIDUAL_CREDIT_CARD\", \"payment_details\":{\"card_holder_first_name\":\"John\", \"card_holder_last_name\":\"Doe\",  \"number\":\"XXXXXXXXXXXXXXXX\", \"expiry_date\":\"MM/YY\","
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeId198Test.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeId198Test.java
deleted file mode 100644
index c34793f..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeId198Test.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.fasterxml.jackson.databind.jsontype.ext;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonSubTypes;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-
-import com.fasterxml.jackson.databind.*;
-
-public class ExternalTypeId198Test extends BaseMapTest
-{
-    public enum Attacks { KICK, PUNCH }
-
-    static class Character {
-        public String name;
-        public Attacks preferredAttack;
-
-        @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, defaultImpl=Kick.class,
-                include=JsonTypeInfo.As.EXTERNAL_PROPERTY, property="preferredAttack")
-        @JsonSubTypes({
-            @JsonSubTypes.Type(value=Kick.class, name="KICK"),
-            @JsonSubTypes.Type(value=Punch.class, name="PUNCH")
-        })
-        public Attack attack;
-    }
-
-    public static abstract class Attack {
-        public String side;
-
-        @JsonCreator
-        public Attack(String side) {
-            this.side = side;
-        }
-    }
-
-    public static class Kick extends Attack {
-        @JsonCreator
-        public Kick(String side) {
-            super(side);
-        }
-    }
-
-    public static class Punch extends Attack {
-        @JsonCreator
-        public Punch(String side) {
-            super(side);
-        }
-    }
-
-    final ObjectMapper MAPPER = new ObjectMapper();
-
-    public void testFails() throws Exception {
-        String json = "{ \"name\": \"foo\", \"attack\":\"right\" } }";
-
-        Character character = MAPPER.readValue(json, Character.class);
-
-        assertNotNull(character);
-        assertNotNull(character.attack);
-        assertEquals("foo", character.name);
-    }
-
-    public void testWorks() throws Exception {
-        String json = "{ \"name\": \"foo\", \"preferredAttack\": \"KICK\", \"attack\":\"right\" } }";
-
-        Character character = MAPPER.readValue(json, Character.class);
-
-        assertNotNull(character);
-        assertNotNull(character.attack);
-        assertEquals("foo", character.name);
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeId999Test.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeId999Test.java
deleted file mode 100644
index a81f251..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeId999Test.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.fasterxml.jackson.databind.jsontype.ext;
-
-import com.fasterxml.jackson.annotation.*;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.*;
-
-public class ExternalTypeId999Test extends BaseMapTest
-{
-    public static interface Payload { }
-
-    @JsonTypeName("foo")
-    public static class FooPayload implements Payload { }
-
-    @JsonTypeName("bar")
-    public static class BarPayload implements Payload { }
-
-    public static class Message<P extends Payload>
-    {
-        final String type;
-
-        @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
-                visible = true,
-                include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
-        @JsonSubTypes({
-                @JsonSubTypes.Type(FooPayload.class),
-                @JsonSubTypes.Type(BarPayload.class) })
-        private final P payload;
-
-        @JsonCreator
-        public Message(@JsonProperty("type") String type,
-                @JsonProperty("payload") P payload)
-        {
-            this.type = type;
-            this.payload = payload;
-        }
-    }
-
-    private final ObjectMapper MAPPER = objectMapper();
-
-    public void testExternalTypeId() throws Exception
-    {
-        TypeReference<?> type = new TypeReference<Message<FooPayload>>() { };
-
-        Message<?> msg = MAPPER.readValue(aposToQuotes("{ 'type':'foo', 'payload': {} }"), type);
-        assertNotNull(msg);
-        assertNotNull(msg.payload);
-        assertEquals("foo", msg.type);
-
-        // and then with different order
-        msg = MAPPER.readValue(aposToQuotes("{'payload': {}, 'type':'foo' }"), type);
-        assertNotNull(msg);
-        assertNotNull(msg.payload);
-        assertEquals("foo", msg.type);
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest.java
index 7537129..c7a5eef 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdTest.java
@@ -514,7 +514,6 @@
     // for [databind#965]
     public void testBigDecimal965() throws Exception
     {
-
         Wrapper965 w = new Wrapper965();
         w.typeEnum = Type965.BIG_DECIMAL;
         final String NUM_STR = "-10000000000.0000000001";
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdWithCreatorTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdWithCreatorTest.java
new file mode 100644
index 0000000..e58ba1d
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdWithCreatorTest.java
@@ -0,0 +1,126 @@
+package com.fasterxml.jackson.databind.jsontype.ext;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.*;
+
+public class ExternalTypeIdWithCreatorTest extends BaseMapTest
+{
+    // [databind#1198]
+    
+    public enum Attacks { KICK, PUNCH }
+
+    static class Character {
+        public String name;
+        public Attacks preferredAttack;
+
+        @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, defaultImpl=Kick.class,
+                include=JsonTypeInfo.As.EXTERNAL_PROPERTY, property="preferredAttack")
+        @JsonSubTypes({
+            @JsonSubTypes.Type(value=Kick.class, name="KICK"),
+            @JsonSubTypes.Type(value=Punch.class, name="PUNCH")
+        })
+        public Attack attack;
+    }
+
+    public static abstract class Attack {
+        public String side;
+
+        @JsonCreator
+        public Attack(String side) {
+            this.side = side;
+        }
+    }
+
+    public static class Kick extends Attack {
+        @JsonCreator
+        public Kick(String side) {
+            super(side);
+        }
+    }
+
+    public static class Punch extends Attack {
+        @JsonCreator
+        public Punch(String side) {
+            super(side);
+        }
+    }
+
+    // [databind#999]
+
+    public static interface Payload999 { }
+
+    @JsonTypeName("foo")
+    public static class FooPayload999 implements Payload999 { }
+
+    @JsonTypeName("bar")
+    public static class BarPayload999 implements Payload999 { }
+
+    public static class Message<P extends Payload999>
+    {
+        final String type;
+
+        @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
+                visible = true,
+                include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
+        @JsonSubTypes({
+                @JsonSubTypes.Type(FooPayload999.class),
+                @JsonSubTypes.Type(BarPayload999.class) })
+        private final P payload;
+
+        @JsonCreator
+        public Message(@JsonProperty("type") String type,
+                @JsonProperty("payload") P payload)
+        {
+            this.type = type;
+            this.payload = payload;
+        }
+    }
+    
+    /*
+    /********************************************************************** 
+    /* Test methods
+    /********************************************************************** 
+     */
+
+    private final ObjectMapper MAPPER = new ObjectMapper();
+
+    // [databind#1198]
+    public void testFails() throws Exception {
+        String json = "{ \"name\": \"foo\", \"attack\":\"right\" } }";
+
+        Character character = MAPPER.readValue(json, Character.class);
+
+        assertNotNull(character);
+        assertNotNull(character.attack);
+        assertEquals("foo", character.name);
+    }
+
+    // [databind#1198]
+    public void testWorks() throws Exception {
+        String json = "{ \"name\": \"foo\", \"preferredAttack\": \"KICK\", \"attack\":\"right\" } }";
+
+        Character character = MAPPER.readValue(json, Character.class);
+
+        assertNotNull(character);
+        assertNotNull(character.attack);
+        assertEquals("foo", character.name);
+    }
+
+    // [databind#999]
+    public void testExternalTypeId() throws Exception
+    {
+        TypeReference<Message<FooPayload999>> type = new TypeReference<Message<FooPayload999>>() { };
+
+        Message<?> msg = MAPPER.readValue(aposToQuotes("{ 'type':'foo', 'payload': {} }"), type);
+        assertNotNull(msg);
+        assertNotNull(msg.payload);
+        assertEquals("foo", msg.type);
+
+        // and then with different order
+        msg = MAPPER.readValue(aposToQuotes("{'payload': {}, 'type':'foo' }"), type);
+        assertNotNull(msg);
+        assertNotNull(msg.payload);
+        assertEquals("foo", msg.type);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdWithIgnoreUnknownTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdWithIgnoreUnknownTest.java
new file mode 100644
index 0000000..481553d
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/ExternalTypeIdWithIgnoreUnknownTest.java
@@ -0,0 +1,59 @@
+package com.fasterxml.jackson.databind.jsontype.ext;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.*;
+
+public class ExternalTypeIdWithIgnoreUnknownTest extends BaseMapTest
+{
+    // [databind#2611]
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    static class Wrapper2611 {
+        private String type;
+
+        @JsonTypeInfo(
+                use = JsonTypeInfo.Id.NAME,
+                include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
+                property = "type",
+                defaultImpl = Default2611.class
+        )
+        private Default2611 data;
+
+        @JsonCreator
+        public Wrapper2611(
+                @JsonProperty(value = "type", required = true) String type,
+                @JsonProperty(value = "data", required = true) Default2611 data
+        ) {
+            this.type = type;
+            this.data = data;
+        }
+
+        String getType() {
+            return type;
+        }
+
+        Default2611 getData() {
+            return data;
+        }
+    }
+
+    static class Default2611 {}
+
+    private final ObjectMapper MAPPER = newJsonMapper();
+
+    // [databind#2611]
+    public void testDeserialization() throws Exception
+    {
+        final String data = aposToQuotes("[{'type': 'test','data': {},'additional': {}}]");
+
+        List<Wrapper2611> result = MAPPER.readValue(data, new TypeReference<List<Wrapper2611>>() {});
+
+        assertEquals(1, result.size());
+
+        Wrapper2611 item = result.get(0);
+        assertEquals("test", item.getType());
+        assertNotNull(item.getData());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/TestPropertyCreatorSubtypesExternalPropertyMissingProperty.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/TestPropertyCreatorSubtypesExternalPropertyMissingProperty.java
index 6e24114..ac75229 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/TestPropertyCreatorSubtypesExternalPropertyMissingProperty.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/ext/TestPropertyCreatorSubtypesExternalPropertyMissingProperty.java
@@ -7,10 +7,12 @@
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
 import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
+
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
+import com.fasterxml.jackson.databind.ObjectReader;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -103,8 +105,6 @@
         }
     }
 
-    private final ObjectMapper MAPPER = new ObjectMapper();
-
     /*
     /**********************************************************
     /* Mock data
@@ -131,18 +131,27 @@
     /**********************************************************
      */
 
+    private final ObjectReader BOX_READER_PASS;
+    private final ObjectReader BOX_READER_FAIL;
+
+    {
+        final ObjectMapper mapper = new ObjectMapper();
+        BOX_READER_PASS = mapper.readerFor(Box.class)
+            .without(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
+        BOX_READER_FAIL = mapper.readerFor(Box.class)
+            .with(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
+    }
+
     /**
      * Deserialization tests for external type id property present
      */
     @Test
     public void testDeserializationPresent() throws Exception {
-        MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
-        checkOrangeBox();
-        checkAppleBox();
+        checkOrangeBox(BOX_READER_PASS);
+        checkAppleBox(BOX_READER_PASS);
 
-        MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
-        checkOrangeBox();
-        checkAppleBox();
+        checkOrangeBox(BOX_READER_FAIL);
+        checkAppleBox(BOX_READER_FAIL);
     }
 
     /**
@@ -150,13 +159,11 @@
      */
     @Test
     public void testDeserializationNull() throws Exception {
-        MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
-        checkOrangeBoxNull(orangeBoxNullJson);
-        checkAppleBoxNull(appleBoxNullJson);
+        checkOrangeBoxNull(BOX_READER_PASS, orangeBoxNullJson);
+        checkAppleBoxNull(BOX_READER_PASS, appleBoxNullJson);
 
-        MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
-        checkOrangeBoxNull(orangeBoxNullJson);
-        checkAppleBoxNull(appleBoxNullJson);
+        checkOrangeBoxNull(BOX_READER_FAIL, orangeBoxNullJson);
+        checkAppleBoxNull(BOX_READER_FAIL, appleBoxNullJson);
     }
 
     /**
@@ -164,13 +171,11 @@
      */
     @Test
     public void testDeserializationEmpty() throws Exception {
-        MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
-        checkOrangeBoxEmpty(orangeBoxEmptyJson);
-        checkAppleBoxEmpty(appleBoxEmptyJson);
+        checkOrangeBoxEmpty(BOX_READER_PASS, orangeBoxEmptyJson);
+        checkAppleBoxEmpty(BOX_READER_PASS, appleBoxEmptyJson);
 
-        MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
-        checkOrangeBoxEmpty(orangeBoxEmptyJson);
-        checkAppleBoxEmpty(appleBoxEmptyJson);
+        checkOrangeBoxEmpty(BOX_READER_FAIL, orangeBoxEmptyJson);
+        checkAppleBoxEmpty(BOX_READER_FAIL, appleBoxEmptyJson);
     }
 
     /**
@@ -178,17 +183,15 @@
      */
     @Test
     public void testDeserializationMissing() throws Exception {
-        MAPPER.disable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
-        checkOrangeBoxNull(orangeBoxMissingJson);
-        checkAppleBoxNull(appleBoxMissingJson);
+        checkOrangeBoxNull(BOX_READER_PASS, orangeBoxMissingJson);
+        checkAppleBoxNull(BOX_READER_PASS, appleBoxMissingJson);
 
-        MAPPER.enable(DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY);
-        checkBoxJsonMappingException(orangeBoxMissingJson);
-        checkBoxJsonMappingException(appleBoxMissingJson);
+        checkBoxJsonMappingException(BOX_READER_FAIL, orangeBoxMissingJson);
+        checkBoxJsonMappingException(BOX_READER_FAIL, appleBoxMissingJson);
     }
 
-    private void checkOrangeBox() throws Exception {
-        Box deserOrangeBox = MAPPER.readValue(orangeBoxJson, Box.class);
+    private void checkOrangeBox(ObjectReader reader) throws Exception {
+        Box deserOrangeBox = reader.readValue(orangeBoxJson);
         assertEquals(orangeBox.getType(), deserOrangeBox.getType());
 
         Fruit deserOrange = deserOrangeBox.getFruit();
@@ -197,8 +200,8 @@
         assertEquals(orange.getColor(), ((Orange) deserOrange).getColor());
     }
 
-    private void checkAppleBox() throws Exception {
-        Box deserAppleBox = MAPPER.readValue(appleBoxJson, Box.class);
+    private void checkAppleBox(ObjectReader reader) throws Exception {
+        Box deserAppleBox = reader.readValue(appleBoxJson);
         assertEquals(appleBox.getType(), deserAppleBox.getType());
 
         Fruit deserApple = deserAppleBox.fruit;
@@ -207,8 +210,8 @@
         assertEquals(apple.getSeedCount(), ((Apple) deserApple).getSeedCount());
     }
 
-    private void checkOrangeBoxEmpty(String json) throws Exception {
-        Box deserOrangeBox = MAPPER.readValue(json, Box.class);
+    private void checkOrangeBoxEmpty(ObjectReader reader, String json) throws Exception {
+        Box deserOrangeBox = reader.readValue(json);
         assertEquals(orangeBox.getType(), deserOrangeBox.getType());
 
         Fruit deserOrange = deserOrangeBox.getFruit();
@@ -217,8 +220,8 @@
         assertNull(((Orange) deserOrange).getColor());
     }
 
-    private void checkAppleBoxEmpty(String json) throws Exception {
-        Box deserAppleBox = MAPPER.readValue(json, Box.class);
+    private void checkAppleBoxEmpty(ObjectReader reader, String json) throws Exception {
+        Box deserAppleBox = reader.readValue(json);
         assertEquals(appleBox.getType(), deserAppleBox.getType());
 
         Fruit deserApple = deserAppleBox.fruit;
@@ -227,21 +230,21 @@
         assertEquals(0, ((Apple) deserApple).getSeedCount());
     }
 
-    private void checkOrangeBoxNull(String json) throws Exception {
-        Box deserOrangeBox = MAPPER.readValue(json, Box.class);
+    private void checkOrangeBoxNull(ObjectReader reader, String json) throws Exception {
+        Box deserOrangeBox = reader.readValue(json);
         assertEquals(orangeBox.getType(), deserOrangeBox.getType());
         assertNull(deserOrangeBox.getFruit());
     }
 
-    private void checkAppleBoxNull(String json) throws Exception {
-        Box deserAppleBox = MAPPER.readValue(json, Box.class);
+    private void checkAppleBoxNull(ObjectReader reader, String json) throws Exception {
+        Box deserAppleBox = reader.readValue(json);
         assertEquals(appleBox.getType(), deserAppleBox.getType());
         assertNull(deserAppleBox.getFruit());
     }
 
-    private void checkBoxJsonMappingException(String json) throws Exception {
+    private void checkBoxJsonMappingException(ObjectReader reader, String json) throws Exception {
         thrown.expect(JsonMappingException.class);
         thrown.expectMessage("Missing property 'fruit' for external type id 'type'");
-        MAPPER.readValue(json, Box.class);
+        reader.readValue(json);
     }
 }    
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/vld/BasicPTVTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/vld/BasicPTVTest.java
new file mode 100644
index 0000000..659cf49
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/vld/BasicPTVTest.java
@@ -0,0 +1,267 @@
+package com.fasterxml.jackson.databind.jsontype.vld;
+
+import java.util.regex.Pattern;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
+import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
+import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
+
+/**
+ * Tests for the main user-configurable {@code PolymorphicTypeValidator},
+ * {@link BasicPolymorphicTypeValidator}.
+ */
+public class BasicPTVTest extends BaseMapTest
+{
+    // // // Value types
+
+    static abstract class BaseValue {
+        public int x = 3;
+    }
+
+    static class ValueA extends BaseValue {
+        protected ValueA() { }
+        public ValueA(int x) {
+            super();
+            this.x = x;
+        }
+    }
+
+    static class ValueB extends BaseValue {
+        protected ValueB() { }
+        public ValueB(int x) {
+            super();
+            this.x = x;
+        }
+    }
+
+    // // // Value types
+
+    // make this type `final` to avoid polymorphic handling
+    static final class BaseValueWrapper {
+        public BaseValue value;
+
+        protected BaseValueWrapper() { }
+
+        public static BaseValueWrapper withA(int x) {
+            BaseValueWrapper w = new BaseValueWrapper();
+            w.value = new ValueA(x);
+            return w;
+        }
+
+        public static BaseValueWrapper withB(int x) {
+            BaseValueWrapper w = new BaseValueWrapper();
+            w.value = new ValueB(x);
+            return w;
+        }
+    }
+
+    static final class ObjectWrapper {
+        public Object value;
+
+        protected ObjectWrapper() { }
+        public ObjectWrapper(Object v) { value = v; }
+    }
+
+    static final class NumberWrapper {
+        public Number value;
+
+        protected NumberWrapper() { }
+        public NumberWrapper(Number v) { value = v; }
+    }
+    
+    /*
+    /**********************************************************************
+    /* Test methods: by base type, pass
+    /**********************************************************************
+     */
+
+    // First: test simple Base-type-as-class allowing
+    public void testAllowByBaseClass() throws Exception {
+        final PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
+                .allowIfBaseType(BaseValue.class)
+                .build();
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(ptv, DefaultTyping.NON_FINAL)
+                .build();        
+
+        // First, test accepted case
+        final String json = mapper.writeValueAsString(BaseValueWrapper.withA(42));
+        BaseValueWrapper w = mapper.readValue(json, BaseValueWrapper.class);
+        assertEquals(42, w.value.x);
+
+        // then non-accepted
+        final String json2 = mapper.writeValueAsString(new NumberWrapper(Byte.valueOf((byte) 4)));
+        try {
+            mapper.readValue(json2, NumberWrapper.class);
+            fail("Should not pass");
+        } catch (InvalidTypeIdException e) {
+            verifyException(e, "Could not resolve type id 'java.lang.Byte'");
+            verifyException(e, "as a subtype of");
+        }
+
+        // and then yet again accepted one with different config
+        ObjectMapper mapper2 = jsonMapperBuilder()
+                .activateDefaultTyping(BasicPolymorphicTypeValidator.builder()
+                        .allowIfBaseType(Number.class)
+                        .build(), DefaultTyping.NON_FINAL)
+                .build();
+        NumberWrapper nw = mapper2.readValue(json2, NumberWrapper.class);
+        assertNotNull(nw);
+        assertEquals(Byte.valueOf((byte) 4), nw.value);
+    }
+
+    // Then subtype-prefix
+    public void testAllowByBaseClassPrefix() throws Exception {
+        final PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
+                .allowIfBaseType("com.fasterxml.")
+                .build();
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(ptv, DefaultTyping.NON_FINAL)
+                .build();        
+
+        // First, test accepted case
+        final String json = mapper.writeValueAsString(BaseValueWrapper.withA(42));
+        BaseValueWrapper w = mapper.readValue(json, BaseValueWrapper.class);
+        assertEquals(42, w.value.x);
+
+        // then non-accepted
+        final String json2 = mapper.writeValueAsString(new NumberWrapper(Byte.valueOf((byte) 4)));
+        try {
+            mapper.readValue(json2, NumberWrapper.class);
+            fail("Should not pass");
+        } catch (InvalidTypeIdException e) {
+            verifyException(e, "Could not resolve type id 'java.lang.Byte'");
+            verifyException(e, "as a subtype of");
+        }
+    }
+
+    // Then subtype-pattern
+    public void testAllowByBaseClassPattern() throws Exception {
+        final PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
+                .allowIfBaseType(Pattern.compile("\\w+\\.fasterxml\\..+"))
+                .build();
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(ptv, DefaultTyping.NON_FINAL)
+                .build();        
+
+        // First, test accepted case
+        final String json = mapper.writeValueAsString(BaseValueWrapper.withA(42));
+        BaseValueWrapper w = mapper.readValue(json, BaseValueWrapper.class);
+        assertEquals(42, w.value.x);
+
+        // then non-accepted
+        final String json2 = mapper.writeValueAsString(new NumberWrapper(Byte.valueOf((byte) 4)));
+        try {
+            mapper.readValue(json2, NumberWrapper.class);
+            fail("Should not pass");
+        } catch (InvalidTypeIdException e) {
+            verifyException(e, "Could not resolve type id 'java.lang.Byte'");
+            verifyException(e, "as a subtype of");
+        }
+    }
+
+    // And finally, block by specific direct-match base type
+    public void testDenyByBaseClass() throws Exception {
+        final PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
+                // indicate that all subtypes `BaseValue` would be fine
+                .allowIfBaseType(BaseValue.class)
+                // but that nominal base type MUST NOT be `Object.class`
+                .denyForExactBaseType(Object.class)
+                .build();
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(ptv, DefaultTyping.NON_FINAL)
+                .build();        
+        final String json = mapper.writeValueAsString(new ObjectWrapper(new ValueA(15)));
+        try {
+            mapper.readValue(json, ObjectWrapper.class);
+            fail("Should not pass");
+
+        // NOTE: different exception type since denial was for whole property, not just specific values
+        } catch (InvalidDefinitionException e) {
+            verifyException(e, "denied resolution of all subtypes of base type `java.lang.Object`");
+        }
+    }
+
+    /*
+    /**********************************************************************
+    /* Test methods: by sub type
+    /**********************************************************************
+     */
+
+    public void testAllowBySubClass() throws Exception {
+        final PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
+                .allowIfSubType(ValueB.class)
+                .build();
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(ptv, DefaultTyping.NON_FINAL)
+                .build();        
+
+        // First, test accepted case
+        final String json = mapper.writeValueAsString(BaseValueWrapper.withB(42));
+        BaseValueWrapper w = mapper.readValue(json, BaseValueWrapper.class);
+        assertEquals(42, w.value.x);
+
+        // then non-accepted
+        try {
+            mapper.readValue(mapper.writeValueAsString(BaseValueWrapper.withA(43)),
+                    BaseValueWrapper.class);
+            fail("Should not pass");
+        } catch (InvalidTypeIdException e) {
+            verifyException(e, "Could not resolve type id 'com.fasterxml.jackson.");
+            verifyException(e, "as a subtype of");
+        }
+    }
+
+    public void testAllowBySubClassPrefix() throws Exception {
+        final PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
+                .allowIfSubType(ValueB.class.getName())
+                .build();
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(ptv, DefaultTyping.NON_FINAL)
+                .build();        
+
+        // First, test accepted case
+        final String json = mapper.writeValueAsString(BaseValueWrapper.withB(42));
+        BaseValueWrapper w = mapper.readValue(json, BaseValueWrapper.class);
+        assertEquals(42, w.value.x);
+
+        // then non-accepted
+        try {
+            mapper.readValue(mapper.writeValueAsString(BaseValueWrapper.withA(43)),
+                    BaseValueWrapper.class);
+            fail("Should not pass");
+        } catch (InvalidTypeIdException e) {
+            verifyException(e, "Could not resolve type id 'com.fasterxml.jackson.");
+            verifyException(e, "as a subtype of");
+        }
+    }
+
+    public void testAllowBySubClassPattern() throws Exception {
+        final PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
+                .allowIfSubType(Pattern.compile(Pattern.quote(ValueB.class.getName())))
+                .build();
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(ptv, DefaultTyping.NON_FINAL)
+                .build();        
+
+        // First, test accepted case
+        final String json = mapper.writeValueAsString(BaseValueWrapper.withB(42));
+        BaseValueWrapper w = mapper.readValue(json, BaseValueWrapper.class);
+        assertEquals(42, w.value.x);
+
+        // then non-accepted
+        try {
+            mapper.readValue(mapper.writeValueAsString(BaseValueWrapper.withA(43)),
+                    BaseValueWrapper.class);
+            fail("Should not pass");
+        } catch (InvalidTypeIdException e) {
+            verifyException(e, "Could not resolve type id 'com.fasterxml.jackson.");
+            verifyException(e, "as a subtype of");
+        }
+    }
+}
+
+
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/vld/BasicPTVWithArraysTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/vld/BasicPTVWithArraysTest.java
new file mode 100644
index 0000000..dfd5617
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/vld/BasicPTVWithArraysTest.java
@@ -0,0 +1,97 @@
+package com.fasterxml.jackson.databind.jsontype.vld;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
+import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
+
+/**
+ * Tests related to [databind#2534], support for configuring
+ * {@link BasicPolymorphicTypeValidator} to allow all Array-valued
+ * polymorphic values.
+ */
+public class BasicPTVWithArraysTest extends BaseMapTest
+{
+    static abstract class Base2534 {
+        public int x = 3;
+    }
+
+    static class Good2534 extends Base2534 {
+        protected Good2534() { }
+        public Good2534(int x) {
+            super();
+            this.x = x;
+        }
+    }
+
+    static class Bad2534 extends Base2534 {
+        protected Bad2534() { }
+        public Bad2534(int x) {
+            super();
+            this.x = x;
+        }
+    }
+
+    static final class ObjectWrapper {
+        public Object value;
+
+        protected ObjectWrapper() { }
+        public ObjectWrapper(Object v) { value = v; }
+    }
+
+    /*
+    /**********************************************************************
+    /* Test methods: structured types
+    /**********************************************************************
+     */
+
+    // [databind#2534]: handle Java array-types appropriately wrt validation
+    public void testAllowBySubClassInArray() throws Exception {
+        PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
+                .allowIfSubType(Good2534.class)
+                .build();
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(ptv, DefaultTyping.NON_FINAL)
+                .build();        
+
+        final String json = mapper.writeValueAsString(new ObjectWrapper(new Base2534[] { new Good2534(42) }));
+
+        // First test blocked case:
+        try {
+            mapper.readValue(json, ObjectWrapper.class);
+            fail("Should not pass");
+        } catch (InvalidTypeIdException e) {
+            verifyException(e, "Could not resolve type id '[Lcom.fasterxml.jackson.");
+            verifyException(e, "as a subtype of");
+        }
+
+        // and then accepted:
+        ptv = BasicPolymorphicTypeValidator.builder()
+                .allowIfSubTypeIsArray() // key addition
+                .allowIfSubType(Good2534.class)
+                .build();
+        mapper = jsonMapperBuilder()
+                .activateDefaultTyping(ptv, DefaultTyping.NON_FINAL)
+                .build();        
+
+        ObjectWrapper w = mapper.readValue(json, ObjectWrapper.class);
+        assertNotNull(w);
+        assertNotNull(w.value);
+        assertEquals(Base2534[].class, w.value.getClass());
+        Base2534[] arrayOut = (Base2534[]) w.value;
+        assertEquals(1, arrayOut.length);
+        assertEquals(42, arrayOut[0].x);
+
+        // but ensure array-acceptance does NOT allow non-validated element types!
+        final String badJson = mapper.writeValueAsString(new ObjectWrapper(new Base2534[] { new Bad2534(13) }));
+        try {
+            mapper.readValue(badJson, ObjectWrapper.class);
+            fail("Should not pass");
+        } catch (InvalidTypeIdException e) {
+            verifyException(e, "Could not resolve type id 'com.fasterxml.jackson.");
+            verifyException(e, "$Bad2534");
+            verifyException(e, "as a subtype of");
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/vld/ValidatePolymBaseTypeTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/vld/ValidatePolymBaseTypeTest.java
new file mode 100644
index 0000000..4281484
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/vld/ValidatePolymBaseTypeTest.java
@@ -0,0 +1,146 @@
+package com.fasterxml.jackson.databind.jsontype.vld;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.cfg.MapperConfig;
+import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
+
+/**
+ * Tests to verify working of customizable {@PolymorphicTypeValidator},
+ * see [databind#2195], regarding verification of base type checks.
+ *
+ * @since 2.10
+ */
+public class ValidatePolymBaseTypeTest extends BaseMapTest
+{
+    // // // Value types
+
+    static abstract class BaseValue {
+        public int x = 3;
+    }
+
+    static class BadValue extends BaseValue { }
+    static class GoodValue extends BaseValue { }
+
+    // // // Wrapper types
+
+    static final class AnnotatedGoodWrapper {
+        @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
+        public GoodValue value;
+
+        protected AnnotatedGoodWrapper() { value = new GoodValue(); }
+    }
+
+    static final class AnnotatedBadWrapper {
+        @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
+        public BadValue value;
+
+        protected AnnotatedBadWrapper() { value = new BadValue(); }
+    }
+
+    static final class DefTypeGoodWrapper {
+        public GoodValue value;
+
+        protected DefTypeGoodWrapper() { value = new GoodValue(); }
+    }
+
+    static final class DefTypeBadWrapper {
+        public BadValue value;
+
+        protected DefTypeBadWrapper() { value = new BadValue(); }
+    }
+
+    // // // Validator implementations
+
+    static class BaseTypeValidator extends PolymorphicTypeValidator {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public Validity validateBaseType(MapperConfig<?> ctxt, JavaType baseType) {
+            final Class<?> raw = baseType.getRawClass();
+            if (raw == BadValue.class) {
+                return Validity.DENIED;
+            }
+            if (raw == GoodValue.class) {
+                return Validity.ALLOWED;
+            }
+            // defaults to denied, then:
+            return Validity.INDETERMINATE;
+        }
+
+        @Override
+        public Validity validateSubClassName(MapperConfig<?> ctxt, JavaType baseType, String subClassName) {
+            return Validity.DENIED;
+        }
+
+        @Override
+        public Validity validateSubType(MapperConfig<?> ctxt, JavaType baseType, JavaType subType) {
+            return Validity.DENIED;
+        }
+    }
+
+    // // // Mappers with Default Typing
+
+    // // // Mappers without Default Typing (explicit annotation needed)
+
+    private final ObjectMapper MAPPER_ANNOTATED = jsonMapperBuilder()
+            .polymorphicTypeValidator(new BaseTypeValidator())
+            .build();
+
+    private final ObjectMapper MAPPER_DEF_TYPING = jsonMapperBuilder()
+            // Since GoodBalue, BadValue not abstraction need to use non-final
+            .activateDefaultTyping(new BaseTypeValidator(), DefaultTyping.NON_FINAL)
+            .build();
+
+    /*
+    /**********************************************************************
+    /* Test methods: annotated
+    /**********************************************************************
+     */
+
+    public void testAnnotedGood() throws Exception {
+        final String json = MAPPER_ANNOTATED.writeValueAsString(new AnnotatedGoodWrapper());
+        // should work ok
+        assertNotNull(MAPPER_DEF_TYPING.readValue(json, AnnotatedGoodWrapper.class));
+    }
+
+    public void testAnnotedBad() throws Exception {
+        final String json = MAPPER_ANNOTATED.writeValueAsString(new AnnotatedBadWrapper());
+        // should fail
+        try {
+            MAPPER_ANNOTATED.readValue(json, AnnotatedBadWrapper.class);
+            fail("Should not pass");
+        } catch (InvalidDefinitionException e) {
+            verifyException(e, "Configured `PolymorphicTypeValidator`");
+            verifyException(e, "denied resolution of");
+            verifyException(e, "all subtypes of base type");
+        }
+    }
+   
+    /*
+    /**********************************************************************
+    /* Test methods: default typing
+    /**********************************************************************
+     */
+
+    public void testDefaultGood() throws Exception {
+        final String json = MAPPER_DEF_TYPING.writeValueAsString(new DefTypeGoodWrapper());
+        // should work ok
+        assertNotNull(MAPPER_DEF_TYPING.readValue(json, DefTypeGoodWrapper.class));
+    }
+
+    public void testDefaultBad() throws Exception {
+        final String json = MAPPER_DEF_TYPING.writeValueAsString(new DefTypeBadWrapper());
+        // should fail
+        try {
+            MAPPER_DEF_TYPING.readValue(json, DefTypeBadWrapper.class);
+            fail("Should not pass");
+        } catch (InvalidDefinitionException e) {
+            verifyException(e, "Configured `PolymorphicTypeValidator`");
+            verifyException(e, "denied resolution of");
+            verifyException(e, "all subtypes of base type");
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/vld/ValidatePolymSubTypeTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/vld/ValidatePolymSubTypeTest.java
new file mode 100644
index 0000000..64959a7
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/vld/ValidatePolymSubTypeTest.java
@@ -0,0 +1,343 @@
+package com.fasterxml.jackson.databind.jsontype.vld;
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.cfg.MapperConfig;
+import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
+
+/**
+ * Tests to verify working of customizable {@PolymorphicTypeValidator},
+ * see [databind#2195], regarding verification of subtype instances.
+ *
+ * @since 2.10
+ */
+public class ValidatePolymSubTypeTest extends BaseMapTest
+{
+    // // // Value types
+
+    static abstract class BaseValue {
+        public int x = 3;
+
+        @Override
+        public boolean equals(Object other) {
+            return (other != null)
+                    && (getClass() == other.getClass())
+                    && ((BaseValue) other).x == this.x
+                    ;
+        }
+    }
+
+    static class BadValue extends BaseValue { }
+    static class GoodValue extends BaseValue { }
+    static class MehValue extends BaseValue { }
+    
+    // // // Wrapper types
+
+    static class AnnotatedWrapper {
+        @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
+        public BaseValue value;
+
+        protected AnnotatedWrapper() { }
+        public AnnotatedWrapper(BaseValue v) { value = v; }
+    }
+
+    static class AnnotatedMinimalWrapper {
+        @JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS)
+        public BaseValue value;
+
+        protected AnnotatedMinimalWrapper() { }
+        public AnnotatedMinimalWrapper(BaseValue v) { value = v; }
+    }
+
+    static class DefTypeWrapper {
+        public BaseValue value;
+
+        protected DefTypeWrapper() { }
+        public DefTypeWrapper(BaseValue v) { value = v; }
+    }
+
+    // // // Validator implementations
+    
+    static class SimpleNameBasedValidator extends PolymorphicTypeValidator {
+        private static final long serialVersionUID = 1L;
+
+        // No categoric determination, depends on subtype
+        @Override
+        public Validity validateBaseType(MapperConfig<?> ctxt, JavaType baseType) {
+            return Validity.INDETERMINATE;
+        }
+
+        @Override
+        public Validity validateSubClassName(MapperConfig<?> ctxt, JavaType baseType, String subClassName) {
+            if (subClassName.equals(BadValue.class.getName())) {
+                return Validity.DENIED;
+            }
+            if (subClassName.equals(GoodValue.class.getName())) {
+                return Validity.ALLOWED;
+            }
+            return Validity.INDETERMINATE;
+        }
+
+        @Override
+        public Validity validateSubType(MapperConfig<?> ctxt, JavaType baseType, JavaType subType) {
+            return Validity.DENIED;
+        }
+    }
+
+    static class SimpleClassBasedValidator extends PolymorphicTypeValidator {
+        private static final long serialVersionUID = 1L;
+
+        @Override
+        public Validity validateBaseType(MapperConfig<?> ctxt, JavaType baseType) {
+            return Validity.INDETERMINATE;
+        }
+
+        @Override
+        public Validity validateSubClassName(MapperConfig<?> ctxt, JavaType baseType, String subClassName) {
+            return Validity.INDETERMINATE;
+        }
+
+        @Override
+        public Validity validateSubType(MapperConfig<?> ctxt, JavaType baseType, JavaType subType) {
+            if (subType.hasRawClass(BadValue.class)) {
+                return Validity.DENIED;
+            }
+            if (subType.hasRawClass(GoodValue.class)) {
+                return Validity.ALLOWED;
+            }
+            // defaults to denied, then:
+            return Validity.INDETERMINATE;        }
+    }
+
+    // // // Mappers with Default Typing
+    
+    private final ObjectMapper MAPPER_DEF_TYPING_NAME_CHECK = jsonMapperBuilder()
+            .activateDefaultTyping(new SimpleNameBasedValidator())
+            .build();
+
+    private final ObjectMapper MAPPER_DEF_TYPING_CLASS_CHECK = jsonMapperBuilder()
+            .activateDefaultTyping(new SimpleClassBasedValidator())
+            .build();
+
+    // // // Mappers without Default Typing (explicit annotation needed)
+
+    private final ObjectMapper MAPPER_EXPLICIT_NAME_CHECK = jsonMapperBuilder()
+            .polymorphicTypeValidator(new SimpleNameBasedValidator())
+            .build();
+
+    private final ObjectMapper MAPPER_EXPLICIT_CLASS_CHECK = jsonMapperBuilder()
+            .polymorphicTypeValidator(new SimpleClassBasedValidator())
+            .build();
+
+    /*
+    /**********************************************************************
+    /* Test methods: default typing
+    /**********************************************************************
+     */
+
+    // // With Name check
+
+    public void testWithDefaultTypingNameAccept() throws Exception
+    {
+        final BaseValue inputValue = new GoodValue();
+        DefTypeWrapper result = _roundTripDefault(MAPPER_DEF_TYPING_NAME_CHECK, inputValue);
+        assertEquals(inputValue, result.value);
+    }
+
+    public void testWithDefaultTypingNameDenyExplicit() throws Exception
+    {
+        _verifyBadDefaultValue(MAPPER_DEF_TYPING_NAME_CHECK);
+    }
+
+    public void testWithDefaultTypingNameDenyDefault() throws Exception
+    {
+        _verifyMehDefaultValue(MAPPER_DEF_TYPING_NAME_CHECK);
+    }
+
+    // // With Class check
+
+    public void testWithDefaultTypingClassAccept() throws Exception
+    {
+        final BaseValue inputValue = new GoodValue();
+        DefTypeWrapper result = _roundTripDefault(MAPPER_DEF_TYPING_CLASS_CHECK, inputValue);
+        assertEquals(inputValue, result.value);
+    }
+
+    public void testWithDefaultTypingClassDenyExplicit() throws Exception
+    {
+        _verifyBadDefaultValue(MAPPER_DEF_TYPING_CLASS_CHECK);
+    }
+
+    public void testWithDefaultTypingClassDenyDefault() throws Exception
+    {
+        _verifyMehDefaultValue(MAPPER_DEF_TYPING_CLASS_CHECK);
+    }
+    
+    /*
+    /**********************************************************************
+    /* Test methods, annotated typing, full class
+    /**********************************************************************
+     */
+
+    // // With Name
+
+    public void testWithAnnotationNameAccept() throws Exception
+    {
+        final BaseValue inputValue = new GoodValue();
+        AnnotatedWrapper result = _roundTripAnnotated(MAPPER_EXPLICIT_NAME_CHECK, inputValue);
+        assertEquals(inputValue, result.value);
+    }
+
+    public void testWithAnnotationNameDenyExplicit() throws Exception
+    {
+        _verifyBadAnnotatedValue(MAPPER_EXPLICIT_NAME_CHECK);
+    }
+
+    public void testWithAnnotationNameDenyDefault() throws Exception
+    {
+        _verifyMehAnnotatedValue(MAPPER_EXPLICIT_NAME_CHECK);
+    }
+
+    // // With Class
+
+    public void testWithAnnotationClassAccept() throws Exception
+    {
+        final BaseValue inputValue = new GoodValue();
+        AnnotatedWrapper result = _roundTripAnnotated(MAPPER_EXPLICIT_CLASS_CHECK, inputValue);
+        assertEquals(inputValue, result.value);
+    }
+
+    public void testWithAnnotationClassDenyExplicit() throws Exception
+    {
+        _verifyBadAnnotatedValue(MAPPER_EXPLICIT_CLASS_CHECK);
+    }
+
+    public void testWithAnnotationClassDenyDefault() throws Exception
+    {
+        _verifyMehAnnotatedValue(MAPPER_EXPLICIT_CLASS_CHECK);
+    }
+    
+    /*
+    /**********************************************************************
+    /* Test methods, annotated typing, minimal class name
+    /**********************************************************************
+     */
+
+    // // With Name
+
+    public void testWithAnnotationMinClassNameAccept() throws Exception
+    {
+        final BaseValue inputValue = new GoodValue();
+        AnnotatedMinimalWrapper result = _roundTripAnnotatedMinimal(MAPPER_EXPLICIT_NAME_CHECK, inputValue);
+        assertEquals(inputValue, result.value);
+    }
+
+    public void testWithAnnotationMinClassNameDenyExplicit() throws Exception
+    {
+        _verifyBadAnnotatedMinValue(MAPPER_EXPLICIT_NAME_CHECK);
+    }
+
+    public void testWithAnnotationMinClassNameDenyDefault() throws Exception
+    {
+        _verifyMehAnnotatedMinValue(MAPPER_EXPLICIT_NAME_CHECK);
+    }
+
+    // // With Class
+
+    public void testWithAnnotationMinClassClassAccept() throws Exception
+    {
+        final BaseValue inputValue = new GoodValue();
+        AnnotatedMinimalWrapper result = _roundTripAnnotatedMinimal(MAPPER_EXPLICIT_CLASS_CHECK, inputValue);
+        assertEquals(inputValue, result.value);
+    }
+
+    public void testWithAnnotationMinClassClassDenyExplicit() throws Exception
+    {
+        _verifyBadAnnotatedMinValue(MAPPER_EXPLICIT_CLASS_CHECK);
+    }
+
+    public void testWithAnnotationMinClassClassDenyDefault() throws Exception
+    {
+        _verifyMehAnnotatedMinValue(MAPPER_EXPLICIT_CLASS_CHECK);
+    }
+    
+    /*
+    /**********************************************************************
+    /* Helper methods, round-trip (ok case)
+    /**********************************************************************
+     */
+
+    private DefTypeWrapper _roundTripDefault(ObjectMapper mapper, BaseValue input) throws Exception {
+        final String json = mapper.writeValueAsString(new DefTypeWrapper(input));
+        return mapper.readValue(json, DefTypeWrapper.class);
+    }
+
+    private AnnotatedWrapper _roundTripAnnotated(ObjectMapper mapper, BaseValue input) throws Exception {
+        final String json = mapper.writeValueAsString(new AnnotatedWrapper(input));
+        return mapper.readValue(json, AnnotatedWrapper.class);
+    }
+
+    private AnnotatedMinimalWrapper _roundTripAnnotatedMinimal(ObjectMapper mapper, BaseValue input) throws Exception {
+        final String json = mapper.writeValueAsString(new AnnotatedMinimalWrapper(input));
+        return mapper.readValue(json, AnnotatedMinimalWrapper.class);
+    }
+
+    /*
+    /**********************************************************************
+    /* Helper methods, failing deser verification
+    /**********************************************************************
+     */
+    
+    private void _verifyBadDefaultValue(ObjectMapper mapper) throws Exception {
+        final String json = mapper.writeValueAsString(new DefTypeWrapper(new BadValue()));
+        _verifyBadValue(mapper, json, DefTypeWrapper.class);
+    }
+
+    private void _verifyMehDefaultValue(ObjectMapper mapper) throws Exception {
+        final String json = mapper.writeValueAsString(new DefTypeWrapper(new MehValue()));
+        _verifyMehValue(mapper, json, DefTypeWrapper.class);
+    }
+
+    private void _verifyBadAnnotatedValue(ObjectMapper mapper) throws Exception {
+        final String json = mapper.writeValueAsString(new AnnotatedWrapper(new BadValue()));
+        _verifyBadValue(mapper, json, AnnotatedWrapper.class);
+    }
+
+    private void _verifyMehAnnotatedValue(ObjectMapper mapper) throws Exception {
+        final String json = mapper.writeValueAsString(new AnnotatedWrapper(new MehValue()));
+        _verifyMehValue(mapper, json, AnnotatedWrapper.class);
+    }
+
+    private void _verifyBadAnnotatedMinValue(ObjectMapper mapper) throws Exception {
+        final String json = mapper.writeValueAsString(new AnnotatedMinimalWrapper(new BadValue()));
+        _verifyBadValue(mapper, json, AnnotatedMinimalWrapper.class);
+    }
+
+    private void _verifyMehAnnotatedMinValue(ObjectMapper mapper) throws Exception {
+        final String json = mapper.writeValueAsString(new AnnotatedMinimalWrapper(new MehValue()));
+        _verifyMehValue(mapper, json, AnnotatedMinimalWrapper.class);
+    }
+
+    private void _verifyBadValue(ObjectMapper mapper, String json, Class<?> type) throws Exception {
+        try {
+            mapper.readValue(json, type);
+            fail("Should not pass");
+        } catch (InvalidTypeIdException e) {
+            verifyException(e, "Could not resolve type id");
+            verifyException(e, "`PolymorphicTypeValidator`");
+            verifyException(e, "denied resolution");
+        }
+    }
+
+    private void _verifyMehValue(ObjectMapper mapper, String json, Class<?> type) throws Exception {
+        try {
+            mapper.readValue(json, type);
+            fail("Should not pass");
+        } catch (InvalidTypeIdException e) {
+            verifyException(e, "Could not resolve type id");
+            verifyException(e, "`PolymorphicTypeValidator`");
+            verifyException(e, "denied resolution");
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/misc/AccessFixTest.java b/src/test/java/com/fasterxml/jackson/databind/misc/AccessFixTest.java
index c53b9d3..94e37df 100644
--- a/src/test/java/com/fasterxml/jackson/databind/misc/AccessFixTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/misc/AccessFixTest.java
@@ -24,8 +24,9 @@
     public void testCauseOfThrowableIgnoral() throws Exception
     {
         final SecurityManager origSecMan = System.getSecurityManager();
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.disable(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .disable(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)
+                .build();
         try {
             System.setSecurityManager(new CauseBlockingSecurityManager());
             _testCauseOfThrowableIgnoral(mapper);
diff --git a/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitive1854Test.java b/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitive1854Test.java
deleted file mode 100644
index 10f5449..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitive1854Test.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.fasterxml.jackson.databind.misc;
-
-import java.util.List;
-
-import com.fasterxml.jackson.annotation.*;
-import com.fasterxml.jackson.databind.*;
-
-public class CaseInsensitive1854Test extends BaseMapTest
-{
-    static class Obj1854 {
-        private final int id;
-
-// 17-Dec-2017, tatu: One of following would work around the bug [databind#1854]        
-//        @JsonProperty("Items")
-//        @JsonIgnore
-        private final List<ChildObj> items;
-
-        public Obj1854(int id, List<ChildObj> items) {
-            this.id = id;
-            this.items = items;
-        }
-
-        @JsonCreator
-        public static Obj1854 fromJson(@JsonProperty("ID") int id,
-                @JsonProperty("Items") List<ChildObj> items) {
-            return new Obj1854(id, items);
-        }
-
-        public int getId() {
-            return id;
-        }
-
-        public List<ChildObj> getItems() {
-            return items;
-        }
-
-    }
-
-    static class ChildObj {
-        private final String childId;
-
-        private ChildObj(String id) {
-            this.childId = id;
-        }
-
-        @JsonCreator
-        public static ChildObj fromJson(@JsonProperty("ChildID") String cid) {
-            return new ChildObj(cid);
-        }
-
-        public String getId() {
-            return childId;
-        }
-    }
-
-    public void testIssue1854() throws Exception
-    {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
-        final String DOC = aposToQuotes("{'ID': 1, 'Items': [ { 'ChildID': 10 } ]}");
-        Obj1854 result = mapper.readValue(DOC, Obj1854.class);
-        assertNotNull(result);
-        assertEquals(1, result.getId());
-        assertNotNull(result.getItems());
-        assertEquals(1, result.getItems().size());
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeserTest.java
index 9ae53ca..3620393 100644
--- a/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeserTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeserTest.java
@@ -1,9 +1,13 @@
 package com.fasterxml.jackson.databind.misc;
 
+import java.util.List;
+
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonProperty;
+
 import com.fasterxml.jackson.core.JsonProcessingException;
+
 import com.fasterxml.jackson.databind.*;
 
 public class CaseInsensitiveDeserTest extends BaseMapTest
@@ -44,6 +48,51 @@
         }
     }
 
+    // [databind#1854]
+    static class Obj1854 {
+        private final int id;
+
+        private final List<ChildObj1854> items;
+
+        public Obj1854(int id, List<ChildObj1854> items) {
+            this.id = id;
+            this.items = items;
+        }
+
+        @JsonCreator
+        public static Obj1854 fromJson(@JsonProperty("ID") int id,
+                @JsonProperty("Items") List<ChildObj1854> items) {
+            return new Obj1854(id, items);
+        }
+
+        public int getId() {
+            return id;
+        }
+
+        public List<ChildObj1854> getItems() {
+            return items;
+        }
+
+    }
+
+    // [databind#1854]
+    static class ChildObj1854 {
+        private final String childId;
+
+        private ChildObj1854(String id) {
+            this.childId = id;
+        }
+
+        @JsonCreator
+        public static ChildObj1854 fromJson(@JsonProperty("ChildID") String cid) {
+            return new ChildObj1854(cid);
+        }
+
+        public String getId() {
+            return childId;
+        }
+    }
+
     /*
     /********************************************************
     /* Test methods
@@ -51,13 +100,11 @@
      */
 
     private final ObjectMapper MAPPER = new ObjectMapper();
-    private final ObjectMapper INSENSITIVE_MAPPER = new ObjectMapper();
-    {
-        INSENSITIVE_MAPPER.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
-        
-    }
+    private final ObjectMapper INSENSITIVE_MAPPER = jsonMapperBuilder()
+            .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
+            .build();
 
-// [databind#566]
+    // [databind#566]
     public void testCaseInsensitiveDeserialization() throws Exception
     {
         final String JSON = "{\"Value1\" : {\"nAme\" : \"fruit\", \"vALUe\" : \"apple\"}, \"valUE2\" : {\"NAME\" : \"color\", \"value\" : \"red\"}}";
@@ -124,4 +171,14 @@
         assertEquals("12", role.ID);
         assertEquals("Foo", role.Name);
     }
+
+    public void testIssue1854() throws Exception
+    {
+        final String DOC = aposToQuotes("{'ID': 1, 'Items': [ { 'ChildID': 10 } ]}");
+        Obj1854 result = INSENSITIVE_MAPPER.readValue(DOC, Obj1854.class);
+        assertNotNull(result);
+        assertEquals(1, result.getId());
+        assertNotNull(result.getItems());
+        assertEquals(1, result.getItems().size());
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/misc/RaceCondition738Test.java b/src/test/java/com/fasterxml/jackson/databind/misc/RaceCondition738Test.java
index bb5bb34..92254db 100644
--- a/src/test/java/com/fasterxml/jackson/databind/misc/RaceCondition738Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/misc/RaceCondition738Test.java
@@ -63,7 +63,7 @@
     }
     
     void runOnce(int round, int max) throws Exception {
-        final ObjectMapper mapper = newObjectMapper();
+        final ObjectMapper mapper = newJsonMapper();
         Callable<String> writeJson = new Callable<String>() {
             @Override
             public String call() throws Exception {
diff --git a/src/test/java/com/fasterxml/jackson/databind/misc/ThreadSafety1759Test.java b/src/test/java/com/fasterxml/jackson/databind/misc/ThreadSafety1759Test.java
index 236629f..43ceaaa 100644
--- a/src/test/java/com/fasterxml/jackson/databind/misc/ThreadSafety1759Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/misc/ThreadSafety1759Test.java
@@ -19,7 +19,7 @@
 
     public void testCalendarForDeser() throws Exception
     {
-        final ObjectMapper mapper = newObjectMapper();
+        final ObjectMapper mapper = newJsonMapper();
 
         final int numThreads = 4;
         final int COUNT = 3000;
diff --git a/src/test/java/com/fasterxml/jackson/databind/mixins/MapperMixinsCopy1998Test.java b/src/test/java/com/fasterxml/jackson/databind/mixins/MapperMixinsCopy1998Test.java
index 32897e6..9426c8d 100644
--- a/src/test/java/com/fasterxml/jackson/databind/mixins/MapperMixinsCopy1998Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/mixins/MapperMixinsCopy1998Test.java
@@ -118,10 +118,12 @@
 
     private ObjectMapper defaultMapper()
     {
-        return new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
+        return jsonMapperBuilder()
+                .defaultPropertyInclusion(JsonInclude.Value.construct(JsonInclude.Include.NON_EMPTY,
+                        JsonInclude.Include.NON_EMPTY))
                 .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
                 .configure(MapperFeature.ALLOW_COERCION_OF_SCALARS, false)
                 .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true)
-            ;
+                .build();
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinMerging.java b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinMerging.java
index 76230de..e9cd75e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinMerging.java
+++ b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinMerging.java
@@ -34,19 +34,19 @@
     /**********************************************************
      */
     
-    // for [Issue#515]
+    // for [databind#515]
     public void testDisappearingMixins515() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.disable(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS)
-            .disable(MapperFeature.AUTO_DETECT_FIELDS)
-            .disable(MapperFeature.AUTO_DETECT_GETTERS)
-            .disable(MapperFeature.AUTO_DETECT_IS_GETTERS)
-            .disable(MapperFeature.INFER_PROPERTY_MUTATORS);
         SimpleModule module = new SimpleModule("Test");
-        module.setMixInAnnotation(Person.class, PersonMixin.class);        
-        mapper.registerModule(module);
-
+        module.setMixInAnnotation(Person.class, PersonMixin.class);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .disable(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS)
+                .disable(MapperFeature.AUTO_DETECT_FIELDS)
+                .disable(MapperFeature.AUTO_DETECT_GETTERS)
+                .disable(MapperFeature.AUTO_DETECT_IS_GETTERS)
+                .disable(MapperFeature.INFER_PROPERTY_MUTATORS)
+                .addModule(module)
+                .build();
         assertEquals("{\"city\":\"Seattle\"}", mapper.writeValueAsString(new PersonImpl()));
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForMethods.java b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForMethods.java
index a57cffe..7633c77 100644
--- a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForMethods.java
+++ b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerForMethods.java
@@ -6,6 +6,7 @@
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.introspect.ClassIntrospector;
+import com.fasterxml.jackson.databind.introspect.SimpleMixInResolver;
 import com.fasterxml.jackson.databind.introspect.ClassIntrospector.MixInResolver;
 
 public class TestMixinSerForMethods
@@ -147,11 +148,18 @@
         assertEquals(Integer.valueOf(42), result.get("x"));
     }
 
+    public void testSimpleMixInResolverHasMixins() {
+        SimpleMixInResolver simple = new SimpleMixInResolver(null);
+        assertFalse(simple.hasMixIns());
+        simple.addLocalDefinition(String.class, Number.class);
+        assertTrue(simple.hasMixIns());
+    }
+
     // [databind#688]
     public void testCustomResolver() throws IOException
     {
         ObjectMapper mapper = new ObjectMapper();
-        mapper.setMixInResolver(new ClassIntrospector.MixInResolver() {
+        MixInResolver res = new ClassIntrospector.MixInResolver() {
             @Override
             public Class<?> findMixInClassFor(Class<?> target) {
                 if (target == EmptyBean.class) {
@@ -164,9 +172,13 @@
             public MixInResolver copy() {
                 return this;
             }
-        });
+        };
+        mapper.setMixInResolver(res);
         Map<String,Object> result = writeAndMap(mapper, new SimpleBean());
         assertEquals(1, result.size());
         assertEquals(Integer.valueOf(42), result.get("x"));
+
+        SimpleMixInResolver simple = new SimpleMixInResolver(res);
+        assertTrue(simple.hasMixIns());
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerWithViews.java b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerWithViews.java
index bf6ce96..db0caf5 100644
--- a/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerWithViews.java
+++ b/src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinSerWithViews.java
@@ -171,12 +171,13 @@
 
     public void testIssue560() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
         A a = new A("myname", 29, "mysurname");
 
         // Property SerializationConfig.SerializationFeature.DEFAULT_VIEW_INCLUSION set to false
-        mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, Boolean.FALSE);
-        mapper.addMixIn(A.class, AMixInAnnotation.class);
+        ObjectMapper mapper = jsonMapperBuilder()
+            .configure(MapperFeature.DEFAULT_VIEW_INCLUSION, Boolean.FALSE)
+            .addMixIn(A.class, AMixInAnnotation.class)
+            .build();
         String json = mapper.writerWithView(AView.class).writeValueAsString(a);
 
         assertTrue(json.indexOf("\"name\"") > 0);
@@ -188,12 +189,13 @@
     /**********************************************************
      */
     
-    private ObjectMapper createObjectMapper( )
+    private ObjectMapper createObjectMapper()
     {
-        ObjectMapper objectMapper = new ObjectMapper( );
-        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false );
-        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL );
-        objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false );
+        ObjectMapper objectMapper = jsonMapperBuilder()
+                .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false )
+                .serializationInclusion(JsonInclude.Include.NON_NULL )
+                .configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false )
+                .build();
     
         Map<Class<?>, Class<?>> sourceMixins = new HashMap<Class<?>, Class<?>>( );
         sourceMixins.put( SimpleTestData.class, TestDataJAXBMixin.class );
diff --git a/src/test/java/com/fasterxml/jackson/databind/module/TestAbstractTypes.java b/src/test/java/com/fasterxml/jackson/databind/module/TestAbstractTypes.java
index f007b91..088860e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/module/TestAbstractTypes.java
+++ b/src/test/java/com/fasterxml/jackson/databind/module/TestAbstractTypes.java
@@ -77,7 +77,7 @@
             return value;
         }
     }
-    
+
     /*
     /**********************************************************************
     /* Test methods
@@ -157,9 +157,9 @@
     }
 
     // [databind#2019]: mappings from multiple modules
-    public static void testAbstractMappingsFromTwoModules() throws Exception
+    public void testAbstractMappingsFromTwoModules() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
         SimpleModule module1 = new SimpleModule("module1");
         module1.addAbstractTypeMapping(Datatype1.class, SimpleDatatype1.class);
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/module/TestDuplicateRegistration.java b/src/test/java/com/fasterxml/jackson/databind/module/TestDuplicateRegistration.java
index 9adca9c..7e02bd6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/module/TestDuplicateRegistration.java
+++ b/src/test/java/com/fasterxml/jackson/databind/module/TestDuplicateRegistration.java
@@ -44,13 +44,15 @@
         mapper.registerModule(module);
         assertEquals(2, module.regCount);
 
+        final MyModule module2 = new MyModule();
         // and ditto for a new instance
-        ObjectMapper mapper2 = new ObjectMapper();
-        mapper2.disable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS);
-        MyModule module2 = new MyModule();
-        mapper.registerModule(module2);
-        mapper.registerModule(module2);
-        mapper.registerModule(module2);
+        @SuppressWarnings("unused")
+        ObjectMapper mapper2 = jsonMapperBuilder()
+                .disable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS)
+                .addModule(module2)
+                .addModule(module2)
+                .addModule(module2)
+                .build();
         assertEquals(3, module2.regCount);
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java b/src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java
index 9a1a59f..e1f21ea 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java
@@ -12,6 +12,7 @@
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.node.TextNode;
 import com.fasterxml.jackson.databind.node.TreeTraversingParser;
+import static java.util.Arrays.asList;
 
 /**
  * Additional tests for {@link ArrayNode} container class.
@@ -25,9 +26,11 @@
         assertStandardEquals(n);
         assertFalse(n.elements().hasNext());
         assertFalse(n.fieldNames().hasNext());
+        assertTrue(n.isEmpty());
         TextNode text = TextNode.valueOf("x");
         n.add(text);
         assertEquals(1, n.size());
+        assertFalse(n.isEmpty());
         assertFalse(0 == n.hashCode());
         assertTrue(n.elements().hasNext());
         // no field names for arrays
@@ -149,6 +152,7 @@
         n.add(new BigDecimal("0.2"));
         n.add(BigInteger.TEN);
         assertEquals(9, n.size());
+        assertFalse(n.isEmpty());
 
         assertNotNull(n.insertArray(0));
         assertNotNull(n.insertObject(0));
@@ -183,6 +187,23 @@
         }
     }
 
+    public void testAddAllWithNullInCollection()
+    {
+        // preparation
+        final ArrayNode array = JsonNodeFactory.instance.arrayNode();
+
+        // test
+        array.addAll(asList(null, JsonNodeFactory.instance.objectNode()));
+
+        // assertions
+        assertEquals(2, array.size());
+
+        for (JsonNode node : array) {
+            assertNotNull(node);
+        }
+        assertEquals(NullNode.getInstance(), array.get(0));
+    }
+
     public void testNullInserts()
     {
         JsonNodeFactory f = objectMapper().getNodeFactory();
@@ -239,6 +260,7 @@
         p.setCodec(null);
         assertNull(p.getCodec());
         assertNotNull(p.getParsingContext());
+//        assertTrue(p.getParsingContext().inRoot());
         assertNotNull(p.getTokenLocation());
         assertNotNull(p.getCurrentLocation());
         assertNull(p.getEmbeddedObject());
@@ -247,6 +269,8 @@
         //assertNull(p.getNumberType());
 
         assertToken(JsonToken.START_ARRAY, p.nextToken());
+        assertNotNull(p.getParsingContext());
+        assertTrue(p.getParsingContext().inArray());
         p.skipChildren();
         assertToken(JsonToken.END_ARRAY, p.getCurrentToken());
         p.close();
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/EmptyContentAsTreeTest.java b/src/test/java/com/fasterxml/jackson/databind/node/EmptyContentAsTreeTest.java
new file mode 100644
index 0000000..020ced6
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/node/EmptyContentAsTreeTest.java
@@ -0,0 +1,139 @@
+package com.fasterxml.jackson.databind.node;
+
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.TreeNode;
+import com.fasterxml.jackson.databind.*;
+
+/**
+ * Tests to verify handling of empty content with "readTree()"
+ */
+public class EmptyContentAsTreeTest extends BaseMapTest
+{
+    private final ObjectMapper MAPPER = objectMapper();
+
+    private final String EMPTY0 = "";
+    private final byte[] EMPTY0_BYTES = EMPTY0.getBytes(StandardCharsets.UTF_8);
+    private final String EMPTY1 = "  \n\t  ";
+    private final byte[] EMPTY1_BYTES = EMPTY1.getBytes(StandardCharsets.UTF_8);
+
+    // [databind#1406]: when passing `JsonParser`, indicate lack of content
+    // by returning `null`
+
+    public void testNullFromEOFWithParserAndMapper() throws Exception
+    {
+        try (JsonParser p = MAPPER.getFactory().createParser(EMPTY0)) {
+            _assertNullTree(MAPPER.readTree(p));
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(EMPTY1)) {
+            _assertNullTree(MAPPER.readTree(p));
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(new StringReader(EMPTY0))) {
+            _assertNullTree(MAPPER.readTree(p));
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(new StringReader(EMPTY1))) {
+            _assertNullTree(MAPPER.readTree(p));
+        }
+
+        try (JsonParser p = MAPPER.getFactory().createParser(EMPTY0_BYTES)) {
+            _assertNullTree(MAPPER.readTree(p));
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(EMPTY1_BYTES)) {
+            _assertNullTree(MAPPER.readTree(p));
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(EMPTY1_BYTES, 0, EMPTY1_BYTES.length)) {
+            _assertNullTree(MAPPER.readTree(p));
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(new ByteArrayInputStream(EMPTY0_BYTES))) {
+            _assertNullTree(MAPPER.readTree(p));
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(new ByteArrayInputStream(EMPTY1_BYTES))) {
+            _assertNullTree(MAPPER.readTree(p));
+        }
+    }
+
+    // [databind#1406]
+    public void testNullFromEOFWithParserAndReader() throws Exception
+    {
+        try (JsonParser p = MAPPER.getFactory().createParser(EMPTY0)) {
+            _assertNullTree(MAPPER.reader().readTree(p));
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(EMPTY1)) {
+            _assertNullTree(MAPPER.reader().readTree(p));
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(new StringReader(EMPTY0))) {
+            _assertNullTree(MAPPER.reader().readTree(p));
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(new StringReader(EMPTY1))) {
+            _assertNullTree(MAPPER.reader().readTree(p));
+        }
+
+        try (JsonParser p = MAPPER.getFactory().createParser(EMPTY0_BYTES)) {
+            _assertNullTree(MAPPER.reader().readTree(p));
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(EMPTY1_BYTES)) {
+            _assertNullTree(MAPPER.reader().readTree(p));
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(EMPTY1_BYTES, 0, EMPTY1_BYTES.length)) {
+            _assertNullTree(MAPPER.reader().readTree(p));
+        }
+
+        try (JsonParser p = MAPPER.getFactory().createParser(new ByteArrayInputStream(EMPTY0_BYTES))) {
+            _assertNullTree(MAPPER.reader().readTree(p));
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(new ByteArrayInputStream(EMPTY1_BYTES))) {
+            _assertNullTree(MAPPER.reader().readTree(p));
+        }
+    }
+
+    // [databind#2211]: when passing content sources OTHER than `JsonParser`,
+    // return "missing node" instead of alternate (return `null`, throw exception).
+    public void testMissingNodeForEOFOtherMapper() throws Exception
+    {
+        _assertMissing(MAPPER.readTree(EMPTY0));
+        _assertMissing(MAPPER.readTree(EMPTY1));
+        _assertMissing(MAPPER.readTree(new StringReader(EMPTY0)));
+        _assertMissing(MAPPER.readTree(new StringReader(EMPTY1)));
+        
+        _assertMissing(MAPPER.readTree(EMPTY0_BYTES));
+        _assertMissing(MAPPER.readTree(EMPTY0_BYTES, 0, EMPTY0_BYTES.length));
+        _assertMissing(MAPPER.readTree(new ByteArrayInputStream(EMPTY0_BYTES)));
+        _assertMissing(MAPPER.readTree(EMPTY1_BYTES));
+        _assertMissing(MAPPER.readTree(EMPTY1_BYTES, 0, EMPTY1_BYTES.length));
+        _assertMissing(MAPPER.readTree(new ByteArrayInputStream(EMPTY1_BYTES)));
+
+        // Assume File, URL, etc are fine. Note: `DataInput` probably can't be made to
+        // work since it can not easily/gracefully handle unexpected end-of-input
+    }
+
+    public void testMissingNodeViaObjectReader() throws Exception
+    {
+        _assertMissing(MAPPER.reader().readTree(EMPTY0));
+        _assertMissing(MAPPER.reader().readTree(EMPTY1));
+        _assertMissing(MAPPER.reader().readTree(new StringReader(EMPTY0)));
+        _assertMissing(MAPPER.reader().readTree(new StringReader(EMPTY1)));
+        
+        _assertMissing(MAPPER.reader().readTree(EMPTY0_BYTES));
+        _assertMissing(MAPPER.reader().readTree(EMPTY0_BYTES, 0, EMPTY0_BYTES.length));
+        _assertMissing(MAPPER.reader().readTree(new ByteArrayInputStream(EMPTY0_BYTES)));
+        _assertMissing(MAPPER.reader().readTree(EMPTY1_BYTES));
+        _assertMissing(MAPPER.reader().readTree(EMPTY1_BYTES, 0, EMPTY1_BYTES.length));
+        _assertMissing(MAPPER.reader().readTree(new ByteArrayInputStream(EMPTY1_BYTES)));
+    }
+
+    private void _assertNullTree(TreeNode n) {
+        if (n != null) {
+            fail("Should get `null` for reads with `JsonParser`, instead got: "+n.getClass().getName());
+        }
+    }
+
+    private void _assertMissing(JsonNode n) {
+        assertNotNull("Should not get `null` but `MissingNode`", n);
+        if (!n.isMissingNode()) {
+            fail("Should get `MissingNode` but got: "+n.getClass().getName());
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/JsonNodeFactoryTest.java b/src/test/java/com/fasterxml/jackson/databind/node/JsonNodeFactoryTest.java
index 3a646b4..e01cf18 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/JsonNodeFactoryTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/JsonNodeFactoryTest.java
@@ -33,5 +33,7 @@
         assertTrue(f.numberNode((BigDecimal) null).isNull());
 
         assertTrue(f.numberNode((BigInteger) null).isNull());
+
+        assertTrue(f.missingNode().isMissingNode());
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/NodeTestBase.java b/src/test/java/com/fasterxml/jackson/databind/node/NodeTestBase.java
index c351b79..0da7317 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/NodeTestBase.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/NodeTestBase.java
@@ -25,6 +25,7 @@
         assertEquals((long) expInt, n.asLong(19L));
         assertEquals(expDouble, n.asDouble());
         assertEquals(expDouble, n.asDouble(-19.25));
-    }
 
+        assertTrue(n.isEmpty());
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/ObjectNodeTest.java b/src/test/java/com/fasterxml/jackson/databind/node/ObjectNodeTest.java
index b617d68..260e93e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/ObjectNodeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/ObjectNodeTest.java
@@ -45,6 +45,7 @@
         @JsonInclude(JsonInclude.Include.NON_EMPTY)
         public ObjectNode node;
 
+        protected ObNodeWrapper() { }
         public ObNodeWrapper(ObjectNode n) {
             node = n;
         }
@@ -68,7 +69,7 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = objectMapper();
+    private final ObjectMapper MAPPER = sharedMapper();
 
     public void testSimpleObject() throws Exception
     {
@@ -81,6 +82,7 @@
         assertFalse(root.isArray());
         assertTrue(root.isObject());
         assertEquals(2, root.size());
+        assertFalse(root.isEmpty());
 
         Iterator<JsonNode> it = root.iterator();
         assertNotNull(it);
@@ -127,7 +129,8 @@
     {
         ObjectNode n = new ObjectNode(JsonNodeFactory.instance);
         assertStandardEquals(n);
-
+        assertTrue(n.isEmpty());
+        
         assertFalse(n.elements().hasNext());
         assertFalse(n.fields().hasNext());
         assertFalse(n.fieldNames().hasNext());
@@ -281,9 +284,9 @@
 
     public void testValidWithArray() throws Exception
     {
-        ObjectNode root = MAPPER.createObjectNode();
+        JsonNode root = MAPPER.createObjectNode();
         assertEquals("{}", MAPPER.writeValueAsString(root));
-        JsonNode child = root.withArray("arr");
+        ArrayNode child = root.withArray("arr");
         assertTrue(child instanceof ArrayNode);
         assertEquals("{\"arr\":[]}", MAPPER.writeValueAsString(root));
     }
@@ -328,7 +331,6 @@
         }
     }
 
-    // [Issue#93]
     public void testSetAll() throws Exception
     {
         ObjectNode root = MAPPER.createObjectNode();
@@ -372,20 +374,34 @@
         final String DUP_JSON = "{ \"a\":1, \"a\":2 }";
         
         // first: verify defaults:
-        ObjectMapper mapper = new ObjectMapper();
-        assertFalse(mapper.isEnabled(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY));
-        ObjectNode root = (ObjectNode) mapper.readTree(DUP_JSON);
+        assertFalse(MAPPER.isEnabled(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY));
+        ObjectNode root = (ObjectNode) MAPPER.readTree(DUP_JSON);
         assertEquals(2, root.path("a").asInt());
         
         // and then enable checks:
         try {
-            mapper.reader(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY).readTree(DUP_JSON);
+            MAPPER.reader(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY).readTree(DUP_JSON);
             fail("Should have thrown exception!");
         } catch (JsonMappingException e) {
             verifyException(e, "duplicate field 'a'");
         }
     }
 
+    public void testFailOnDupNestedKeys() throws Exception
+    {
+        final String DOC = aposToQuotes(
+                "{'node' : { 'data' : [ 1, 2, { 'a':3 }, { 'foo' : 1, 'bar' : 2, 'foo': 3}]}}"
+        );
+        try {
+            MAPPER.readerFor(ObNodeWrapper.class)
+                .with(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY)
+                .readValue(DOC);
+            fail("Should have thrown exception!");
+        } catch (JsonMappingException e) {
+            verifyException(e, "duplicate field 'foo'");
+        }
+    }
+
     public void testEqualityWrtOrder() throws Exception
     {
         ObjectNode ob1 = MAPPER.createObjectNode();
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/POJONodeTest.java b/src/test/java/com/fasterxml/jackson/databind/node/POJONodeTest.java
index 638cb43..efff03e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/POJONodeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/POJONodeTest.java
@@ -31,7 +31,7 @@
       }
     }
 
-    final ObjectMapper MAPPER = newObjectMapper();
+    final ObjectMapper MAPPER = newJsonMapper();
 
     public void testPOJONodeCustomSer() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/RequiredAccessorTest.java b/src/test/java/com/fasterxml/jackson/databind/node/RequiredAccessorTest.java
new file mode 100644
index 0000000..22f239a
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/node/RequiredAccessorTest.java
@@ -0,0 +1,102 @@
+package com.fasterxml.jackson.databind.node;
+
+import com.fasterxml.jackson.core.JsonPointer;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class RequiredAccessorTest
+    extends BaseMapTest
+{
+    private final ObjectMapper MAPPER = sharedMapper();
+
+    private final JsonNode TEST_OBJECT, TEST_ARRAY;
+
+    public RequiredAccessorTest() throws Exception {
+        TEST_OBJECT = MAPPER.readTree(aposToQuotes(
+ "{ 'data' : { 'primary' : 15, 'vector' : [ 'yes', false ], 'nullable' : null  },\n"
++"  'array' : [ true,   {\"messsage\":'hello', 'value' : 42, 'misc' : [1, 2] }, null, 0.25 ]\n"
++"}"
+        ));
+        TEST_ARRAY = MAPPER.readTree(aposToQuotes(
+ "[ true, { 'data' : { 'primary' : 15, 'vector' : [ 'yes', false ]  } }, 0.25, 'last' ]"
+        ));
+    }
+
+    public void testIMPORTANT() {
+        _checkRequiredAt(TEST_OBJECT, "/data/weird/and/more", "/weird/and/more");
+    }
+    
+    public void testRequiredAtObjectOk() throws Exception {
+        assertNotNull(TEST_OBJECT.requiredAt("/array"));
+        assertNotNull(TEST_OBJECT.requiredAt("/array/0"));
+        assertTrue(TEST_OBJECT.requiredAt("/array/0").isBoolean());
+        assertNotNull(TEST_OBJECT.requiredAt("/array/1/misc/1"));
+        assertEquals(2, TEST_OBJECT.requiredAt("/array/1/misc/1").intValue());
+    }
+
+    public void testRequiredAtArrayOk() throws Exception {
+        assertTrue(TEST_ARRAY.requiredAt("/0").isBoolean());
+        assertTrue(TEST_ARRAY.requiredAt("/1").isObject());
+        assertNotNull(TEST_ARRAY.requiredAt("/1/data/primary"));
+        assertNotNull(TEST_ARRAY.requiredAt("/1/data/vector/1"));
+    }
+
+    public void testRequiredAtFailOnObject() throws Exception {
+        _checkRequiredAt(TEST_OBJECT, "/0", "/0");
+        _checkRequiredAt(TEST_OBJECT, "/bogus", "/bogus");
+        _checkRequiredAt(TEST_OBJECT, "/data/weird/and/more", "/weird/and/more");
+
+        _checkRequiredAt(TEST_OBJECT, "/data/vector/other/3", "/other/3");
+    }
+
+    public void testRequiredAtFailOnArray() throws Exception {
+        _checkRequiredAt(TEST_ARRAY, "/1/data/vector/25", "/25");
+    }
+
+    private void _checkRequiredAt(JsonNode doc, String fullPath, String mismatchPart) {
+        try {
+            doc.requiredAt(fullPath);
+        } catch (IllegalArgumentException e) {
+            verifyException(e, "No node at '"+fullPath+"' (unmatched part: '"+mismatchPart+"')");
+        }
+    }
+    
+    public void testSimpleRequireOk() throws Exception {
+        // first basic working accessors on node itself
+        assertSame(TEST_OBJECT, TEST_OBJECT.require());
+        assertSame(TEST_OBJECT, TEST_OBJECT.requireNonNull());
+        assertSame(TEST_OBJECT, TEST_OBJECT.requiredAt(""));
+        assertSame(TEST_OBJECT, TEST_OBJECT.requiredAt(JsonPointer.compile("")));
+
+        assertSame(TEST_OBJECT.get("data"), TEST_OBJECT.required("data"));
+        assertSame(TEST_ARRAY.get(0), TEST_ARRAY.required(0));
+        assertSame(TEST_ARRAY.get(3), TEST_ARRAY.required(3));
+
+        // check diff between missing, null nodes
+        TEST_OBJECT.path("data").path("nullable").require();
+
+        try {
+            JsonNode n = TEST_OBJECT.path("data").path("nullable").requireNonNull();
+            fail("Should not pass; got: "+n);
+        } catch (IllegalArgumentException e) {
+            verifyException(e, "requireNonNull() called on `NullNode`");
+        }
+    }
+
+    public void testSimpleRequireFail() throws Exception {
+        try {
+            TEST_OBJECT.required("bogus");
+            fail("Should not pass");
+        } catch (IllegalArgumentException e) {
+            verifyException(e, "No value for property 'bogus'");
+        }
+
+        try {
+            TEST_ARRAY.required("bogus");
+            fail("Should not pass");
+        } catch (IllegalArgumentException e) {
+            verifyException(e, "Node of type `ArrayNode` has no fields");
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestConversions.java b/src/test/java/com/fasterxml/jackson/databind/node/TestConversions.java
index e22082d..f94f052 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestConversions.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestConversions.java
@@ -81,6 +81,32 @@
         public Long longObj;
     }
 
+    // [databind#433]
+    static class CustomSerializedPojo implements JsonSerializable
+    {
+        private final ObjectNode node = JsonNodeFactory.instance.objectNode();
+
+        public void setFoo(final String foo) {
+            node.put("foo", foo);
+        }
+    
+        @Override
+        public void serialize(final JsonGenerator jgen, final SerializerProvider provider) throws IOException
+        {
+            jgen.writeTree(node);
+        }
+
+        @Override
+        public void serializeWithType(JsonGenerator g,
+                SerializerProvider provider, TypeSerializer typeSer) throws IOException
+        {
+            WritableTypeId typeIdDef = new WritableTypeId(this, JsonToken.START_OBJECT);
+            typeSer.writeTypePrefix(g, typeIdDef);
+            serialize(g, provider);
+            typeSer.writeTypePrefix(g, typeIdDef);
+        }    
+    }
+    
     /*
     /**********************************************************
     /* Unit tests
@@ -241,31 +267,6 @@
         assertTrue(tree.has("pi"));
     }
 
-    static class CustomSerializedPojo implements JsonSerializable
-    {
-        private final ObjectNode node = JsonNodeFactory.instance.objectNode();
-
-        public void setFoo(final String foo) {
-            node.put("foo", foo);
-        }
-    
-        @Override
-        public void serialize(final JsonGenerator jgen, final SerializerProvider provider) throws IOException
-        {
-            jgen.writeTree(node);
-        }
-
-        @Override
-        public void serializeWithType(JsonGenerator g,
-                SerializerProvider provider, TypeSerializer typeSer) throws IOException
-        {
-            WritableTypeId typeIdDef = new WritableTypeId(this, JsonToken.START_OBJECT);
-            typeSer.writeTypePrefix(g, typeIdDef);
-            serialize(g, provider);
-            typeSer.writeTypePrefix(g, typeIdDef);
-        }    
-    }
-
     // [databind#433]
     public void testBeanToTree() throws Exception
     {
@@ -314,4 +315,16 @@
         LongContainer1940 obj = MAPPER.treeToValue(tree, LongContainer1940.class);
         assertEquals(Long.valueOf(EXP), obj.longObj);
     }
+
+    public void testConversionsOfNull() throws Exception
+    {
+        // First: `null` value should become `NullNode`
+        JsonNode n = MAPPER.valueToTree(null);
+        assertNotNull(n);
+        assertTrue(n.isNull());
+
+        // and vice versa
+        Object pojo = MAPPER.treeToValue(n, Root.class);
+        assertNull(pojo);
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestEndOfInputHandling.java b/src/test/java/com/fasterxml/jackson/databind/node/TestEndOfInputHandling.java
deleted file mode 100644
index a86baa1..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestEndOfInputHandling.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.fasterxml.jackson.databind.node;
-
-import java.io.IOException;
-
-import com.fasterxml.jackson.core.*;
-
-import com.fasterxml.jackson.databind.*;
-
-public class TestEndOfInputHandling extends BaseMapTest
-{
-  public void testErrorHandling() throws IOException {
-      ObjectMapper mapper = new ObjectMapper();
-
-      String json = "{\"A\":{\"B\":\n";
-      JsonParser parser = mapper.getFactory().createParser(json);
-      parser.setCodec(new ObjectMapper());
-      try {
-          parser.readValueAsTree();
-      } catch(JsonParseException e) {
-          verifyException(e, "Unexpected end-of-input");
-      }
-      parser.close();
-
-      try {
-          mapper.readTree(json);
-      }
-      catch(JsonParseException e) {
-          verifyException(e, "Unexpected end-of-input");
-      }
-  }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestJsonNode.java b/src/test/java/com/fasterxml/jackson/databind/node/TestJsonNode.java
index 0750fef..c26ed90 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestJsonNode.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestJsonNode.java
@@ -5,6 +5,7 @@
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.io.SerializedString;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 import com.fasterxml.jackson.databind.util.RawValue;
 
 /**
@@ -83,8 +84,8 @@
         assertStandardEquals(n);
         assertEquals(n, new POJONode("x"));
         assertEquals("x", n.asText());
-        // not sure if this is what it'll remain as but:
-        assertEquals("x", n.toString());
+        // 10-Dec-2018, tatu: With 2.10, should serialize same as via ObjectMapper/ObjectWriter
+        assertEquals("\"x\"", n.toString());
 
         assertEquals(new POJONode(null), new POJONode(null));
 
@@ -177,7 +178,7 @@
     public void testArrayWithDefaultTyping() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper()
-            .enableDefaultTyping();
+            .activateDefaultTyping(NoCheckSubTypeValidator.instance);
 
         JsonNode array = mapper.readTree("[ 1, 2 ]");
         assertTrue(array.isArray());
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestMissingNode.java b/src/test/java/com/fasterxml/jackson/databind/node/TestMissingNode.java
index 45f0bac..91c1f60 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestMissingNode.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestMissingNode.java
@@ -15,6 +15,9 @@
         assertEquals(JsonToken.NOT_AVAILABLE, n.asToken());
         assertEquals("", n.asText());
         assertStandardEquals(n);
+        // 10-Dec-2018, tatu: With 2.10, should serialize same as via ObjectMapper/ObjectWriter
+        // 10-Dec-2019, tatu: Surprise! No, this is not how it worked in 2.9, nor does it make
+        //    sense... see [databind#2566] for details
         assertEquals("", n.toString());
 
         assertNodeNumbersForNonNumeric(n);
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestNullNode.java b/src/test/java/com/fasterxml/jackson/databind/node/TestNullNode.java
index 99f6eab..d698d7e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestNullNode.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestNullNode.java
@@ -17,6 +17,11 @@
         public void setArray(ArrayNode n) { _array = n; }
     }
 
+    @SuppressWarnings("serial")
+    static class MyNull extends NullNode { }
+    
+    private final ObjectMapper MAPPER = sharedMapper();
+    
     public void testBasicsWithNullNode() throws Exception
     {
         // Let's use something that doesn't add much beyond JsonNode base
@@ -40,6 +45,7 @@
         assertEquals(BigInteger.ZERO, n.bigIntegerValue());
 
         assertEquals(0, n.size());
+        assertTrue(n.isEmpty());
         assertFalse(n.elements().hasNext());
         assertFalse(n.fieldNames().hasNext());
         // path is never null; but does point to missing node
@@ -58,7 +64,7 @@
     public void testNullHandling() throws Exception
     {
         // First, a stand-alone null
-        JsonNode n = objectReader().readTree("null");
+        JsonNode n = MAPPER.readTree("null");
         assertNotNull(n);
         assertTrue(n.isNull());
         assertFalse(n.isNumber());
@@ -80,16 +86,15 @@
 
     public void testNullSerialization() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
         StringWriter sw = new StringWriter();
-        mapper.writeValue(sw, NullNode.instance);
+        MAPPER.writeValue(sw, NullNode.instance);
         assertEquals("null", sw.toString());
     }
 
     public void testNullHandlingCovariance() throws Exception
     {
         String JSON = "{\"object\" : null, \"array\" : null }";
-        CovarianceBean bean = objectMapper().readValue(JSON, CovarianceBean.class);
+        CovarianceBean bean = MAPPER.readValue(JSON, CovarianceBean.class);
 
         ObjectNode on = bean._object;
         assertNull(on);
@@ -97,4 +102,16 @@
         ArrayNode an = bean._array;
         assertNull(an);
     }
+
+    @SuppressWarnings("unlikely-arg-type")
+    public void testNullEquality() throws Exception
+    {
+        JsonNode n = MAPPER.nullNode();
+        assertTrue(n.isNull());
+        assertEquals(n, new MyNull());
+        assertEquals(new MyNull(), n);
+
+        assertFalse(n.equals(null));
+        assertFalse(n.equals("foo"));
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestTreeMapperSerializer.java b/src/test/java/com/fasterxml/jackson/databind/node/TestTreeMapperSerializer.java
deleted file mode 100644
index 10f77a8..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestTreeMapperSerializer.java
+++ /dev/null
@@ -1,213 +0,0 @@
-package com.fasterxml.jackson.databind.node;
-
-import static org.junit.Assert.*;
-
-import java.io.*;
-
-import com.fasterxml.jackson.core.*;
-import com.fasterxml.jackson.databind.*;
-
-/**
- * This unit test suite tries to verify that the trees ObjectMapper
- * constructs can be serialized properly.
- */
-public class TestTreeMapperSerializer extends NodeTestBase
-{
-    final static String FIELD1 = "first";
-    final static String FIELD2 = "Second?";
-    final static String FIELD3 = "foo'n \"bar\"";
-    final static String FIELD4 = "4";
-
-    final static String TEXT1 = "Some text & \"stuff\"";
-    final static String TEXT2 = "Some more text:\twith\nlinefeeds and all!";
-
-    final static double DOUBLE_VALUE = 9.25;
-
-    public void testFromArray() throws Exception
-    {
-        ObjectMapper mapper = new ObjectMapper();
-        ArrayNode root = mapper.createArrayNode();
-        root.add(TEXT1);
-        root.add(3);
-        ObjectNode obj = root.addObject();
-        obj.put(FIELD1, true);
-        obj.putArray(FIELD2);
-        root.add(false);
-
-        /* Ok, ready... let's serialize using one of two alternate
-         * methods: first preferred (using generator)
-         * (there are 2 variants here too)
-         */
-        for (int i = 0; i < 2; ++i) {
-            StringWriter sw = new StringWriter();
-            if (i == 0) {
-                JsonGenerator gen = new JsonFactory().createGenerator(sw);
-                root.serialize(gen, null);
-                gen.close();
-            } else {
-                mapper.writeValue(sw, root);
-            }
-            verifyFromArray(sw.toString());
-        }
-            
-        // And then convenient but less efficient alternative:
-        verifyFromArray(root.toString());
-    }
-
-    public void testFromMap()
-        throws Exception
-    {
-        ObjectMapper mapper = new ObjectMapper();
-        ObjectNode root = mapper.createObjectNode();
-        root.put(FIELD4, TEXT2);
-        root.put(FIELD3, -1);
-        root.putArray(FIELD2);
-        root.put(FIELD1, DOUBLE_VALUE);
-
-        /* Let's serialize using one of two alternate methods:
-         * first preferred (using generator)
-         * (there are 2 variants here too)
-         */
-        for (int i = 0; i < 2; ++i) {
-            StringWriter sw = new StringWriter();
-            if (i == 0) {
-                JsonGenerator gen = new JsonFactory().createGenerator(sw);
-                root.serialize(gen, null);
-                gen.close();
-            } else {
-                mapper.writeValue(sw, root);
-            }
-            verifyFromMap(sw.toString());
-        }
-
-        // And then convenient but less efficient alternative:
-        verifyFromMap(root.toString());
-    }
-
-    /**
-     * Unit test to check for regression of [JACKSON-18].
-     */
-    public void testSmallNumbers()
-        throws Exception
-    {
-        ObjectMapper mapper = new ObjectMapper();
-        ArrayNode root = mapper.createArrayNode();
-        for (int i = -20; i <= 20; ++i) {
-            JsonNode n = root.numberNode(i);
-            root.add(n);
-            // Hmmh. Not sure why toString() won't be triggered otherwise...
-            assertEquals(String.valueOf(i), n.toString());
-        }
-
-        // Loop over 2 different serialization methods
-        for (int type = 0; type < 2; ++type) {
-            StringWriter sw = new StringWriter();
-            if (type == 0) {
-                JsonGenerator gen = new JsonFactory().createGenerator(sw);
-                root.serialize(gen, null);
-                gen.close();
-            } else {
-                mapper.writeValue(sw, root);
-            }
-            
-            String doc = sw.toString();
-            JsonParser p = new JsonFactory().createParser(new StringReader(doc));
-            
-            assertEquals(JsonToken.START_ARRAY, p.nextToken());
-            for (int i = -20; i <= 20; ++i) {
-                assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken());
-                assertEquals(i, p.getIntValue());
-                assertEquals(""+i, p.getText());
-            }
-            assertEquals(JsonToken.END_ARRAY, p.nextToken());
-            p.close();
-        }
-    }
-
-    public void testBinary() throws Exception
-    {
-        ObjectMapper mapper = new ObjectMapper();
-        final int LENGTH = 13045;
-        byte[] data = new byte[LENGTH];
-        for (int i = 0; i < LENGTH; ++i) {
-            data[i] = (byte) i;
-        }
-        StringWriter sw = new StringWriter();
-        mapper.writeValue(sw, BinaryNode.valueOf(data));
-
-        JsonParser p = new JsonFactory().createParser(sw.toString());
-        // note: can't determine it's binary from json alone:
-        assertToken(JsonToken.VALUE_STRING, p.nextToken());
-        assertArrayEquals(data, p.getBinaryValue());
-        p.close();
-    }
-
-    /*
-    ///////////////////////////////////////////////////////////////
-    // Internal methods
-    ///////////////////////////////////////////////////////////////
-     */
-
-    private void verifyFromArray(String input)
-        throws Exception
-    {
-        JsonParser p = new JsonFactory().createParser(new StringReader(input));
-        
-        assertEquals(JsonToken.START_ARRAY, p.nextToken());
-        
-        assertEquals(JsonToken.VALUE_STRING, p.nextToken());
-        assertEquals(TEXT1, getAndVerifyText(p));
-        
-        assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken());
-        assertEquals(3, p.getIntValue());
-        
-        assertEquals(JsonToken.START_OBJECT, p.nextToken());
-        assertEquals(JsonToken.FIELD_NAME, p.nextToken());
-        assertEquals(FIELD1, getAndVerifyText(p));
-        
-        assertEquals(JsonToken.VALUE_TRUE, p.nextToken());
-        assertEquals(JsonToken.FIELD_NAME, p.nextToken());
-        assertEquals(FIELD2, getAndVerifyText(p));
-        
-        assertEquals(JsonToken.START_ARRAY, p.nextToken());
-        assertEquals(JsonToken.END_ARRAY, p.nextToken());
-        assertEquals(JsonToken.END_OBJECT, p.nextToken());
-        
-        assertEquals(JsonToken.VALUE_FALSE, p.nextToken());
-        
-        assertEquals(JsonToken.END_ARRAY, p.nextToken());
-        assertNull(p.nextToken());
-        p.close();
-    }
-
-    private void verifyFromMap(String input)
-        throws Exception
-    {
-        JsonParser p = new JsonFactory().createParser(input);
-        assertEquals(JsonToken.START_OBJECT, p.nextToken());
-        assertEquals(JsonToken.FIELD_NAME, p.nextToken());
-        assertEquals(FIELD4, getAndVerifyText(p));
-        assertEquals(JsonToken.VALUE_STRING, p.nextToken());
-        assertEquals(TEXT2, getAndVerifyText(p));
-        
-        assertEquals(JsonToken.FIELD_NAME, p.nextToken());
-        assertEquals(FIELD3, getAndVerifyText(p));
-        assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken());
-        assertEquals(-1, p.getIntValue());
-        
-        assertEquals(JsonToken.FIELD_NAME, p.nextToken());
-        assertEquals(FIELD2, getAndVerifyText(p));
-        assertEquals(JsonToken.START_ARRAY, p.nextToken());
-        assertEquals(JsonToken.END_ARRAY, p.nextToken());
-        
-        assertEquals(JsonToken.FIELD_NAME, p.nextToken());
-        assertEquals(FIELD1, getAndVerifyText(p));
-        assertEquals(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
-        assertEquals(DOUBLE_VALUE, p.getDoubleValue(), 0);
-        
-        assertEquals(JsonToken.END_OBJECT, p.nextToken());
-        
-        assertNull(p.nextToken());
-        p.close();
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestTreeTraversingParser.java b/src/test/java/com/fasterxml/jackson/databind/node/TestTreeTraversingParser.java
index 0573696..722bfe4 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestTreeTraversingParser.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestTreeTraversingParser.java
@@ -1,5 +1,7 @@
 package com.fasterxml.jackson.databind.node;
 
+import java.io.IOException;
+import java.math.BigInteger;
 import java.util.*;
 
 import static org.junit.Assert.*;
@@ -7,12 +9,10 @@
 import com.fasterxml.jackson.annotation.*;
 
 import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.core.JsonParser.NumberType;
+import com.fasterxml.jackson.core.exc.InputCoercionException;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.exc.InvalidFormatException;
-import com.fasterxml.jackson.databind.node.BinaryNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.fasterxml.jackson.databind.node.POJONode;
-import com.fasterxml.jackson.databind.node.TextNode;
 
 public class TestTreeTraversingParser
     extends BaseMapTest
@@ -37,14 +37,15 @@
     /* Test methods
     /**********************************************************
      */
-    
+
+    private final ObjectMapper MAPPER = newJsonMapper();
+
     public void testSimple() throws Exception
     {
         // For convenience, parse tree from JSON first
         final String JSON =
             "{ \"a\" : 123, \"list\" : [ 12.25, null, true, { }, [ ] ] }";
-        ObjectMapper m = new ObjectMapper();
-        JsonNode tree = m.readTree(JSON);
+        JsonNode tree = MAPPER.readTree(JSON);
         JsonParser p = tree.traverse();
 
         assertNull(p.getCurrentToken());
@@ -109,21 +110,19 @@
     public void testArray() throws Exception
     {
         // For convenience, parse tree from JSON first
-        ObjectMapper m = new ObjectMapper();
-
-        JsonParser p = m.readTree("[]").traverse();
+        JsonParser p = MAPPER.readTree("[]").traverse();
         assertToken(JsonToken.START_ARRAY, p.nextToken());
         assertToken(JsonToken.END_ARRAY, p.nextToken());
         p.close();
 
-        p = m.readTree("[[]]").traverse();
+        p = MAPPER.readTree("[[]]").traverse();
         assertToken(JsonToken.START_ARRAY, p.nextToken());
         assertToken(JsonToken.START_ARRAY, p.nextToken());
         assertToken(JsonToken.END_ARRAY, p.nextToken());
         assertToken(JsonToken.END_ARRAY, p.nextToken());
         p.close();
 
-        p = m.readTree("[[ 12.1 ]]").traverse();
+        p = MAPPER.readTree("[[ 12.1 ]]").traverse();
         assertToken(JsonToken.START_ARRAY, p.nextToken());
         assertToken(JsonToken.START_ARRAY, p.nextToken());
         assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
@@ -138,8 +137,7 @@
         final String JSON =
             "{\"coordinates\":[[[-3,\n1],[179.859681,51.175092]]]}"
             ;
-        ObjectMapper m = new ObjectMapper();
-        JsonNode tree = m.readTree(JSON);
+        JsonNode tree = MAPPER.readTree(JSON);
         JsonParser p = tree.traverse();
         assertToken(JsonToken.START_OBJECT, p.nextToken());
         assertToken(JsonToken.FIELD_NAME, p.nextToken());
@@ -170,8 +168,7 @@
      */
     public void testSpecDoc() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        JsonNode tree = m.readTree(SAMPLE_DOC_JSON_SPEC);
+        JsonNode tree = MAPPER.readTree(SAMPLE_DOC_JSON_SPEC);
         JsonParser p = tree.traverse();
         verifyJsonSpecSampleDoc(p, true);
         p.close();
@@ -245,13 +242,12 @@
      */
     public void testDataBind() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        JsonNode tree = m.readTree
+        JsonNode tree = MAPPER.readTree
             ("{ \"name\" : \"Tatu\", \n"
              +"\"magicNumber\" : 42,"
              +"\"kids\" : [ \"Leo\", \"Lila\", \"Leia\" ] \n"
              +"}");
-        Person tatu = m.treeToValue(tree, Person.class);
+        Person tatu = MAPPER.treeToValue(tree, Person.class);
         assertNotNull(tatu);
         assertEquals(42, tatu.magicNumber);
         assertEquals("Tatu", tatu.name);
@@ -262,16 +258,111 @@
         assertEquals("Leia", tatu.kids.get(2));
     }
 
-    // [JACKSON-370]
     public void testSkipChildrenWrt370() throws Exception
     {
-        ObjectMapper o = new ObjectMapper();
-        ObjectNode n = o.createObjectNode();
+        ObjectNode n = MAPPER.createObjectNode();
         n.putObject("inner").put("value", "test");
         n.putObject("unknown").putNull("inner");
-        Jackson370Bean obj = o.readValue(n.traverse(), Jackson370Bean.class);
+        Jackson370Bean obj = MAPPER.readValue(n.traverse(), Jackson370Bean.class);
         assertNotNull(obj.inner);
         assertEquals("test", obj.inner.value);        
     }
-}
 
+    // // // Numeric coercion checks, [databind#2189]
+
+    public void testNumberOverflowInt() throws IOException
+    {
+        final long tooBig = 1L + Integer.MAX_VALUE;
+        try (final JsonParser p = MAPPER.readTree("[ "+tooBig+" ]").traverse()) {
+            assertToken(JsonToken.START_ARRAY, p.nextToken());
+            assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
+            assertEquals(NumberType.LONG, p.getNumberType());
+            try {
+                p.getIntValue();
+                fail("Expected failure for `int` overflow");
+            } catch (InputCoercionException e) {
+                verifyException(e, "Numeric value ("+tooBig+") out of range of int");
+            }
+        }
+        try (final JsonParser p = MAPPER.readTree("{ \"value\" : "+tooBig+" }").traverse()) {
+            assertToken(JsonToken.START_OBJECT, p.nextToken());
+            assertToken(JsonToken.FIELD_NAME, p.nextToken());
+            assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
+            assertEquals(NumberType.LONG, p.getNumberType());
+            try {
+                p.getIntValue();
+                fail("Expected failure for `int` overflow");
+            } catch (InputCoercionException e) {
+                verifyException(e, "Numeric value ("+tooBig+") out of range of int");
+            }
+        }
+        // But also from floating-point
+        final String tooBig2 = "1.0e10";
+        try (final JsonParser p = MAPPER.readTree("[ "+tooBig2+" ]").traverse()) {
+            assertToken(JsonToken.START_ARRAY, p.nextToken());
+            assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
+            assertEquals(NumberType.DOUBLE, p.getNumberType());
+            try {
+                p.getIntValue();
+                fail("Expected failure for `int` overflow");
+            } catch (InputCoercionException e) {
+                verifyException(e, "Numeric value ("+tooBig2+") out of range of int");
+            }
+        }
+    }
+
+    public void testNumberOverflowLong() throws IOException
+    {
+        final BigInteger tooBig = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE);
+        try (final JsonParser p = MAPPER.readTree("[ "+tooBig+" ]").traverse()) {
+            assertToken(JsonToken.START_ARRAY, p.nextToken());
+            assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
+            assertEquals(NumberType.BIG_INTEGER, p.getNumberType());
+            try {
+                p.getLongValue();
+                fail("Expected failure for `long` overflow");
+            } catch (InputCoercionException e) {
+                verifyException(e, "Numeric value ("+tooBig+") out of range of long");
+            }
+        }
+        try (final JsonParser p = MAPPER.readTree("{ \"value\" : "+tooBig+" }").traverse()) {
+            assertToken(JsonToken.START_OBJECT, p.nextToken());
+            assertToken(JsonToken.FIELD_NAME, p.nextToken());
+            assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
+            assertEquals(NumberType.BIG_INTEGER, p.getNumberType());
+            try {
+                p.getLongValue();
+                fail("Expected failure for `long` overflow");
+            } catch (InputCoercionException e) {
+                verifyException(e, "Numeric value ("+tooBig+") out of range of long");
+            }
+        }
+        // But also from floating-point
+        final String tooBig2 = "1.0e30";
+        try (final JsonParser p = MAPPER.readTree("[ "+tooBig2+" ]").traverse()) {
+            assertToken(JsonToken.START_ARRAY, p.nextToken());
+            assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
+            assertEquals(NumberType.DOUBLE, p.getNumberType());
+            try {
+                p.getLongValue();
+                fail("Expected failure for `long` overflow");
+            } catch (InputCoercionException e) {
+                verifyException(e, "Numeric value ("+tooBig2+") out of range of long");
+            }
+        }
+
+        // Plus, wrt [databind#2393], NON-failing cases
+        final long[] okValues = new long[] { 1L+Integer.MAX_VALUE, -1L + Integer.MIN_VALUE,
+                Long.MAX_VALUE, Long.MIN_VALUE };
+        for (long okValue : okValues) {
+            try (final JsonParser p = MAPPER.readTree("{ \"value\" : "+okValue+" }").traverse()) {
+                assertToken(JsonToken.START_OBJECT, p.nextToken());
+                assertToken(JsonToken.FIELD_NAME, p.nextToken());
+                assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
+                assertEquals(NumberType.LONG, p.getNumberType());
+                assertEquals(okValue, p.getLongValue());
+                assertToken(JsonToken.END_OBJECT, p.nextToken());
+            }
+        }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TestTreeWithType.java b/src/test/java/com/fasterxml/jackson/databind/node/TestTreeWithType.java
index 8395627..2e364f6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TestTreeWithType.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TestTreeWithType.java
@@ -7,6 +7,7 @@
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
 import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class TestTreeWithType extends BaseMapTest
 {
@@ -68,8 +69,10 @@
     }
 
     public void testValueAsStringWithDefaultTyping() throws Exception {
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+        final ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY)
+                .build();
 
         Foo foo = new Foo("baz");
         String json = mapper.writeValueAsString(foo);
@@ -82,9 +85,11 @@
     {
         final String CLASS = Foo.class.getName();
 
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL,
-                JsonTypeInfo.As.PROPERTY);
+        final ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL,
+                        JsonTypeInfo.As.PROPERTY)
+                .build();
         String json = "{\"@class\":\""+CLASS+"\",\"bar\":\"baz\"}";
         JsonNode jsonNode = mapper.readTree(json);
         assertEquals(jsonNode.get("bar").textValue(), "baz");
@@ -98,8 +103,10 @@
     }
 
     public void testValueToTreeWithDefaultTyping() throws Exception {
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
+        final ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY)
+                .build();
 
         Foo foo = new Foo("baz");
         JsonNode jsonNode = mapper.valueToTree(foo);
@@ -108,9 +115,10 @@
 
     public void testIssue353() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-
-        mapper.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.NON_FINAL, "@class");
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTypingAsProperty(NoCheckSubTypeValidator.instance,
+                ObjectMapper.DefaultTyping.NON_FINAL, "@class")
+                .build();
 
          SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null, "TEST", "TEST"));
          testModule.addDeserializer(SavedCookie.class, new SavedCookieDeserializer());
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TextNodeTest.java b/src/test/java/com/fasterxml/jackson/databind/node/TextNodeTest.java
index ad04c8a..37e7b5a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TextNodeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TextNodeTest.java
@@ -9,6 +9,9 @@
         assertStandardEquals(empty);
         assertSame(TextNode.EMPTY_STRING_NODE, empty);
 
+        assertEquals(0, empty.size());
+        assertTrue(empty.isEmpty());
+
         assertNodeNumbers(TextNode.valueOf("-3"), -3, -3.0);
         assertNodeNumbers(TextNode.valueOf("17.75"), 17, 17.75);
     
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/ToStringForNodesTest.java b/src/test/java/com/fasterxml/jackson/databind/node/ToStringForNodesTest.java
new file mode 100644
index 0000000..28513cc
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/node/ToStringForNodesTest.java
@@ -0,0 +1,39 @@
+package com.fasterxml.jackson.databind.node;
+
+import com.fasterxml.jackson.databind.*;
+
+public class ToStringForNodesTest extends BaseMapTest
+{
+    private final ObjectMapper MAPPER = objectMapper();
+
+    public void testObjectNode() throws Exception
+    {
+        _verifyToStrings(MAPPER.readTree("{ \"key\" : 1, \"b\" : \"x\", \"array\" : [ 1, false ] }"));
+        final ObjectNode n = MAPPER.createObjectNode().put("msg", "hello world");
+        assertEquals(MAPPER.writeValueAsString(n), n.toString());
+        final String expPretty = MAPPER.writer().withDefaultPrettyPrinter()
+                .writeValueAsString(n);
+        assertEquals(expPretty, n.toPrettyString());
+    }
+
+    public void testArrayNode() throws Exception
+    {
+        _verifyToStrings(MAPPER.readTree("[ 1, true, null, [ \"abc\",3], { } ]"));
+        final ArrayNode n = MAPPER.createArrayNode().add(0.25).add(true);
+        assertEquals("[0.25,true]", n.toString());
+        assertEquals("[ 0.25, true ]", n.toPrettyString());
+    }
+
+    public void testBinaryNode() throws Exception
+    {
+        _verifyToStrings(MAPPER.getNodeFactory().binaryNode(new byte[] { 1, 2, 3, 4, 6 }));
+    }
+    
+    protected void _verifyToStrings(JsonNode node) throws Exception
+    {
+        assertEquals(MAPPER.writeValueAsString(node), node.toString());
+
+        assertEquals(MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(node),
+                node.toPrettyString());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TreeFromIncompleteJsonTest.java b/src/test/java/com/fasterxml/jackson/databind/node/TreeFromIncompleteJsonTest.java
new file mode 100644
index 0000000..bb2a6db
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TreeFromIncompleteJsonTest.java
@@ -0,0 +1,36 @@
+package com.fasterxml.jackson.databind.node;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.core.io.JsonEOFException;
+import com.fasterxml.jackson.databind.*;
+
+public class TreeFromIncompleteJsonTest extends BaseMapTest
+{
+    final private ObjectMapper MAPPER = objectMapper(); // shared is fine
+
+    public void testErrorHandling() throws IOException {
+
+      String json = "{\"A\":{\"B\":\n";
+      JsonParser parser = MAPPER.getFactory().createParser(json);
+      try {
+          parser.readValueAsTree();
+      } catch (JsonEOFException e) {
+          verifyException(e, "Unexpected end-of-input");
+      }
+      parser.close();
+
+      try {
+          MAPPER.readTree(json);
+      } catch (JsonEOFException e) {
+          verifyException(e, "Unexpected end-of-input");
+      }
+
+      try {
+          MAPPER.reader().readTree(json);
+      } catch (JsonEOFException e) {
+          verifyException(e, "Unexpected end-of-input");
+      }
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/TreeReadViaMapperTest.java b/src/test/java/com/fasterxml/jackson/databind/node/TreeReadViaMapperTest.java
index dbeed46..c27f9db 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/TreeReadViaMapperTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/TreeReadViaMapperTest.java
@@ -14,6 +14,8 @@
  */
 public class TreeReadViaMapperTest extends BaseMapTest
 {
+    private final ObjectMapper MAPPER = objectMapper();
+
     public void testSimple() throws Exception
     {
         final String JSON = SAMPLE_DOC_JSON_SPEC;
@@ -22,9 +24,9 @@
             JsonNode result;
 
             if (type == 0) {
-                result = objectMapper().readTree(new StringReader(JSON));
+                result = MAPPER.readTree(new StringReader(JSON));
             } else {
-                result = objectMapper().readTree(JSON);
+                result = MAPPER.readTree(JSON);
             }
 
             assertType(result, ObjectNode.class);
@@ -90,9 +92,8 @@
 
     public void testMixed() throws IOException
     {
-        ObjectMapper om = new ObjectMapper();
         String JSON = "{\"node\" : { \"a\" : 3 }, \"x\" : 9 }";
-        Bean bean = om.readValue(JSON, Bean.class);
+        Bean bean = MAPPER.readValue(JSON, Bean.class);
 
         assertEquals(9, bean._x);
         JsonNode n = bean._node;
@@ -115,15 +116,26 @@
             ;
         JsonFactory jf = new JsonFactory();
         JsonParser p = jf.createParser(new StringReader(JSON));
-        JsonNode result = objectMapper().readTree(p);
+        JsonNode result = MAPPER.readTree(p);
 
         assertTrue(result.isObject());
         assertEquals(4, result.size());
 
-        assertNull(objectMapper().readTree(p));
+        assertNull(MAPPER.readTree(p));
         p.close();
     }
 
+    public void testNullViaParser() throws Exception
+    {
+        final String JSON = " null ";
+        JsonFactory jf = new JsonFactory();
+
+        try (JsonParser p = jf.createParser(new StringReader(JSON))) {
+            final JsonNode result = MAPPER.readTree(p);
+            assertTrue(result.isNull());
+        }
+    }
+
     public void testMultiple() throws Exception
     {
         String JSON = "12  \"string\" [ 1, 2, 3 ]";
@@ -151,28 +163,6 @@
         p.close();
     }
 
-    // [databind#1406]
-    public void testNullFromEOFViaMapper() throws Exception
-    {
-        final ObjectMapper mapper = objectMapper();
-
-        assertNull(mapper.readTree(new StringReader("")));
-        assertNull(mapper.readTree(new ByteArrayInputStream(new byte[0])));
-    }
-
-    // [databind#1406]
-    public void testNullFromEOFViaObjectReader() throws Exception
-    {
-        final ObjectMapper mapper = objectMapper();
-
-        assertNull(mapper.readTree(new StringReader("")));
-        assertNull(mapper.readTree(new ByteArrayInputStream(new byte[0])));
-        assertNull(mapper.readerFor(JsonNode.class)
-                .readTree(new StringReader("")));
-        assertNull(mapper.readerFor(JsonNode.class)
-                .readTree(new ByteArrayInputStream(new byte[0])));
-    }
-
     /*
     /**********************************************
     /* Helper methods
diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825BTest.java b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825BTest.java
index 8c36f27..af173ee 100644
--- a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825BTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825BTest.java
@@ -4,6 +4,7 @@
 
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 @SuppressWarnings("serial")
 public class ObjectId825BTest extends BaseMapTest
@@ -133,13 +134,15 @@
 
     static class V extends AbstractData {
         private static final long serialVersionUID = 1L;
-    }    
+    }
 
     public void testFull825() throws Exception
     {
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE);
-        mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
+        final ObjectMapper mapper = jsonMapperBuilder()
+                .enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE)
+                .build();
 
         String INPUT = aposToQuotes(
 "{\n"+
diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825Test.java b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825Test.java
index 86f4eb9..343cc42 100644
--- a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825Test.java
@@ -3,6 +3,7 @@
 import com.fasterxml.jackson.annotation.*;
 
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class ObjectId825Test extends BaseMapTest
 {
@@ -24,11 +25,11 @@
 
     static class TestD extends AbstractEntity { }
 
-    private final ObjectMapper DEF_TYPING_MAPPER = new ObjectMapper();
-    {
-        DEF_TYPING_MAPPER.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
-    }
-    
+    private final ObjectMapper DEF_TYPING_MAPPER = jsonMapperBuilder()
+            .activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                    ObjectMapper.DefaultTyping.NON_FINAL)
+            .build();
+
     public void testDeserialize() throws Exception {
         TestA a = new TestA();
         a.oidString = "oidA";
diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectIdReordering1388Test.java b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectIdReordering1388Test.java
index 3555aeb..9802323 100644
--- a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectIdReordering1388Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectIdReordering1388Test.java
@@ -48,7 +48,7 @@
         final UUID id = UUID.fromString("a59aa02c-fe3c-43f8-9b5a-5fe01878a818");
         final NamedThing thing = new NamedThing(id, "Hello");
 
-        final TypeReference<?> namedThingListType = new TypeReference<List<NamedThing>>() { };
+        final TypeReference<List<NamedThing>> namedThingListType = new TypeReference<List<NamedThing>>() { };
 
         {
             final String jsog = mapper.writeValueAsString(Arrays.asList(thing, thing, thing));
diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectWithCreator1261Test.java b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectWithCreator1261Test.java
index e673d73..ceff2f3 100644
--- a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectWithCreator1261Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectWithCreator1261Test.java
@@ -65,9 +65,10 @@
 
     public void testObjectIds1261() throws Exception
     {
-         ObjectMapper mapper = new ObjectMapper();
-         mapper.enable(SerializationFeature.INDENT_OUTPUT);
-         mapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
+         ObjectMapper mapper = jsonMapperBuilder()
+                 .enable(SerializationFeature.INDENT_OUTPUT)
+             .enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
+             .build();
 
          Answer initialAnswer = createInitialAnswer();
          String initialAnswerString = mapper.writeValueAsString(initialAnswer);
diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/TestAbstractWithObjectId.java b/src/test/java/com/fasterxml/jackson/databind/objectid/TestAbstractWithObjectId.java
index b2267fb..f967992 100644
--- a/src/test/java/com/fasterxml/jackson/databind/objectid/TestAbstractWithObjectId.java
+++ b/src/test/java/com/fasterxml/jackson/databind/objectid/TestAbstractWithObjectId.java
@@ -4,6 +4,8 @@
 
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 import java.util.*;
 
@@ -52,8 +54,10 @@
         myList.add(two);
 
         // make an object mapper that will add class info in so deserialisation works
-        ObjectMapper om = new ObjectMapper();
-        om.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.NON_FINAL, "@class");
+        ObjectMapper om = JsonMapper.builder()
+                .activateDefaultTypingAsProperty(NoCheckSubTypeValidator.instance,
+                        ObjectMapper.DefaultTyping.NON_FINAL, "@class")
+                .build();
 
         // write and print the JSON
         String json = om.writerWithDefaultPrettyPrinter().writeValueAsString(myList);
diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/TestObjectIdWithPolymorphic.java b/src/test/java/com/fasterxml/jackson/databind/objectid/TestObjectIdWithPolymorphic.java
index 486abf3..39e7036 100644
--- a/src/test/java/com/fasterxml/jackson/databind/objectid/TestObjectIdWithPolymorphic.java
+++ b/src/test/java/com/fasterxml/jackson/databind/objectid/TestObjectIdWithPolymorphic.java
@@ -8,6 +8,7 @@
 
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class TestObjectIdWithPolymorphic extends BaseMapTest
 {
@@ -134,7 +135,8 @@
         ObjectMapper om = new ObjectMapper();
         om.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX);
         om.enable(SerializationFeature.INDENT_OUTPUT);
-        om.enableDefaultTypingAsProperty(DefaultTyping.NON_FINAL, "@class");
+        om.activateDefaultTypingAsProperty(NoCheckSubTypeValidator.instance,
+                DefaultTyping.NON_FINAL, "@class");
     
         Process p = new Process();
         Scope s = new Scope(p, null);
diff --git a/src/test/java/com/fasterxml/jackson/databind/seq/PolyMapWriter827Test.java b/src/test/java/com/fasterxml/jackson/databind/seq/PolyMapWriter827Test.java
index 574a08c..9e5b577 100644
--- a/src/test/java/com/fasterxml/jackson/databind/seq/PolyMapWriter827Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/seq/PolyMapWriter827Test.java
@@ -11,6 +11,7 @@
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 // for [databind#827]
 public class PolyMapWriter827Test extends BaseMapTest
@@ -33,7 +34,8 @@
     public void testPolyCustomKeySerializer() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        mapper.activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                ObjectMapper.DefaultTyping.NON_FINAL);
 
         mapper.registerModule(new SimpleModule("keySerializerModule")
             .addKeySerializer(CustomKey.class, new CustomKeySerializer()));
diff --git a/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java b/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java
index 9f3634e..a9c3f89 100644
--- a/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/seq/ReadValuesTest.java
@@ -332,4 +332,14 @@
         assertFalse(it.hasNext());
         p.close();
     }
+
+    public void testEmptyIterator() throws Exception
+    {
+        MappingIterator<Object> empty = MappingIterator.emptyIterator();
+
+        assertFalse(empty.hasNext());
+        assertFalse(empty.hasNextValue());
+
+        empty.close();
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/EnumAsMapKeyTest.java b/src/test/java/com/fasterxml/jackson/databind/ser/EnumAsMapKeyTest.java
new file mode 100644
index 0000000..3996c45
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/EnumAsMapKeyTest.java
@@ -0,0 +1,178 @@
+package com.fasterxml.jackson.databind.ser;
+
+import java.io.IOException;
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+public class EnumAsMapKeyTest extends BaseMapTest
+{
+    static class MapBean {
+        public Map<ABCEnum,Integer> map = new HashMap<>();
+        
+        public void add(ABCEnum key, int value) {
+            map.put(key, Integer.valueOf(value));
+        }
+    }
+
+    protected enum ABCEnum {
+        A, B, C;
+        private ABCEnum() { }
+
+        @Override public String toString() { return name().toLowerCase(); }
+    }
+
+    // [databind#594]
+    static enum MyEnum594 {
+        VALUE_WITH_A_REALLY_LONG_NAME_HERE("longValue");
+
+        private final String key;
+        private MyEnum594(String k) { key = k; }
+
+        @JsonValue
+        public String getKey() { return key; }
+    }
+
+    static class MyStuff594 {
+        public Map<MyEnum594,String> stuff = new EnumMap<MyEnum594,String>(MyEnum594.class);
+        
+        public MyStuff594(String value) {
+            stuff.put(MyEnum594.VALUE_WITH_A_REALLY_LONG_NAME_HERE, value);
+        }
+    }
+
+    // [databind#661]
+    static class MyBean661 {
+        private Map<Foo661, String> foo = new EnumMap<Foo661, String>(Foo661.class);
+
+        public MyBean661(String value) {
+            foo.put(Foo661.FOO, value);
+        }
+
+        @JsonAnyGetter
+        @JsonSerialize(keyUsing = Foo661.Serializer.class)
+        public Map<Foo661, String> getFoo() {
+            return foo;
+        }
+    }
+
+    enum Foo661 {
+        FOO;
+        public static class Serializer extends JsonSerializer<Foo661> {
+            @Override
+            public void serialize(Foo661 value, JsonGenerator jgen, SerializerProvider provider) 
+                    throws IOException {
+                jgen.writeFieldName("X-"+value.name());
+            }
+        }
+    }
+    
+    // [databind#2129]
+    public enum Type {
+        FIRST,
+        SECOND;
+    }
+
+    static class TypeContainer {
+        public Map<Type, Integer> values;
+
+        public TypeContainer(Type type, int value) {
+            values = Collections.singletonMap(type, value);
+        }
+    }
+
+    /*
+    /**********************************************************************
+    /* Test methods
+    /**********************************************************************
+     */
+    
+    private final ObjectMapper MAPPER = newJsonMapper();
+
+    public void testMapWithEnumKeys() throws Exception
+    {
+        MapBean bean = new MapBean();
+        bean.add(ABCEnum.B, 3);
+
+        // By default Enums serialized using `name()`
+        String json = MAPPER.writeValueAsString(bean);
+        assertEquals("{\"map\":{\"B\":3}}", json);
+
+        // but can change
+        json = MAPPER.writer()
+                .with(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
+                .writeValueAsString(bean);
+        assertEquals("{\"map\":{\"b\":3}}", json);
+
+        // [databind#1570]
+
+        // 14-Sep-2019, tatu: as per [databind#2129], must NOT use this feature but
+        //    instead new `WRITE_ENUM_KEYS_USING_INDEX` added in 2.10
+        json = MAPPER.writer()
+                .with(SerializationFeature.WRITE_ENUMS_USING_INDEX)
+                .writeValueAsString(bean);
+//        assertEquals(aposToQuotes("{'map':{'"+TestEnum.B.ordinal()+"':3}}"), json);
+        assertEquals(aposToQuotes("{'map':{'B':3}}"), json);
+    }
+
+    public void testCustomEnumMapKeySerializer() throws Exception {
+        String json = MAPPER.writeValueAsString(new MyBean661("abc"));
+        assertEquals(aposToQuotes("{'X-FOO':'abc'}"), json);
+    }
+
+    // [databind#594]
+    public void testJsonValueForEnumMapKey() throws Exception {
+        assertEquals(aposToQuotes("{'stuff':{'longValue':'foo'}}"),
+                MAPPER.writeValueAsString(new MyStuff594("foo")));
+    }
+    
+    // [databind#2129]
+    public void testEnumAsIndexForRootMap() throws Exception
+    {
+        final Map<Type, Integer> input = Collections.singletonMap(Type.FIRST, 3);
+
+        // by default, write using name()
+        assertEquals(aposToQuotes("{'FIRST':3}"),
+                MAPPER.writeValueAsString(input));
+
+        // but change with setting
+        assertEquals(aposToQuotes("{'0':3}"),
+                MAPPER.writer()
+                .with(SerializationFeature.WRITE_ENUM_KEYS_USING_INDEX)
+                .writeValueAsString(input));
+
+        // but NOT with value settings
+        assertEquals(aposToQuotes("{'FIRST':3}"),
+                MAPPER.writer()
+                    .with(SerializationFeature.WRITE_ENUMS_USING_INDEX)
+                    .writeValueAsString(input));
+    }
+    
+    // [databind#2129]
+    public void testEnumAsIndexForValueMap() throws Exception
+    {
+        final TypeContainer input = new TypeContainer(Type.SECOND, 72);
+
+        // by default, write using name()
+        assertEquals(aposToQuotes("{'values':{'SECOND':72}}"),
+                MAPPER.writeValueAsString(input));
+
+        // but change with setting
+        assertEquals(aposToQuotes("{'values':{'1':72}}"),
+                MAPPER.writer()
+                .with(SerializationFeature.WRITE_ENUM_KEYS_USING_INDEX)
+                .writeValueAsString(input));
+
+        // but NOT with value settings
+        assertEquals(aposToQuotes("{'values':{'SECOND':72}}"),
+                MAPPER.writer()
+                    .with(SerializationFeature.WRITE_ENUMS_USING_INDEX)
+                    .writeValueAsString(input));
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/JsonValueTest.java b/src/test/java/com/fasterxml/jackson/databind/ser/JsonValueTest.java
index ec1adb5..95cf7fe 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/JsonValueTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/JsonValueTest.java
@@ -240,8 +240,9 @@
         assertEquals("{\"a\":\"a\",\"b\":\"b\"}", MAPPER.writeValueAsString(new ValueWrapper()));
 
         // then static
-        ObjectMapper staticMapper = new ObjectMapper();
-        staticMapper.configure(MapperFeature.USE_STATIC_TYPING, true);
+        ObjectMapper staticMapper = jsonMapperBuilder()
+                .configure(MapperFeature.USE_STATIC_TYPING, true)
+                .build();
         assertEquals("{\"a\":\"a\"}", staticMapper.writeValueAsString(new ValueWrapper()));
     }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestAnnotations.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestAnnotations.java
index 1308caf..dbdc1e3 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestAnnotations.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestAnnotations.java
@@ -229,9 +229,8 @@
     public void testInactiveMethodSerializer() throws Exception
     {
         String json = MAPPER.writeValueAsString(new InactiveClassMethodSerializer(8));
-        /* Here we will get wrapped as an object, since we have
-         * full object, just override a single property
-         */
+        // Here we will get wrapped as an object, since we have
+        // full object, just override a single property
         assertEquals("{\"x\":8}", json);
     }
 
@@ -245,16 +244,18 @@
         assertEquals("{\"a\":3,\"b\":4,\"c\":5,\"d\":6}", m.writeValueAsString(bean));
 
         // but 3 if we require mutator:
-        m = new ObjectMapper();
-        m.enable(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS);
+        m = jsonMapperBuilder()
+                .enable(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS)
+                .build();
         assertEquals("{\"a\":3,\"c\":5,\"d\":6}", m.writeValueAsString(bean));
     }
 
     public void testGettersWithoutSettersOverride() throws Exception
     {
         GettersWithoutSetters2 bean = new GettersWithoutSetters2();
-        ObjectMapper m = new ObjectMapper();
-        m.enable(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS);
+        ObjectMapper m = jsonMapperBuilder()
+                .enable(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS)
+                .build();
         assertEquals("{\"a\":123}", m.writeValueAsString(bean));
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestArraySerialization.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestArraySerialization.java
index 1aa8bd5..8624ebd 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestArraySerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestArraySerialization.java
@@ -6,7 +6,7 @@
 public class TestArraySerialization
     extends BaseMapTest
 {
-    private final ObjectMapper MAPPER = objectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
     
     public void testLongStringArray() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestConfig.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestConfig.java
index 3f224e6..9d10895 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestConfig.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestConfig.java
@@ -124,8 +124,9 @@
         Map<String,Object> result = writeAndMap(MAPPER, new AnnoBean());
         assertEquals(2, result.size());
 
-        ObjectMapper m2 = new ObjectMapper();
-        m2.configure(MapperFeature.USE_ANNOTATIONS, false);
+        ObjectMapper m2 = jsonMapperBuilder()
+                .configure(MapperFeature.USE_ANNOTATIONS, false)
+                .build();
         result = writeAndMap(m2, new AnnoBean());
         assertEquals(1, result.size());
     }
@@ -187,8 +188,9 @@
 
     public void testNoAccessOverrides() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS);
+        ObjectMapper m = jsonMapperBuilder()
+            .disable(MapperFeature.CAN_OVERRIDE_ACCESS_MODIFIERS)
+            .build();
         assertEquals("{\"x\":1}", m.writeValueAsString(new SimpleBean()));
     }
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestCustomSerializers.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestCustomSerializers.java
index 1feeba6..f8be935 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestCustomSerializers.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestCustomSerializers.java
@@ -8,12 +8,16 @@
 
 import org.w3c.dom.Element;
 
+import com.fasterxml.jackson.annotation.JsonFilter;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.io.CharacterEscapes;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
+import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
 import com.fasterxml.jackson.databind.ser.std.CollectionSerializer;
 import com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer;
 import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
@@ -146,11 +150,46 @@
         }
     }
 
+    // [databind#2475]
+    static class MyFilter2475 extends SimpleBeanPropertyFilter {
+        @Override
+        public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception {
+            // Ensure that "current value" remains pojo
+            final JsonStreamContext ctx = jgen.getOutputContext();
+            final Object curr = ctx.getCurrentValue();
+
+            if (!(curr instanceof Item2475)) {
+                throw new Error("Field '"+writer.getName()+"', context not that of `Item2475` instance");
+            }
+            super.serializeAsField(pojo, jgen, provider, writer);
+        }
+    }
+
+    @JsonFilter("myFilter")
+    @JsonPropertyOrder({ "id", "set" })
+    public static class Item2475 {
+        private Collection<String> set;
+        private String id;
+
+        public Item2475(Collection<String> set, String id) {
+            this.set = set;
+            this.id = id;
+        }
+
+        public Collection<String> getSet() {
+            return set;
+        }
+
+        public String getId() {
+            return id;
+        }
+    }
+
     /*
     /**********************************************************
     /* Unit tests
     /**********************************************************
-    */
+     */
 
     private final ObjectMapper MAPPER = new ObjectMapper();
 
@@ -251,4 +290,19 @@
         Set<String> set = new LinkedHashSet<String>(Arrays.asList("foo", null));
         assertEquals(aposToQuotes("['FOO',null]"), mapper.writeValueAsString(set));
     }
+
+    // [databind#2475]
+    public void testIssue2475() throws Exception {
+        SimpleFilterProvider provider = new SimpleFilterProvider().addFilter("myFilter", new MyFilter2475());
+        ObjectWriter writer = MAPPER.writer(provider);
+
+        // contents don't really matter that much as verification within filter but... let's
+        // check anyway
+        assertEquals(aposToQuotes("{'id':'ID-1','set':[]}"),
+                writer.writeValueAsString(new Item2475(new ArrayList<String>(), "ID-1")));
+
+        assertEquals(aposToQuotes("{'id':'ID-2','set':[]}"),
+                writer.writeValueAsString(new Item2475(new HashSet<String>(), "ID-2")));
+    }    
+
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.java
index d2120b9..86e6b08 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestEnumSerialization.java
@@ -20,12 +20,6 @@
 public class TestEnumSerialization
     extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Helper enums
-    /**********************************************************
-     */
-
     /**
      * Test enumeration for verifying Enum serialization functionality.
      */
@@ -125,49 +119,6 @@
         }
     }
 
-    static enum MyEnum594 {
-        VALUE_WITH_A_REALLY_LONG_NAME_HERE("longValue");
-
-        private final String key;
-        private MyEnum594(String k) { key = k; }
-
-        @JsonValue
-        public String getKey() { return key; }
-    }
-
-    static class MyStuff594 {
-        public Map<MyEnum594,String> stuff = new EnumMap<MyEnum594,String>(MyEnum594.class);
-        
-        public MyStuff594(String value) {
-            stuff.put(MyEnum594.VALUE_WITH_A_REALLY_LONG_NAME_HERE, value);
-        }
-    }
-
-    public class MyBean661 {
-        private Map<Foo661, String> foo = new EnumMap<Foo661, String>(Foo661.class);
-
-        public MyBean661(String value) {
-            foo.put(Foo661.FOO, value);
-        }
-
-        @JsonAnyGetter
-        @JsonSerialize(keyUsing = Foo661.Serializer.class)
-        public Map<Foo661, String> getFoo() {
-            return foo;
-        }
-    }
-
-    enum Foo661 {
-        FOO;
-        public static class Serializer extends JsonSerializer<Foo661> {
-            @Override
-            public void serialize(Foo661 value, JsonGenerator jgen, SerializerProvider provider) 
-                    throws IOException {
-                jgen.writeFieldName("X-"+value.name());
-            }
-        }
-    }
-
     protected static enum LC749Enum {
         A, B, C;
         private LC749Enum() { }
@@ -182,12 +133,12 @@
     }
 
     /*
-    /**********************************************************
-    /* Tests
-    /**********************************************************
+    /**********************************************************************
+    /* Test methods
+    /**********************************************************************
      */
 
-    private final ObjectMapper MAPPER = new ObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
     
     public void testSimple() throws Exception
     {
@@ -196,10 +147,8 @@
 
     public void testEnumSet() throws Exception
     {
-        StringWriter sw = new StringWriter();
-        EnumSet<TestEnum> value = EnumSet.of(TestEnum.B);
-        MAPPER.writeValue(sw, value);
-        assertEquals("[\"B\"]", sw.toString());
+        final EnumSet<TestEnum> value = EnumSet.of(TestEnum.B);
+        assertEquals("[\"B\"]", MAPPER.writeValueAsString(value));
     }
 
     /**
@@ -209,12 +158,9 @@
      */
     public void testEnumUsingToString() throws Exception
     {
-        StringWriter sw = new StringWriter();
-        MAPPER.writeValue(sw, AnnotatedTestEnum.C2);
-        assertEquals("\"c2\"", sw.toString());
+        assertEquals("\"c2\"", MAPPER.writeValueAsString(AnnotatedTestEnum.C2));
     }
 
-    // Test [JACKSON-214]
     public void testSubclassedEnums() throws Exception
     {
         assertEquals("\"B\"", MAPPER.writeValueAsString(EnumWithSubClass.B));
@@ -250,7 +196,6 @@
         assertEquals("\"foo\"", MAPPER.writeValueAsString(SerializableEnum.A));
     }
 
-    // [JACKSON-212]
     public void testToStringEnum() throws Exception
     {
         ObjectMapper m = new ObjectMapper();
@@ -272,28 +217,6 @@
         assertEquals("{\"c\":\"value\"}", m.writeValueAsString(enums));
     }
 
-    public void testMapWithEnumKeys() throws Exception
-    {
-        MapBean bean = new MapBean();
-        bean.add(TestEnum.B, 3);
-
-        // By default Enums serialized using `name()`
-        String json = MAPPER.writeValueAsString(bean);
-        assertEquals("{\"map\":{\"B\":3}}", json);
-
-        // but can change
-        json = MAPPER.writer()
-                .with(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
-                .writeValueAsString(bean);
-        assertEquals("{\"map\":{\"b\":3}}", json);
-
-        // [databind#1570]
-        json = MAPPER.writer()
-                .with(SerializationFeature.WRITE_ENUMS_USING_INDEX)
-                .writeValueAsString(bean);
-        assertEquals(aposToQuotes("{'map':{'"+TestEnum.B.ordinal()+"':3}}"), json);
-    }
-
     public void testAsIndex() throws Exception
     {
         // By default, serialize using name
@@ -306,7 +229,6 @@
         assertEquals("1", m.writeValueAsString(TestEnum.B));
     }
 
-    // [JACKSON-757]
     public void testAnnotationsOnEnumCtor() throws Exception
     {
         assertEquals(quote("V1"), MAPPER.writeValueAsString(OK.V1));
@@ -314,7 +236,7 @@
         assertEquals(quote("V2"), MAPPER.writeValueAsString(NOT_OK2.V2));
     }
 
-    // [Issue#227]
+    // [databind#227]
     public void testGenericEnumSerializer() throws Exception
     {
         // By default, serialize using name
@@ -325,22 +247,10 @@
         assertEquals(quote("b"), m.writeValueAsString(TestEnum.B));
     }
 
-    // [databind#594]
-    public void testJsonValueForEnumMapKey() throws Exception {
-        assertEquals(aposToQuotes("{'stuff':{'longValue':'foo'}}"),
-                MAPPER.writeValueAsString(new MyStuff594("foo")));
-    }
-
-    // [databind#661]
-    public void testCustomEnumMapKeySerializer() throws Exception {
-        String json = MAPPER.writeValueAsString(new MyBean661("abc"));
-        assertEquals(aposToQuotes("{'X-FOO':'abc'}"), json);
-    }
-
     // [databind#749]
 
     public void testEnumMapSerDefault() throws Exception {
-        final ObjectMapper mapper = new ObjectMapper();
+        final ObjectMapper mapper = newJsonMapper();
         EnumMap<LC749Enum, String> m = new EnumMap<LC749Enum, String>(LC749Enum.class);
         m.put(LC749Enum.A, "value");
         assertEquals("{\"A\":\"value\"}", mapper.writeValueAsString(m));
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestIterable.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestIterable.java
index 2d49d3a..5e09834 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestIterable.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestIterable.java
@@ -3,6 +3,7 @@
 import java.io.IOException;
 import java.util.*;
 
+import com.fasterxml.jackson.annotation.JsonFilter;
 import com.fasterxml.jackson.core.JsonGenerator;
 
 import com.fasterxml.jackson.databind.*;
@@ -45,7 +46,7 @@
 
         public Iterator<String> getValues() { return values.iterator(); }
     }
-    
+
     static class IntIterable implements Iterable<Integer>
     {
         @Override
@@ -99,6 +100,10 @@
         }
     }
 
+    // [databind#2390]
+    @JsonFilter("default")
+    static class IntIterable2390 extends IntIterable { }
+
     /*
     /**********************************************************
     /* Test methods
@@ -107,10 +112,9 @@
 
     private final ObjectMapper MAPPER = new ObjectMapper();
 
-    private final ObjectMapper STATIC_MAPPER = new ObjectMapper();
-    {
-        STATIC_MAPPER.enable(MapperFeature.USE_STATIC_TYPING);
-    }
+    private final ObjectMapper STATIC_MAPPER = jsonMapperBuilder()
+            .enable(MapperFeature.USE_STATIC_TYPING)
+            .build();
 
     public void testIterator() throws IOException
     {
@@ -157,4 +161,11 @@
         String json = MAPPER.writeValueAsString(new B());
         assertEquals("{\"list\":[[\"Hello world.\"]]}", json);
     }
+
+    // [databind#2390]
+    public void testIterableWithAnnotation() throws Exception
+    {
+        assertEquals("[1,2,3]",
+                STATIC_MAPPER.writeValueAsString(new IntIterable2390()));
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestJsonSerialize.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestJsonSerialize.java
index 483ccb2..0a5ff9a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestJsonSerialize.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestJsonSerialize.java
@@ -188,8 +188,9 @@
 
     public void testStaticTypingWithMap() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.configure(MapperFeature.USE_STATIC_TYPING, true);
+        ObjectMapper m = jsonMapperBuilder()
+                .configure(MapperFeature.USE_STATIC_TYPING, true)
+                .build();
         ValueMap map = new ValueMap();
         map.put("a", new ValueClass());
         assertEquals("{\"a\":{\"x\":3}}", serializeAsString(m, map));
@@ -197,8 +198,9 @@
 
     public void testStaticTypingWithArrayList() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.configure(MapperFeature.USE_STATIC_TYPING, true);
+        ObjectMapper m = jsonMapperBuilder()
+                .configure(MapperFeature.USE_STATIC_TYPING, true)
+                .build();
         ValueList list = new ValueList();
         list.add(new ValueClass());
         assertEquals("[{\"x\":3}]", m.writeValueAsString(list));
@@ -206,8 +208,9 @@
 
     public void testStaticTypingWithLinkedList() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.configure(MapperFeature.USE_STATIC_TYPING, true);
+        ObjectMapper m = jsonMapperBuilder()
+                .configure(MapperFeature.USE_STATIC_TYPING, true)
+                .build();
         ValueLinkedList list = new ValueLinkedList();
         list.add(new ValueClass());
         assertEquals("[{\"x\":3}]", serializeAsString(m, list));
@@ -215,8 +218,9 @@
     
     public void testStaticTypingWithArray() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.configure(MapperFeature.USE_STATIC_TYPING, true);
+        ObjectMapper m = jsonMapperBuilder()
+                .configure(MapperFeature.USE_STATIC_TYPING, true)
+                .build();
         ValueInterface[] array = new ValueInterface[] { new ValueClass() };
         assertEquals("[{\"x\":3}]", serializeAsString(m, array));
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestKeySerializers.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestKeySerializers.java
deleted file mode 100644
index dd97392..0000000
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestKeySerializers.java
+++ /dev/null
@@ -1,254 +0,0 @@
-package com.fasterxml.jackson.databind.ser;
-
-import java.io.IOException;
-import java.util.*;
-
-import com.fasterxml.jackson.annotation.*;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
-import com.fasterxml.jackson.databind.module.SimpleModule;
-
-public class TestKeySerializers extends BaseMapTest
-{
-    public static class KarlSerializer extends JsonSerializer<String>
-    {
-        @Override
-        public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException {
-            gen.writeFieldName("Karl");
-        }
-    }
-
-    public static class NullKeySerializer extends JsonSerializer<Object>
-    {
-        private String _null;
-        public NullKeySerializer(String s) { _null = s; }
-        @Override
-        public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
-            gen.writeFieldName(_null);
-        }
-    }
-
-    public static class NullValueSerializer extends JsonSerializer<Object>
-    {
-        private String _null;
-        public NullValueSerializer(String s) { _null = s; }
-        @Override
-        public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
-            gen.writeString(_null);
-        }
-    }
-    
-    public static class NotKarlBean
-    {
-        public Map<String,Integer> map = new HashMap<String,Integer>();
-        {
-            map.put("Not Karl", 1);
-        }
-    }
-
-    public static class KarlBean
-    {
-        @JsonSerialize(keyUsing = KarlSerializer.class)
-        public Map<String,Integer> map = new HashMap<String,Integer>();
-        {
-            map.put("Not Karl", 1);
-        }
-    }
-
-    enum ABC {
-        A, B, C
-    }
-
-    enum AbcLC {
-        A, B, C;
-
-        @JsonValue
-        public String toLC() {
-            return name().toLowerCase();
-        }
-    }
-    
-    static class ABCKeySerializer extends JsonSerializer<ABC> {
-        @Override
-        public void serialize(ABC value, JsonGenerator gen,
-                SerializerProvider provider) throws IOException {
-            gen.writeFieldName("xxx"+value);
-        }
-    }
-
-    @JsonSerialize(keyUsing = ABCKeySerializer.class)
-    public static enum ABCMixin { }
-
-    public static enum Outer {
-        inner;
-    }
-
-    static class ABCMapWrapper {
-        public Map<ABC,String> stuff = new HashMap<ABC,String>();
-        public ABCMapWrapper() {
-            stuff.put(ABC.B, "bar");
-        }
-    }
-
-    static class BAR<T>{
-        T value;
-
-        public BAR(T value) {
-            this.value = value;
-        }
-
-        @JsonValue
-        public T getValue() {
-            return value;
-        }
-
-        @Override
-        public String toString() {
-            return this.getClass().getSimpleName()
-                    + ", value:" + value
-                    ;
-        }
-    }
-
-    static class UCString {
-        private String value;
-
-        public UCString(String v) {
-            value = v.toUpperCase();
-        }
-
-        @JsonValue
-        public String asString() {
-            return value;
-        }
-    }
-
-    /*
-    /**********************************************************
-    /* Unit tests
-    /**********************************************************
-     */
-
-    private final ObjectMapper MAPPER = new ObjectMapper();
-    
-    public void testNotKarl() throws IOException {
-        final String serialized = MAPPER.writeValueAsString(new NotKarlBean());
-        assertEquals("{\"map\":{\"Not Karl\":1}}", serialized);
-    }
-
-    public void testKarl() throws IOException {
-        final String serialized = MAPPER.writeValueAsString(new KarlBean());
-        assertEquals("{\"map\":{\"Karl\":1}}", serialized);
-    }
-
-    // [databind#75]: caching of KeySerializers
-    public void testBoth() throws IOException
-    {
-        // Let's NOT use shared one, to ensure caching starts from clean slate
-        final ObjectMapper mapper = new ObjectMapper();
-        final String value1 = mapper.writeValueAsString(new NotKarlBean());
-        assertEquals("{\"map\":{\"Not Karl\":1}}", value1);
-        final String value2 = mapper.writeValueAsString(new KarlBean());
-        assertEquals("{\"map\":{\"Karl\":1}}", value2);
-    }
-
-    // Test custom key serializer for enum
-    public void testCustomForEnum() throws IOException
-    {
-        // cannot use shared mapper as we are registering a module
-        final ObjectMapper mapper = new ObjectMapper();
-        SimpleModule mod = new SimpleModule("test");
-        mod.addKeySerializer(ABC.class, new ABCKeySerializer());
-        mapper.registerModule(mod);
-
-        String json = mapper.writeValueAsString(new ABCMapWrapper());
-        assertEquals("{\"stuff\":{\"xxxB\":\"bar\"}}", json);
-    }
-
-    public void testCustomNullSerializers() throws IOException
-    {
-        final ObjectMapper mapper = new ObjectMapper();
-        mapper.getSerializerProvider().setNullKeySerializer(new NullKeySerializer("NULL-KEY"));
-        mapper.getSerializerProvider().setNullValueSerializer(new NullValueSerializer("NULL"));
-        Map<String,Integer> input = new HashMap<>();
-        input.put(null, 3);
-        String json = mapper.writeValueAsString(input);
-        assertEquals("{\"NULL-KEY\":3}", json);
-        json = mapper.writeValueAsString(new Object[] { 1, null, true });
-        assertEquals("[1,\"NULL\",true]", json);
-    }
-    
-    public void testCustomEnumInnerMapKey() throws Exception {
-        Map<Outer, Object> outerMap = new HashMap<Outer, Object>();
-        Map<ABC, Map<String, String>> map = new EnumMap<ABC, Map<String, String>>(ABC.class);
-        Map<String, String> innerMap = new HashMap<String, String>();
-        innerMap.put("one", "1");
-        map.put(ABC.A, innerMap);
-        outerMap.put(Outer.inner, map);
-        final ObjectMapper mapper = new ObjectMapper();
-        SimpleModule mod = new SimpleModule("test");
-        mod.setMixInAnnotation(ABC.class, ABCMixin.class);
-        mod.addKeySerializer(ABC.class, new ABCKeySerializer());
-        mapper.registerModule(mod);
-
-        JsonNode tree = mapper.convertValue(outerMap, JsonNode.class);
-
-        JsonNode innerNode = tree.get("inner");
-        String key = innerNode.fieldNames().next();
-        assertEquals("xxxA", key);
-    }
-
-    // [databind#838]
-    public void testUnWrappedMapWithDefaultType() throws Exception{
-        final ObjectMapper mapper = new ObjectMapper();
-        SimpleModule mod = new SimpleModule("test");
-        mod.addKeySerializer(ABC.class, new ABCKeySerializer());
-        mapper.registerModule(mod);
-
-        TypeResolverBuilder<?> typer = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL);
-        typer = typer.init(JsonTypeInfo.Id.NAME, null);
-        typer = typer.inclusion(JsonTypeInfo.As.PROPERTY);
-        //typer = typer.typeProperty(TYPE_FIELD);
-        typer = typer.typeIdVisibility(true);
-        mapper.setDefaultTyping(typer);
-
-        Map<ABC,String> stuff = new HashMap<ABC,String>();
-        stuff.put(ABC.B, "bar");
-        String json = mapper.writerFor(new TypeReference<Map<ABC, String>>() {})
-                .writeValueAsString(stuff);
-        assertEquals("{\"@type\":\"HashMap\",\"xxxB\":\"bar\"}", json);
-    }
-
-    // [databind#838]
-    @SuppressWarnings("deprecation")
-    public void testUnWrappedMapWithKeySerializer() throws Exception{
-        SimpleModule mod = new SimpleModule("test");
-        mod.addKeySerializer(ABC.class, new ABCKeySerializer());
-        final ObjectMapper mapper = new ObjectMapper()
-            .registerModule(mod)
-            .enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)
-            .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
-            .disable(SerializationFeature.WRITE_NULL_MAP_VALUES)
-            .setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
-            ;
-
-        Map<ABC,BAR<?>> stuff = new HashMap<ABC,BAR<?>>();
-        stuff.put(ABC.B, new BAR<String>("bar"));
-        String json = mapper.writerFor(new TypeReference<Map<ABC,BAR<?>>>() {})
-                .writeValueAsString(stuff);
-        assertEquals("{\"xxxB\":\"bar\"}", json);
-    }
-
-    // [databind#943]
-    public void testDynamicMapKeys() throws Exception
-    {
-        Map<Object,Integer> stuff = new LinkedHashMap<Object,Integer>();
-        stuff.put(AbcLC.B, Integer.valueOf(3));
-        stuff.put(new UCString("foo"), Integer.valueOf(4));
-        String json = MAPPER.writeValueAsString(stuff);
-        assertEquals(aposToQuotes("{'b':3,'FOO':4}"), json);
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestMapSerialization.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestMapSerialization.java
index 26cabd6..ca4c2e2 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestMapSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestMapSerialization.java
@@ -11,6 +11,7 @@
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 @SuppressWarnings("serial")
 public class TestMapSerialization extends BaseMapTest
@@ -186,7 +187,8 @@
         assertEquals(aposToQuotes("[{'answer':42}]"), json);
 
         // and maybe with bit of extra typing?
-        ObjectMapper mapper = new ObjectMapper().enableDefaultTyping(DefaultTyping.NON_FINAL);
+        ObjectMapper mapper = new ObjectMapper().activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                DefaultTyping.NON_FINAL);
         json = mapper.writeValueAsString(input);
         assertEquals(aposToQuotes("['"+StringIntMapEntry.class.getName()+"',{'answer':42}]"),
                 json);
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestRootType.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestRootType.java
index 56af44d..fb17b50 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestRootType.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestRootType.java
@@ -114,9 +114,10 @@
 
     public void testInArray() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
+        ObjectMapper mapper = jsonMapperBuilder()
         // must force static typing, otherwise won't matter a lot
-        mapper.configure(MapperFeature.USE_STATIC_TYPING, true);
+                .configure(MapperFeature.USE_STATIC_TYPING, true)
+                .build();
         SubType[] ob = new SubType[] { new SubType() };
         String json = mapper.writerFor(BaseInterface[].class).writeValueAsString(ob);
         // should propagate interface type through due to root declaration; static typing
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestSerializationOrder.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestSerializationOrder.java
index 6cf1b41..eac04d3 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestSerializationOrder.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestSerializationOrder.java
@@ -11,12 +11,6 @@
 public class TestSerializationOrder
     extends BaseMapTest
 {
-    /*
-    /**********************************************************
-    /* Annotated helper classes
-    /**********************************************************
-     */
-
     static class BeanWithCreator
     {
         public int a;
@@ -33,7 +27,7 @@
     static class BeanWithOrder
     {
         public int d, b, a, c;
-        
+
         public BeanWithOrder(int a, int b, int c, int d) {
             this.a = a;
             this.b = b;
@@ -59,10 +53,10 @@
 
     @JsonPropertyOrder(value={"a","b","x","z"})
     static class BeanFor268 {
-    	@JsonProperty("a") public String xA = "a";
-    	@JsonProperty("z") public String aZ = "z";
-    	@JsonProperty("b") public String xB() { return "b"; }
-    	@JsonProperty("x") public String aX() { return "x"; }
+        @JsonProperty("a") public String xA = "a";
+        @JsonProperty("z") public String aZ = "z";
+    	   @JsonProperty("b") public String xB() { return "b"; }
+    	   @JsonProperty("x") public String aX() { return "x"; }
     }
 
     static class BeanFor459 {
@@ -72,7 +66,7 @@
         public int a = 1;
     }
 
-    // For [Issue#311]
+    // For [databind#311]
     @JsonPropertyOrder(alphabetic = true)
     public class BeanForGH311 {
         private final int a;
@@ -87,16 +81,15 @@
         public int getA() { return a; }
         public int getB() { return b; }
     }
-    
+
     /*
     /*********************************************
     /* Unit tests
     /*********************************************
      */
 
-    final ObjectMapper MAPPER = new ObjectMapper();
-    
-    // Test for [JACKSON-170]
+    private final ObjectMapper MAPPER = newJsonMapper();
+
     public void testImplicitOrderByCreator() throws Exception
     {
         assertEquals("{\"c\":1,\"a\":2,\"b\":0}", MAPPER.writeValueAsString(new BeanWithCreator(1, 2)));
@@ -112,11 +105,11 @@
         assertEquals("{\"d\":4,\"a\":1,\"b\":2,\"c\":3}", MAPPER.writeValueAsString(new SubBeanWithOrder(1, 2, 3, 4)));
     }
 
-
     public void testOrderWithMixins() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.addMixIn(BeanWithOrder.class, OrderMixIn.class);
+        ObjectMapper m = jsonMapperBuilder()
+                .addMixIn(BeanWithOrder.class, OrderMixIn.class)
+                .build();
         assertEquals("{\"b\":2,\"a\":1,\"c\":3,\"d\":4}",
                 serializeAsString(m, new BeanWithOrder(1, 2, 3, 4)));
     }
@@ -129,18 +122,19 @@
 
     public void testOrderWithFeature() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
+        ObjectMapper m = jsonMapperBuilder()
+                .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
+                .build();
         assertEquals("{\"a\":1,\"b\":2,\"c\":3,\"d\":4}",
                 m.writeValueAsString(new BeanFor459()));
     }
 
-    // [Issue#311]
-
+    // [databind#311]
     public void testAlphaAndCreatorOrdering() throws Exception
     {
-        ObjectMapper m = new ObjectMapper();
-        m.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
+        ObjectMapper m = jsonMapperBuilder()
+                .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
+                .build();
         String json = m.writeValueAsString(new BeanForGH311(2, 1));
         assertEquals("{\"a\":1,\"b\":2}", json);
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/filter/MapInclusion2573Test.java b/src/test/java/com/fasterxml/jackson/databind/ser/filter/MapInclusion2573Test.java
new file mode 100644
index 0000000..58122d5
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/filter/MapInclusion2573Test.java
@@ -0,0 +1,84 @@
+package com.fasterxml.jackson.databind.ser.filter;
+
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+
+public class MapInclusion2573Test extends BaseMapTest
+{
+    @JsonPropertyOrder({ "model", "properties" })
+    static class Car
+    {
+        public String model;
+        public Map<String, Integer> properties;
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+
+    private final Map<String, Integer> CAR_PROPERTIES = new LinkedHashMap<>();
+    {
+        CAR_PROPERTIES.put("Speed", 100);
+        CAR_PROPERTIES.put("Weight", null);
+    }
+
+    private final Car CAR = new Car();
+    {
+        CAR.model = "F60";
+        CAR.properties = CAR_PROPERTIES;
+    }
+
+    private final JsonInclude.Value BOTH_NON_NULL = JsonInclude.Value.construct(JsonInclude.Include.NON_NULL,
+            JsonInclude.Include.NON_NULL);
+    
+//    final private ObjectMapper MAPPER = objectMapper();
+
+    // [databind#2572]
+    public void test2572MapDefault() throws Exception
+    {
+                
+        ObjectMapper mapper = JsonMapper.builder()
+                .defaultPropertyInclusion(BOTH_NON_NULL)
+                .build();
+        assertEquals(aposToQuotes("{'Speed':100}"),
+                mapper.writeValueAsString(CAR_PROPERTIES));
+        assertEquals(aposToQuotes("{'model':'F60','properties':{'Speed':100}}"),
+                mapper.writeValueAsString(CAR));
+    }
+
+    // [databind#2572]
+    public void test2572MapOverrideUseDefaults() throws Exception
+    {
+        ObjectMapper mapper = JsonMapper.builder()
+                .defaultPropertyInclusion(BOTH_NON_NULL)
+                .build();
+        mapper.configOverride(Map.class)
+            .setInclude(JsonInclude.Value.construct(JsonInclude.Include.USE_DEFAULTS,
+                    JsonInclude.Include.USE_DEFAULTS));
+        assertEquals(aposToQuotes("{'Speed':100}"),
+                mapper.writeValueAsString(CAR_PROPERTIES));
+        assertEquals(aposToQuotes("{'model':'F60','properties':{'Speed':100}}"),
+                mapper.writeValueAsString(CAR));
+    }
+
+    // [databind#2572]
+    public void test2572MapOverrideInclAlways() throws Exception
+    {
+        ObjectMapper mapper = JsonMapper.builder()
+                .defaultPropertyInclusion(BOTH_NON_NULL)
+                .build();
+        mapper.configOverride(Map.class)
+            .setInclude(JsonInclude.Value.construct(JsonInclude.Include.ALWAYS,
+                    JsonInclude.Include.ALWAYS));
+        assertEquals(aposToQuotes("{'Speed':100,'Weight':null}"),
+                mapper.writeValueAsString(CAR_PROPERTIES));
+        assertEquals(aposToQuotes("{'model':'F60','properties':{'Speed':100,'Weight':null}}"),
+                mapper.writeValueAsString(CAR));
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/BigDecimalAsString2519Test.java b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/BigDecimalAsString2519Test.java
new file mode 100644
index 0000000..f75b4a4
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/BigDecimalAsString2519Test.java
@@ -0,0 +1,40 @@
+package com.fasterxml.jackson.databind.ser.jdk;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.*;
+
+public class BigDecimalAsString2519Test extends BaseMapTest
+{
+    static class Bean2519Typed {
+        public List<BigDecimal> values = new ArrayList<>();
+    }
+
+    static class Bean2519Untyped {
+        public Collection<BigDecimal> values = new HashSet<>();
+    }
+
+    public void testBigDecimalAsString2519Typed() throws Exception
+    {
+        Bean2519Typed foo = new Bean2519Typed();
+        foo.values.add(new BigDecimal("2.34"));
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.configOverride(BigDecimal.class)
+            .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING));
+        String json = mapper.writeValueAsString(foo);
+        assertEquals(aposToQuotes("{'values':['2.34']}"), json);
+    }
+
+    public void testBigDecimalAsString2519Untyped() throws Exception
+    {
+        Bean2519Untyped foo = new Bean2519Untyped();
+        foo.values.add(new BigDecimal("2.34"));
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.configOverride(BigDecimal.class)
+            .setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING));
+        String json = mapper.writeValueAsString(foo);
+        assertEquals(aposToQuotes("{'values':['2.34']}"), json);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/BigDecimalPlain2230Test.java b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/BigDecimalPlain2230Test.java
new file mode 100644
index 0000000..fdbe088
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/BigDecimalPlain2230Test.java
@@ -0,0 +1,37 @@
+package com.fasterxml.jackson.databind.ser.jdk;
+
+import java.math.BigDecimal;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import com.fasterxml.jackson.core.StreamWriteFeature;
+
+import com.fasterxml.jackson.databind.*;
+
+public class BigDecimalPlain2230Test extends BaseMapTest
+{
+    static class BigDecimalAsString {
+        @JsonFormat(shape=JsonFormat.Shape.STRING)
+        public BigDecimal value;
+
+        public BigDecimalAsString() { this(BigDecimal.valueOf(0.25)); }
+        public BigDecimalAsString(BigDecimal v) { value = v; }
+    }
+
+    private final ObjectMapper MAPPER = objectMapper();
+
+    public void testBigIntegerAsPlainTest() throws Exception
+    {
+        final String NORM_VALUE = "0.0000000005";
+        final BigDecimal BD_VALUE = new BigDecimal(NORM_VALUE);
+        final BigDecimalAsString INPUT = new BigDecimalAsString(BD_VALUE);
+        // by default, use the default `toString()`
+        assertEquals("{\"value\":\""+BD_VALUE.toString()+"\"}", MAPPER.writeValueAsString(INPUT));
+
+        // but can force to "plain" notation
+        final ObjectMapper m = jsonMapperBuilder()
+            .enable(StreamWriteFeature.WRITE_BIGDECIMAL_AS_PLAIN)
+            .build();
+        assertEquals("{\"value\":\""+NORM_VALUE+"\"}", m.writeValueAsString(INPUT));
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/CollectionSerializationTest.java b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/CollectionSerializationTest.java
index 1d09d74..7ea97d1 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/CollectionSerializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/CollectionSerializationTest.java
@@ -8,6 +8,7 @@
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class CollectionSerializationTest
     extends BaseMapTest
@@ -273,8 +274,9 @@
         assertEquals(aposToQuotes("{'list':['a','b','c']}"), json);
 
         // but then with default typing
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping(DefaultTyping.NON_FINAL);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance, DefaultTyping.NON_FINAL)
+                .build();
         json = mapper.writeValueAsString(w);
         assertEquals(aposToQuotes(String.format("['%s',{'list':['%s',['a','b','c']]}]",
                 w.getClass().getName(), w.list.getClass().getName())), json);
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/JDKTypeSerializationTest.java b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/JDKTypeSerializationTest.java
index b93d9a9..5c4da87 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/JDKTypeSerializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/JDKTypeSerializationTest.java
@@ -150,13 +150,36 @@
     public void testSlicedByteBuffer() throws IOException
     {
         final byte[] INPUT_BYTES = new byte[] { 1, 2, 3, 4, 5 };
-        String exp = MAPPER.writeValueAsString(new byte[] { 3, 4, 5 });
         ByteBuffer bbuf = ByteBuffer.wrap(INPUT_BYTES);
 
         bbuf.position(2);
         ByteBuffer slicedBuf = bbuf.slice();
 
-        assertEquals(exp, MAPPER.writeValueAsString(slicedBuf));
+        assertEquals(MAPPER.writeValueAsString(new byte[] { 3, 4, 5 }),
+                MAPPER.writeValueAsString(slicedBuf));
+
+        // but how about offset within?
+        slicedBuf.position(1);
+        assertEquals(MAPPER.writeValueAsString(new byte[] { 4, 5 }),
+                MAPPER.writeValueAsString(slicedBuf));
+    }
+
+    // [databind#2602]: Need to consider position()
+    public void testDuplicatedByteBufferWithCustomPosition() throws IOException
+    {
+        final byte[] INPUT_BYTES = new byte[] { 1, 2, 3, 4, 5 };
+
+        String exp = MAPPER.writeValueAsString(new byte[] { 3, 4, 5 });
+        ByteBuffer bbuf = ByteBuffer.wrap(INPUT_BYTES);
+        bbuf.position(2);
+        ByteBuffer duplicated = bbuf.duplicate();
+        assertEquals(exp, MAPPER.writeValueAsString(duplicated));
+
+        // also check differently constructed bytebuffer (noting that
+        // offset given is the _position_ to use, NOT array offset
+        exp = MAPPER.writeValueAsString(new byte[] { 2, 3, 4 });
+        bbuf = ByteBuffer.wrap(INPUT_BYTES, 1, 3);
+        assertEquals(exp, MAPPER.writeValueAsString(bbuf.duplicate()));
     }
 
     // Verify that efficient UUID codec won't mess things up:
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/MapKeySerializationTest.java b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/MapKeySerializationTest.java
index 8731deb..661f0b4 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/MapKeySerializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/MapKeySerializationTest.java
@@ -1,20 +1,57 @@
 package com.fasterxml.jackson.databind.ser.jdk;
 
 import java.io.IOException;
+import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.annotation.JsonValue;
+
 import com.fasterxml.jackson.core.Base64Variants;
 import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.type.TypeReference;
+
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
+import com.fasterxml.jackson.databind.module.SimpleModule;
 
 @SuppressWarnings("serial")
 public class MapKeySerializationTest extends BaseMapTest
 {
-    // for [databind#47]
+    public static class KarlSerializer extends JsonSerializer<String>
+    {
+        @Override
+        public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException {
+            gen.writeFieldName("Karl");
+        }
+    }
+
+    public static class NotKarlBean
+    {
+        public Map<String,Integer> map = new HashMap<String,Integer>();
+        {
+            map.put("Not Karl", 1);
+        }
+    }
+
+    public static class KarlBean
+    {
+        @JsonSerialize(keyUsing = KarlSerializer.class)
+        public Map<String,Integer> map = new HashMap<String,Integer>();
+        {
+            map.put("Not Karl", 1);
+        }
+    }
+
+    public static enum Outer {
+        inner;
+    }
+
     public static class Wat
     {
         private final String wat;
@@ -37,6 +74,90 @@
 
     static class WatMap extends HashMap<Wat,Boolean> { }
 
+    enum ABC {
+        A, B, C
+    }
+
+    enum AbcLC {
+        A, B, C;
+
+        @JsonValue
+        public String toLC() {
+            return name().toLowerCase();
+        }
+    }
+
+    static class ABCMapWrapper {
+        public Map<ABC,String> stuff = new HashMap<ABC,String>();
+        public ABCMapWrapper() {
+            stuff.put(ABC.B, "bar");
+        }
+    }
+
+    @JsonSerialize(keyUsing = ABCKeySerializer.class)
+    public static enum ABCMixin { }
+
+    static class BAR<T>{
+        T value;
+
+        public BAR(T value) {
+            this.value = value;
+        }
+
+        @JsonValue
+        public T getValue() {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return this.getClass().getSimpleName()
+                    + ", value:" + value
+                    ;
+        }
+    }
+
+    static class UCString {
+        private String value;
+
+        public UCString(String v) {
+            value = v.toUpperCase();
+        }
+
+        @JsonValue
+        public String asString() {
+            return value;
+        }
+    }
+
+    static class ABCKeySerializer extends JsonSerializer<ABC> {
+        @Override
+        public void serialize(ABC value, JsonGenerator gen,
+                SerializerProvider provider) throws IOException {
+            gen.writeFieldName("xxx"+value);
+        }
+    }
+
+    public static class NullKeySerializer extends JsonSerializer<Object>
+    {
+        private String _null;
+        public NullKeySerializer(String s) { _null = s; }
+        @Override
+        public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
+            gen.writeFieldName(_null);
+        }
+    }
+
+    public static class NullValueSerializer extends JsonSerializer<Object>
+    {
+        private String _null;
+        public NullValueSerializer(String s) { _null = s; }
+        @Override
+        public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
+            gen.writeString(_null);
+        }
+    }
+
     static class DefaultKeySerializer extends JsonSerializer<Object>
     {
         @Override
@@ -54,6 +175,82 @@
 
     final private ObjectMapper MAPPER = objectMapper();
 
+    public void testNotKarl() throws IOException {
+        final String serialized = MAPPER.writeValueAsString(new NotKarlBean());
+        assertEquals("{\"map\":{\"Not Karl\":1}}", serialized);
+    }
+
+    public void testKarl() throws IOException {
+        final String serialized = MAPPER.writeValueAsString(new KarlBean());
+        assertEquals("{\"map\":{\"Karl\":1}}", serialized);
+    }
+
+    // [databind#75]: caching of KeySerializers
+    public void testBoth() throws IOException
+    {
+        // Let's NOT use shared one, to ensure caching starts from clean slate
+        final ObjectMapper mapper = new ObjectMapper();
+        final String value1 = mapper.writeValueAsString(new NotKarlBean());
+        assertEquals("{\"map\":{\"Not Karl\":1}}", value1);
+        final String value2 = mapper.writeValueAsString(new KarlBean());
+        assertEquals("{\"map\":{\"Karl\":1}}", value2);
+    }
+
+    // Test custom key serializer for enum
+    public void testCustomForEnum() throws IOException
+    {
+        // cannot use shared mapper as we are registering a module
+        final ObjectMapper mapper = new ObjectMapper();
+        SimpleModule mod = new SimpleModule("test");
+        mod.addKeySerializer(ABC.class, new ABCKeySerializer());
+        mapper.registerModule(mod);
+
+        String json = mapper.writeValueAsString(new ABCMapWrapper());
+        assertEquals("{\"stuff\":{\"xxxB\":\"bar\"}}", json);
+    }
+
+    public void testCustomNullSerializers() throws IOException
+    {
+        final ObjectMapper mapper = new ObjectMapper();
+        mapper.getSerializerProvider().setNullKeySerializer(new NullKeySerializer("NULL-KEY"));
+        mapper.getSerializerProvider().setNullValueSerializer(new NullValueSerializer("NULL"));
+        Map<String,Integer> input = new HashMap<>();
+        input.put(null, 3);
+        String json = mapper.writeValueAsString(input);
+        assertEquals("{\"NULL-KEY\":3}", json);
+        json = mapper.writeValueAsString(new Object[] { 1, null, true });
+        assertEquals("[1,\"NULL\",true]", json);
+    }
+    
+    public void testCustomEnumInnerMapKey() throws Exception {
+        Map<Outer, Object> outerMap = new HashMap<Outer, Object>();
+        Map<ABC, Map<String, String>> map = new EnumMap<ABC, Map<String, String>>(ABC.class);
+        Map<String, String> innerMap = new HashMap<String, String>();
+        innerMap.put("one", "1");
+        map.put(ABC.A, innerMap);
+        outerMap.put(Outer.inner, map);
+        final ObjectMapper mapper = new ObjectMapper();
+        SimpleModule mod = new SimpleModule("test");
+        mod.setMixInAnnotation(ABC.class, ABCMixin.class);
+        mod.addKeySerializer(ABC.class, new ABCKeySerializer());
+        mapper.registerModule(mod);
+
+        JsonNode tree = mapper.convertValue(outerMap, JsonNode.class);
+
+        JsonNode innerNode = tree.get("inner");
+        String key = innerNode.fieldNames().next();
+        assertEquals("xxxA", key);
+    }
+
+    public void testDefaultKeySerializer() throws IOException
+    {
+        ObjectMapper m = new ObjectMapper();
+        m.getSerializerProvider().setDefaultKeySerializer(new DefaultKeySerializer());
+        Map<String,String> map = new HashMap<String,String>();
+        map.put("a", "b");
+        assertEquals("{\"DEFAULT:a\":\"b\"}", m.writeValueAsString(map));
+    }
+    
     // [databind#47]
     public void testMapJsonValueKey47() throws Exception
     {
@@ -73,15 +270,57 @@
         assertEquals(aposToQuotes("{'java.lang.String':2}"), json);
     }
 
-    public void testDefaultKeySerializer() throws IOException
-    {
-        ObjectMapper m = new ObjectMapper();
-        m.getSerializerProvider().setDefaultKeySerializer(new DefaultKeySerializer());
-        Map<String,String> map = new HashMap<String,String>();
-        map.put("a", "b");
-        assertEquals("{\"DEFAULT:a\":\"b\"}", m.writeValueAsString(map));
+    // [databind#838]
+    @SuppressWarnings("deprecation")
+    public void testUnWrappedMapWithKeySerializer() throws Exception{
+        SimpleModule mod = new SimpleModule("test");
+        mod.addKeySerializer(ABC.class, new ABCKeySerializer());
+        final ObjectMapper mapper = new ObjectMapper()
+            .registerModule(mod)
+            .enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)
+            .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
+            .disable(SerializationFeature.WRITE_NULL_MAP_VALUES)
+            .setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
+            ;
+
+        Map<ABC,BAR<?>> stuff = new HashMap<ABC,BAR<?>>();
+        stuff.put(ABC.B, new BAR<String>("bar"));
+        String json = mapper.writerFor(new TypeReference<Map<ABC,BAR<?>>>() {})
+                .writeValueAsString(stuff);
+        assertEquals("{\"xxxB\":\"bar\"}", json);
     }
 
+    // [databind#838]
+    public void testUnWrappedMapWithDefaultType() throws Exception{
+        final ObjectMapper mapper = new ObjectMapper();
+        SimpleModule mod = new SimpleModule("test");
+        mod.addKeySerializer(ABC.class, new ABCKeySerializer());
+        mapper.registerModule(mod);
+
+        TypeResolverBuilder<?> typer = ObjectMapper.DefaultTypeResolverBuilder.construct(
+                ObjectMapper.DefaultTyping.NON_FINAL, mapper.getPolymorphicTypeValidator());
+        typer = typer.init(JsonTypeInfo.Id.NAME, null);
+        typer = typer.inclusion(JsonTypeInfo.As.PROPERTY);
+        //typer = typer.typeProperty(TYPE_FIELD);
+        typer = typer.typeIdVisibility(true);
+        mapper.setDefaultTyping(typer);
+
+        Map<ABC,String> stuff = new HashMap<ABC,String>();
+        stuff.put(ABC.B, "bar");
+        String json = mapper.writerFor(new TypeReference<Map<ABC, String>>() {})
+                .writeValueAsString(stuff);
+        assertEquals("{\"@type\":\"HashMap\",\"xxxB\":\"bar\"}", json);
+    }
+    
+    // [databind#943]
+    public void testDynamicMapKeys() throws Exception
+    {
+        Map<Object,Integer> stuff = new LinkedHashMap<Object,Integer>();
+        stuff.put(AbcLC.B, Integer.valueOf(3));
+        stuff.put(new UCString("foo"), Integer.valueOf(4));
+        String json = MAPPER.writeValueAsString(stuff);
+        assertEquals(aposToQuotes("{'b':3,'FOO':4}"), json);
+    }    
     // [databind#1552]
     public void testMapsWithBinaryKeys() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/NumberSerTest.java b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/NumberSerTest.java
index d99eaf4..cff30a4 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/NumberSerTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/NumberSerTest.java
@@ -4,7 +4,9 @@
 import java.math.BigInteger;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
+
 import com.fasterxml.jackson.databind.BaseMapTest;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
@@ -15,7 +17,11 @@
  */
 public class NumberSerTest extends BaseMapTest
 {
-    private final ObjectMapper MAPPER = objectMapper();
+    private final ObjectMapper MAPPER = sharedMapper();
+
+    private final ObjectMapper NON_EMPTY_MAPPER = newJsonMapper()
+            .setDefaultPropertyInclusion(JsonInclude.Include.NON_EMPTY)
+            ;
 
     static class IntWrapper {
         public int i;
@@ -55,7 +61,10 @@
 
     static class BigDecimalAsString {
         @JsonFormat(shape=JsonFormat.Shape.STRING)
-        public BigDecimal value = BigDecimal.valueOf(0.25);
+        public BigDecimal value;
+
+        public BigDecimalAsString() { this(BigDecimal.valueOf(0.25)); }
+        public BigDecimalAsString(BigDecimal v) { value = v; }
     }
     
     static class NumberWrapper {
@@ -110,6 +119,15 @@
         assertEquals(aposToQuotes("{'value':'123456'}"), MAPPER.writeValueAsString(new BigIntegerAsString()));
     }
 
+    public void testNumbersAsStringNonEmpty() throws Exception
+    {
+        assertEquals(aposToQuotes("{'value':'3'}"), NON_EMPTY_MAPPER.writeValueAsString(new IntAsString()));
+        assertEquals(aposToQuotes("{'value':'4'}"), NON_EMPTY_MAPPER.writeValueAsString(new LongAsString()));
+        assertEquals(aposToQuotes("{'value':'-0.5'}"), NON_EMPTY_MAPPER.writeValueAsString(new DoubleAsString()));
+        assertEquals(aposToQuotes("{'value':'0.25'}"), NON_EMPTY_MAPPER.writeValueAsString(new BigDecimalAsString()));
+        assertEquals(aposToQuotes("{'value':'123456'}"), NON_EMPTY_MAPPER.writeValueAsString(new BigIntegerAsString()));
+    }
+
     public void testConfigOverridesForNumbers() throws Exception
     {
         ObjectMapper mapper = new ObjectMapper();
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/SqlDateSerializationTest.java b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/SqlDateSerializationTest.java
index 3f8dbba..698b1a6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/SqlDateSerializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/SqlDateSerializationTest.java
@@ -98,7 +98,8 @@
     // [databind#2064]
     public void testSqlDateConfigOverride() throws Exception
     {
-        ObjectMapper mapper = newObjectMapper();
+        ObjectMapper mapper = newJsonMapper();
+        mapper.setTimeZone(TimeZone.getDefault());
         mapper.configOverride(java.sql.Date.class)
             .setFormat(JsonFormat.Value.forPattern("yyyy+MM+dd"));        
         assertEquals("\"1980+04+14\"",
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/ScalarCoercionTest.java b/src/test/java/com/fasterxml/jackson/databind/struct/ScalarCoercionTest.java
index e524d72..e1d5180 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/ScalarCoercionTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/ScalarCoercionTest.java
@@ -10,13 +10,13 @@
 // for [databind#1106]
 public class ScalarCoercionTest extends BaseMapTest
 {
-    private final ObjectMapper COERCING_MAPPER = new ObjectMapper(); {
-        COERCING_MAPPER.enable(MapperFeature.ALLOW_COERCION_OF_SCALARS);
-    }
+    private final ObjectMapper COERCING_MAPPER = jsonMapperBuilder()
+            .enable(MapperFeature.ALLOW_COERCION_OF_SCALARS)
+            .build();
 
-    private final ObjectMapper NOT_COERCING_MAPPER = new ObjectMapper(); {
-        NOT_COERCING_MAPPER.disable(MapperFeature.ALLOW_COERCION_OF_SCALARS);
-    }
+    private final ObjectMapper NOT_COERCING_MAPPER = jsonMapperBuilder()
+            .disable(MapperFeature.ALLOW_COERCION_OF_SCALARS)
+            .build();
 
     /*
     /**********************************************************
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/TestPOJOAsArrayPolymorphic.java b/src/test/java/com/fasterxml/jackson/databind/struct/TestPOJOAsArrayPolymorphic.java
new file mode 100644
index 0000000..bbb9bcf
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/TestPOJOAsArrayPolymorphic.java
@@ -0,0 +1,38 @@
+package com.fasterxml.jackson.databind.struct;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class TestPOJOAsArrayPolymorphic extends BaseMapTest
+{
+    // [databind#2077]
+    @JsonTypeInfo(
+        use = JsonTypeInfo.Id.NAME,
+        include = JsonTypeInfo.As.WRAPPER_ARRAY)  // Both WRAPPER_OBJECT and WRAPPER_ARRAY cause the same problem
+    @JsonSubTypes({
+        @JsonSubTypes.Type(value = DirectLayout.class, name = "Direct"),
+    })
+    public interface Layout {
+    }
+
+    @JsonFormat(shape=JsonFormat.Shape.ARRAY)
+    public static class DirectLayout implements Layout {
+    }
+
+    private final ObjectMapper MAPPER = sharedMapper();
+
+    // [databind#2077]
+    public void testPolymorphicAsArray() throws Exception
+    {
+        // 20-Sep-2019, taut: this fails to add shape information, due to class annotations
+        //   not being checked due to missing `property` for `createContextual()`
+
+        String json = MAPPER.writeValueAsString(new DirectLayout());
+
+        Layout instance = MAPPER.readValue(json, Layout.class);
+        assertNotNull(instance);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapped.java b/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapped.java
index b799172..84249a7 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapped.java
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/TestUnwrapped.java
@@ -238,8 +238,9 @@
     // [databind#1493]: case-insensitive handling
     public void testCaseInsensitiveUnwrap() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
+                .build();
         Person p = mapper.readValue("{ }", Person.class);
         assertNotNull(p);
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/UnwrappedWithView1559Test.java b/src/test/java/com/fasterxml/jackson/databind/struct/UnwrappedWithView1559Test.java
index b23cf71..bee6868 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/UnwrappedWithView1559Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/UnwrappedWithView1559Test.java
@@ -25,11 +25,13 @@
 
     // for [databind#1559]
     public void testCanSerializeSimpleWithDefaultView() throws Exception {
-        String json = new ObjectMapper().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false)
+        String json = jsonMapperBuilder().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false)
+                .build()
                 .writeValueAsString(new Health());
         assertEquals(aposToQuotes("{}"), json);
         // and just in case this, although won't matter wrt output
-        json = new ObjectMapper().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true)
+        json = jsonMapperBuilder().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true)
+                .build()
                 .writeValueAsString(new Health());
         assertEquals(aposToQuotes("{}"), json);
     }
diff --git a/src/test/java/com/fasterxml/jackson/databind/BrokenStringReader.java b/src/test/java/com/fasterxml/jackson/databind/testutil/BrokenStringReader.java
similarity index 90%
rename from src/test/java/com/fasterxml/jackson/databind/BrokenStringReader.java
rename to src/test/java/com/fasterxml/jackson/databind/testutil/BrokenStringReader.java
index a4d1a92..ca20aed 100644
--- a/src/test/java/com/fasterxml/jackson/databind/BrokenStringReader.java
+++ b/src/test/java/com/fasterxml/jackson/databind/testutil/BrokenStringReader.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.databind;
+package com.fasterxml.jackson.databind.testutil;
 
 import java.io.*;
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/BrokenStringWriter.java b/src/test/java/com/fasterxml/jackson/databind/testutil/BrokenStringWriter.java
similarity index 92%
rename from src/test/java/com/fasterxml/jackson/databind/BrokenStringWriter.java
rename to src/test/java/com/fasterxml/jackson/databind/testutil/BrokenStringWriter.java
index 93bd68a..0362332 100644
--- a/src/test/java/com/fasterxml/jackson/databind/BrokenStringWriter.java
+++ b/src/test/java/com/fasterxml/jackson/databind/testutil/BrokenStringWriter.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.databind;
+package com.fasterxml.jackson.databind.testutil;
 
 import java.io.*;
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/MediaItem.java b/src/test/java/com/fasterxml/jackson/databind/testutil/MediaItem.java
similarity index 98%
rename from src/test/java/com/fasterxml/jackson/databind/MediaItem.java
rename to src/test/java/com/fasterxml/jackson/databind/testutil/MediaItem.java
index 451429e..a619ce8 100644
--- a/src/test/java/com/fasterxml/jackson/databind/MediaItem.java
+++ b/src/test/java/com/fasterxml/jackson/databind/testutil/MediaItem.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.databind;
+package com.fasterxml.jackson.databind.testutil;
 
 import java.util.*;
 
diff --git a/src/test/java/com/fasterxml/jackson/databind/testutil/NoCheckSubTypeValidator.java b/src/test/java/com/fasterxml/jackson/databind/testutil/NoCheckSubTypeValidator.java
new file mode 100644
index 0000000..2ef64e2
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/testutil/NoCheckSubTypeValidator.java
@@ -0,0 +1,34 @@
+package com.fasterxml.jackson.databind.testutil;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.cfg.MapperConfig;
+import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
+
+/**
+ * Test-only {@link PolymorphicTypeValidator} used by tests that should not block
+ * use of any subtypes.
+ */
+public final class NoCheckSubTypeValidator
+    extends PolymorphicTypeValidator.Base
+{
+    private static final long serialVersionUID = 1L;
+
+    public final static NoCheckSubTypeValidator instance = new NoCheckSubTypeValidator(); 
+
+    @Override
+    public Validity validateBaseType(MapperConfig<?> config, JavaType baseType) {
+        return Validity.INDETERMINATE;
+    }
+
+    @Override
+    public Validity validateSubClassName(MapperConfig<?> config,
+            JavaType baseType, String subClassName) {
+        return Validity.ALLOWED;
+    }
+
+    @Override
+    public Validity validateSubType(MapperConfig<?> config, JavaType baseType,
+            JavaType subType) {
+        return Validity.ALLOWED;
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/NestedTypes1604Test.java b/src/test/java/com/fasterxml/jackson/databind/type/NestedTypes1604Test.java
index bf77b68..e6adf5c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/NestedTypes1604Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/NestedTypes1604Test.java
@@ -89,7 +89,7 @@
         }
     }
 
-    private final ObjectMapper objectMapper = newObjectMapper();
+    private final ObjectMapper objectMapper = newJsonMapper();
     
     public void testIssue1604Simple() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/RecursiveType1658Test.java b/src/test/java/com/fasterxml/jackson/databind/type/RecursiveType1658Test.java
index c211cd9..93249ed 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/RecursiveType1658Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/RecursiveType1658Test.java
@@ -3,6 +3,7 @@
 import java.util.*;
 
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.*;
 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
 import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
@@ -41,5 +42,13 @@
         Tree<?> tRead = mapper.readValue(res, Tree.class);
 
         assertNotNull(tRead);
+
+        // 30-Oct-2019, tatu: Let's actually verify that description will be safe to use, too
+        JavaType resolved = mapper.getTypeFactory()
+                .constructType(new TypeReference<Tree<String>> () { });
+        final String namePath = Tree.class.getName().replace('.', '/');
+        assertEquals("L"+namePath+";", resolved.getErasedSignature());
+        assertEquals("L"+namePath+"<Ljava/lang/String;L"+namePath+";>;",
+                resolved.getGenericSignature());
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
index 60bcee8..aba0a28 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
@@ -282,6 +282,7 @@
         JavaType t = tf.constructType(ArrayList.class);
         assertEquals(CollectionType.class, t.getClass());
         assertSame(ArrayList.class, t.getRawClass());
+        assertSame(Object.class, ((CollectionType) t).getContentType().getRawClass());
 
         // And then the proper way
         t = tf.constructType(new TypeReference<ArrayList<String>>() { });
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory1604.java b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory1604.java
index 4455547..9a3141c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory1604.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory1604.java
@@ -7,7 +7,7 @@
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.type.TypeFactory;
 
-// for [databind#1604]
+// for [databind#1604], [databind#2577]
 public class TestTypeFactory1604 extends BaseMapTest
 {
     static class Data1604<T> { }
@@ -22,6 +22,17 @@
 
     static class SneakyTwoParam1604<V,K> extends TwoParam1604<K,List<V>> { }
 
+    // [databind#2577]
+
+    static class Either<L, R> { }
+
+    static class EitherWrapper<L, R> {
+        public Either<L, R> value;
+    }
+
+    static class Left<V> extends Either<V, Void> { }
+    static class Right<V> extends Either<Void, V> { }
+
     public void testCustomTypesRefinedSimple()
     {
         TypeFactory tf = newTypeFactory();
@@ -108,4 +119,26 @@
             verifyException(e, "DataList1604");
         }
     }
+
+    // [databind#2577]
+    public void testResolveGenericPartialSubtypes()
+    {
+        TypeFactory tf = newTypeFactory();
+        JavaType base = tf.constructType(new TypeReference<Either<Object, Object>>() { });
+
+        JavaType lefty = tf.constructSpecializedType(base, Left.class);
+        assertEquals(Left.class, lefty.getRawClass());
+        JavaType[] params = tf.findTypeParameters(lefty, Either.class);
+        assertEquals(2, params.length);
+        assertEquals(Object.class, params[0].getRawClass());
+        assertEquals(Void.class, params[1].getRawClass());
+
+        JavaType righty = tf.constructSpecializedType(base, Right.class);
+        assertEquals(Right.class, righty.getRawClass());
+        
+        params = tf.findTypeParameters(righty, Either.class);
+        assertEquals(2, params.length);
+        assertEquals(Void.class, params[0].getRawClass());
+        assertEquals(Object.class, params[1].getRawClass());
+    }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/util/ClassUtilTest.java b/src/test/java/com/fasterxml/jackson/databind/util/ClassUtilTest.java
index 61faf3b..08153cb 100644
--- a/src/test/java/com/fasterxml/jackson/databind/util/ClassUtilTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/util/ClassUtilTest.java
@@ -2,7 +2,10 @@
 
 import java.util.*;
 
+import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.type.TypeFactory;
 import com.fasterxml.jackson.databind.util.ClassUtil;
 
 public class ClassUtilTest extends BaseMapTest
@@ -196,8 +199,14 @@
 
     public void testDescs()
     {
-        final String exp = "`java.lang.String`";
-        assertEquals(exp, ClassUtil.getClassDescription("foo"));
-        assertEquals(exp, ClassUtil.getClassDescription(String.class));
+        final String stringExp = "`java.lang.String`";
+        assertEquals(stringExp, ClassUtil.getClassDescription("foo"));
+        assertEquals(stringExp, ClassUtil.getClassDescription(String.class));
+        final JavaType stringType = TypeFactory.defaultInstance().constructType(String.class);
+        assertEquals(stringExp, ClassUtil.getTypeDescription(stringType));
+        final JavaType mapType = TypeFactory.defaultInstance().constructType(
+                new TypeReference<Map<String, Integer>>() { });
+        assertEquals("`java.util.Map<java.lang.String,java.lang.Integer>`",
+                ClassUtil.getTypeDescription(mapType));
     }
 }
diff --git a/src/test/java/com/fasterxml/jackson/databind/util/ISO8601DateFormatTest.java b/src/test/java/com/fasterxml/jackson/databind/util/ISO8601DateFormatTest.java
index 20e9412..8c3ff9f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/util/ISO8601DateFormatTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/util/ISO8601DateFormatTest.java
@@ -3,7 +3,6 @@
 import java.text.DateFormat;
 import java.util.*;
 
-
 import com.fasterxml.jackson.databind.BaseMapTest;
 
 @SuppressWarnings("deprecation")
diff --git a/src/test/java/com/fasterxml/jackson/databind/util/TestObjectBuffer.java b/src/test/java/com/fasterxml/jackson/databind/util/TestObjectBuffer.java
index bdaba8f..8d1a4cc 100644
--- a/src/test/java/com/fasterxml/jackson/databind/util/TestObjectBuffer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/util/TestObjectBuffer.java
@@ -29,7 +29,7 @@
     private void _testObjectBuffer(Class<?> clz)
     {
         int[] SIZES = new int[] {
-            3, 19, 99, 1007, 79000, 256001
+            3, 19, 99, 1007, 19999, 99001
         };
 
         // Let's loop separately for reused instance, new instance
diff --git a/src/test/java/com/fasterxml/jackson/databind/util/TestTokenBuffer.java b/src/test/java/com/fasterxml/jackson/databind/util/TestTokenBuffer.java
index e785be7..297313e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/util/TestTokenBuffer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/util/TestTokenBuffer.java
@@ -7,6 +7,7 @@
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.core.JsonParser.NumberType;
+import com.fasterxml.jackson.core.exc.InputCoercionException;
 import com.fasterxml.jackson.core.io.SerializedString;
 import com.fasterxml.jackson.core.util.JsonParserSequence;
 
@@ -39,11 +40,11 @@
         buf.setCodec(null);
         assertNull(buf.getCodec());
 
-        assertFalse(buf.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII));
-        buf.enable(JsonGenerator.Feature.ESCAPE_NON_ASCII);
-        assertTrue(buf.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII));
-        buf.disable(JsonGenerator.Feature.ESCAPE_NON_ASCII);
-        assertFalse(buf.isEnabled(JsonGenerator.Feature.ESCAPE_NON_ASCII));
+        assertFalse(buf.isEnabled(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN));
+        buf.enable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
+        assertTrue(buf.isEnabled(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN));
+        buf.disable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
+        assertFalse(buf.isEnabled(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN));
 
         buf.close();
         assertTrue(buf.isClosed());
@@ -138,7 +139,7 @@
                 try {
                     p.getIntValue();
                     fail("Expected failure for `int` overflow");
-                } catch (JsonParseException e) {
+                } catch (InputCoercionException e) {
                     verifyException(e, "Numeric value ("+big+") out of range of int");
                 }
             }
@@ -153,7 +154,7 @@
                 try {
                     p.getIntValue();
                     fail("Expected failure for `int` overflow");
-                } catch (JsonParseException e) {
+                } catch (InputCoercionException e) {
                     verifyException(e, "Numeric value ("+big+") out of range of int");
                 }
             }
@@ -171,7 +172,7 @@
                 try {
                     p.getLongValue();
                     fail("Expected failure for `long` overflow");
-                } catch (JsonParseException e) {
+                } catch (InputCoercionException e) {
                     verifyException(e, "Numeric value ("+big+") out of range of long");
                 }
             }
diff --git a/src/test/java/com/fasterxml/jackson/databind/views/TestViewDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/views/TestViewDeserialization.java
index fd81d13..ac0602f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/views/TestViewDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/views/TestViewDeserialization.java
@@ -103,8 +103,9 @@
         assertEquals(3, bean.a);
         assertEquals(9, bean.b);
 
-        ObjectMapper myMapper = new ObjectMapper();
-        myMapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
+        ObjectMapper myMapper = jsonMapperBuilder()
+                .disable(MapperFeature.DEFAULT_VIEW_INCLUSION)
+                .build();
 
         // but with, say, AA, will not get 'b'
         bean = myMapper.readerWithView(ViewAA.class)
diff --git a/src/test/java/com/fasterxml/jackson/databind/views/TestViewSerialization.java b/src/test/java/com/fasterxml/jackson/databind/views/TestViewSerialization.java
index 79dfee0..5cccb66 100644
--- a/src/test/java/com/fasterxml/jackson/databind/views/TestViewSerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/views/TestViewSerialization.java
@@ -140,8 +140,9 @@
         assertEquals("2", map.get("b"));
 
         // but can also change (but not necessarily on the fly...)
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false)
+                .build();
 
         // with this setting, only explicit inclusions count:
         json = mapper.writerWithView(ViewA.class).writeValueAsString(bean);
diff --git a/src/test/java/com/fasterxml/jackson/databind/views/TestViewsSerialization2.java b/src/test/java/com/fasterxml/jackson/databind/views/TestViewsSerialization2.java
index 96b11cf..382947c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/views/TestViewsSerialization2.java
+++ b/src/test/java/com/fasterxml/jackson/databind/views/TestViewsSerialization2.java
@@ -143,10 +143,11 @@
 
     private ObjectMapper createMapper()
     {
-        ObjectMapper mapper = newObjectMapper();
-        mapper.configure( SerializationFeature.FAIL_ON_EMPTY_BEANS, false );
-        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL );
-        mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false );
+        ObjectMapper mapper = jsonMapperBuilder()
+                .configure( SerializationFeature.FAIL_ON_EMPTY_BEANS, false )
+                .serializationInclusion(JsonInclude.Include.NON_NULL )
+                .configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false )
+                .build();
         return mapper;
     }
 
diff --git a/src/test/java/com/fasterxml/jackson/failing/CreatorFallback2438Test.java b/src/test/java/com/fasterxml/jackson/failing/CreatorFallback2438Test.java
new file mode 100644
index 0000000..61b5861
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/CreatorFallback2438Test.java
@@ -0,0 +1,38 @@
+package com.fasterxml.jackson.failing;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import com.fasterxml.jackson.databind.*;
+
+// for [databind#2438]
+public class CreatorFallback2438Test extends BaseMapTest
+{
+    static class Creator2438 {
+        int value;
+
+        @JsonCreator
+        public Creator2438(@JsonProperty("value") int v) {
+//System.err.println("DEBUG: value set as "+v);
+            value = v;
+        }
+
+        public int accessValue() { return value; }
+
+        // This or visible (public) setter are required to show the issue
+        public void setValue(int v) { value = v; }
+    }
+
+    private final ObjectMapper MAPPER = newJsonMapper();
+
+    public void testCreator2438() throws Exception
+    {
+        // note: by default, duplicate-detection not enabled, so should not
+        // throw exception. But should also NOT apply second value because
+        // field/setter should NOT be used in case there is already creator property
+        Creator2438 value = MAPPER.readValue(aposToQuotes(
+                "{'value':1, 'value':2}"),
+                Creator2438.class);
+        assertEquals(1, value.accessValue());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/DefaultTypingOverride1391Test.java b/src/test/java/com/fasterxml/jackson/failing/DefaultTypingOverride1391Test.java
index 40d4a31..89b82aa 100644
--- a/src/test/java/com/fasterxml/jackson/failing/DefaultTypingOverride1391Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/DefaultTypingOverride1391Test.java
@@ -4,6 +4,8 @@
 
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 // for [databind#1391]: should allow disabling of default typing
 // via explicit {@link JsonTypeInfo}
@@ -20,9 +22,11 @@
 
     public void testCollectionWithOverride() throws Exception
     {
-        final ObjectMapper mapper = new ObjectMapper()
-            .enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE,
-                    "$type");
+        final ObjectMapper mapper = JsonMapper.builder()
+            .activateDefaultTypingAsProperty(NoCheckSubTypeValidator.instance,
+                    ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE,
+                    "$type")
+            .build();
         String json = mapper.writeValueAsString(new ListWrapper());
         assertEquals(aposToQuotes("{'stuff':[]}"), json);
     }
diff --git a/src/test/java/com/fasterxml/jackson/failing/DelegatingCreatorWithAbstractProp2252Test.java b/src/test/java/com/fasterxml/jackson/failing/DelegatingCreatorWithAbstractProp2252Test.java
index d0d26f2..fea2e44 100644
--- a/src/test/java/com/fasterxml/jackson/failing/DelegatingCreatorWithAbstractProp2252Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/DelegatingCreatorWithAbstractProp2252Test.java
@@ -26,7 +26,7 @@
     @SuppressWarnings("serial")
     static abstract class MyAbstractList extends ArrayList<String> { }
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     // loosely based on [databind#2251], in which delegating creator is used, but
     // theoretically necessary type for setter can cause issues -- shouldn't, as no
diff --git a/src/test/java/com/fasterxml/jackson/failing/EnumAsIndexMapKey1877Test.java b/src/test/java/com/fasterxml/jackson/failing/EnumAsIndexMapKey1877Test.java
deleted file mode 100644
index ebe12d3..0000000
--- a/src/test/java/com/fasterxml/jackson/failing/EnumAsIndexMapKey1877Test.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.fasterxml.jackson.failing;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.exc.InvalidFormatException;
-
-public class EnumAsIndexMapKey1877Test extends BaseMapTest
-{
-    public enum Type {
-        ANY,
-        OTHER
-    }
-
-    static class Container {
-        private Type simpleType;
-        private Map<Type, String> map;
-
-        public Type getSimpleType() {
-            return simpleType;
-        }
-
-        public void setSimpleType(Type simpleType) {
-            this.simpleType= simpleType;
-        }
-
-        public Map<Type, String> getMap() {
-            return map;
-        }
-
-        public void setMap(Map<Type, String> map) {
-            this.map = map;
-        }
-    }
-    // [databind#1877]
-    public void testEnumAsIndexMapKey() throws Exception
-    {
-        ObjectMapper mapper = newObjectMapper();
-
-        Map<Type, String> map = new HashMap<>();
-        map.put(Type.OTHER, "hello world");
-        Container container = new Container();
-        container.setSimpleType(Type.ANY);
-        container.setMap(map);
-
-        String json = mapper
-                .writer().with(SerializationFeature.WRITE_ENUMS_USING_INDEX)
-                .writeValueAsString(container);
-
-        Container cont;
-        try {
-            cont = mapper
-                .readerFor(Container.class)
-                .readValue(json);
-        } catch (JsonMappingException e) {
-            throw e;
-        }
-        assertNotNull(cont);
-        assertEquals(1, container.getMap().size());
-        InvalidFormatException foo = null;
-
-        assertSame(Type.OTHER, container.getMap().keySet().iterator().next());
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/failing/ExternalTypeIdWithUnwrapped2039Test.java b/src/test/java/com/fasterxml/jackson/failing/ExternalTypeIdWithUnwrapped2039Test.java
index a81f6ab..182caa7 100644
--- a/src/test/java/com/fasterxml/jackson/failing/ExternalTypeIdWithUnwrapped2039Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/ExternalTypeIdWithUnwrapped2039Test.java
@@ -36,7 +36,7 @@
     
     public void testExternalWithUnwrapped2039() throws Exception
     {
-        final ObjectMapper mapper = newObjectMapper();
+        final ObjectMapper mapper = newJsonMapper();
 
         final String json = aposToQuotes("{\n"
                 +"'text': 'this is A',\n"
diff --git a/src/test/java/com/fasterxml/jackson/failing/ImplicitParamsForCreator806Test.java b/src/test/java/com/fasterxml/jackson/failing/ImplicitParamsForCreator806Test.java
index 890f576..d6d15fc 100644
--- a/src/test/java/com/fasterxml/jackson/failing/ImplicitParamsForCreator806Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/ImplicitParamsForCreator806Test.java
@@ -37,7 +37,7 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper()
+    private final ObjectMapper MAPPER = newJsonMapper()
             .setAnnotationIntrospector(new MyParamIntrospector())
             .setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
             ;
diff --git a/src/test/java/com/fasterxml/jackson/failing/InnerClassNonStaticCore384Test.java b/src/test/java/com/fasterxml/jackson/failing/InnerClassNonStaticCore384Test.java
index 0ef5e76..1390a65 100644
--- a/src/test/java/com/fasterxml/jackson/failing/InnerClassNonStaticCore384Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/InnerClassNonStaticCore384Test.java
@@ -10,6 +10,7 @@
 import static org.junit.Assert.assertThat;
 
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 // see [https://github.com/FasterXML/jackson-core/issues/384]: most likely
 // can not be fixed, but could we improve error message to indicate issue
@@ -170,8 +171,9 @@
      */
 
     public void testHierarchy() throws IOException {
-        ObjectMapper mapper = new ObjectMapper();
-        mapper.enableDefaultTyping();
+        ObjectMapper mapper = jsonMapperBuilder()
+                .activateDefaultTyping(NoCheckSubTypeValidator.instance)
+                .build();
 
         Fleet fleet = initVehicle();
 
diff --git a/src/test/java/com/fasterxml/jackson/failing/JacksonInject2465Test.java b/src/test/java/com/fasterxml/jackson/failing/JacksonInject2465Test.java
new file mode 100644
index 0000000..d92e01b
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/JacksonInject2465Test.java
@@ -0,0 +1,53 @@
+package com.fasterxml.jackson.failing;
+
+import com.fasterxml.jackson.annotation.JacksonInject;
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonSetter;
+import com.fasterxml.jackson.annotation.Nulls;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+
+import com.fasterxml.jackson.databind.*;
+
+public class JacksonInject2465Test extends BaseMapTest
+{
+    public static final class TestCase2465 {
+        private final Internal2465 str;
+        private final int id;
+
+        @JsonCreator
+        public TestCase2465(@JacksonInject Internal2465 str, @JsonProperty("id") int id) {
+            this.str = str;
+            this.id = id;
+        }
+
+        public int fetchId() { return id; }
+        public Internal2465 fetchInternal() { return str; }
+    }
+
+    public static final class Internal2465 {
+        final String val;
+
+        public Internal2465(String val) {
+            this.val = val;
+        }
+    }
+
+    // [databind#2465]
+    public void testInjectWithCreator() throws Exception
+    {
+        ObjectMapper mapper = jsonMapperBuilder()
+                .defaultSetterInfo(JsonSetter.Value.construct(Nulls.AS_EMPTY, Nulls.AS_EMPTY))
+                .build();
+        mapper.setVisibility(mapper.getVisibilityChecker().withVisibility(PropertyAccessor.FIELD,
+                JsonAutoDetect.Visibility.ANY));
+
+        final Internal2465 injected = new Internal2465("test");
+        TestCase2465 o = mapper.readerFor(TestCase2465.class)
+                .with(new InjectableValues.Std().addValue(Internal2465.class, injected))
+                .readValue("{\"id\":3}");
+        assertEquals(3, o.fetchId());
+        assertNotNull(o.fetchInternal());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/JsonSetter2572Test.java b/src/test/java/com/fasterxml/jackson/failing/JsonSetter2572Test.java
new file mode 100644
index 0000000..ac3c254
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/JsonSetter2572Test.java
@@ -0,0 +1,50 @@
+package com.fasterxml.jackson.failing;
+
+import java.util.Objects;
+
+import com.fasterxml.jackson.annotation.*;
+
+import com.fasterxml.jackson.databind.*;
+
+// Not sure if [databind#2572] is actually a bug, but behavior in 2.9 was
+// different from 2.10 in that no exception thrown and databind quietly just
+// left `null` for Beans as `null` even if "EMPTY" was indicated by configuration.
+public class JsonSetter2572Test extends BaseMapTest
+{
+    static class Outer {
+        @JsonProperty("inner")
+        final Inner inner;
+
+        @JsonCreator
+        public Outer(@JsonProperty("inner") Inner inner) {
+            this.inner = Objects.requireNonNull(inner, "inner");
+        }
+    }
+
+    static class Inner {
+        @JsonProperty("field")
+        final String field;
+
+        @JsonCreator
+        public Inner(@JsonProperty("field") String field) {
+            this.field = field;
+        }
+    }
+
+    public void testSetterWithEmpty() throws Exception {
+        /*
+        ObjectMapper mapper = newObjectMapper()
+                .setDefaultSetterInfo(JsonSetter.Value.construct(Nulls.AS_EMPTY, Nulls.AS_EMPTY));
+                */
+        ObjectMapper mapper = jsonMapperBuilder()
+                .defaultSetterInfo(JsonSetter.Value.construct(Nulls.AS_EMPTY, Nulls.AS_EMPTY))
+                .build();
+
+        String json = mapper.writeValueAsString(new Outer(new Inner("inner")));
+        Outer result = mapper.readValue(json, Outer.class);
+        assertNotNull(result);
+        assertNotNull(result.inner); // converted to "empty" bean
+
+//System.err.println("Final -> "+mapper.writeValueAsString(result));        
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/NoTypeInfo1654Test.java b/src/test/java/com/fasterxml/jackson/failing/NoTypeInfo1654Test.java
index b39d44a..8de6249 100644
--- a/src/test/java/com/fasterxml/jackson/failing/NoTypeInfo1654Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/NoTypeInfo1654Test.java
@@ -52,7 +52,7 @@
     // [databind#1654]
     public void testNoTypeElementOverride() throws Exception
     {
-        final ObjectMapper mapper = newObjectMapper();
+        final ObjectMapper mapper = newJsonMapper();
 
         // First: regular typed case
         String json = mapper.writeValueAsString(new Value1654TypedContainer(
diff --git a/src/test/java/com/fasterxml/jackson/failing/NullConversionWithCreatorTest.java b/src/test/java/com/fasterxml/jackson/failing/NullConversionWithCreatorTest.java
deleted file mode 100644
index 39e4043..0000000
--- a/src/test/java/com/fasterxml/jackson/failing/NullConversionWithCreatorTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.fasterxml.jackson.failing;
-
-import com.fasterxml.jackson.annotation.*;
-
-import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.exc.InvalidNullException;
-
-public class NullConversionWithCreatorTest extends BaseMapTest
-{
-    // [databind#2024]
-    static class EmptyFromNullViaCreator {
-        @JsonSetter(nulls=Nulls.AS_EMPTY)
-        Point p;
-
-        @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
-        public EmptyFromNullViaCreator(@JsonSetter(nulls=Nulls.AS_EMPTY)
-            @JsonProperty("p") Point p)
-        {
-            this.p = p;
-        }
-    }
-
-    static class FailFromNullViaCreator {
-        @JsonSetter(nulls=Nulls.AS_EMPTY)
-        Point p;
-
-        @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
-        public FailFromNullViaCreator(@JsonSetter(nulls=Nulls.FAIL)
-            @JsonProperty("p") Point p)
-        {
-            this.p = p;
-        }
-    }
-
-    /*
-    /**********************************************************
-    /* Test methods
-    /**********************************************************
-     */
-    private final ObjectMapper MAPPER = newObjectMapper();
-
-    // [databind#2024]
-    public void testEmptyFromNullViaCreator() throws Exception
-    {
-        EmptyFromNullViaCreator result = MAPPER.readValue(aposToQuotes("{'p':null}"),
-                EmptyFromNullViaCreator.class);
-        assertNotNull(result);
-        assertNotNull(result.p);
-    }
-
-    // [databind#2024]
-    public void testFailForNullViaCreator() throws Exception
-    {
-        try {
-            /*FailFromNullViaCreator result =*/ MAPPER.readValue(aposToQuotes("{'p':null}"),
-                    FailFromNullViaCreator.class);
-            fail("Should not pass");
-        } catch (InvalidNullException e) {
-            verifyException(e, "property \"p\"");
-        }
-    }
-}
diff --git a/src/test/java/com/fasterxml/jackson/failing/NumberNodes1770Test.java b/src/test/java/com/fasterxml/jackson/failing/NumberNodes1770Test.java
index 93e3602..bec4231 100644
--- a/src/test/java/com/fasterxml/jackson/failing/NumberNodes1770Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/NumberNodes1770Test.java
@@ -8,7 +8,7 @@
  */
 public class NumberNodes1770Test extends BaseMapTest
 {
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     // Related to [databind#1770]
     public void testBigDecimalCoercion() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/failing/ObjectIdWithBuilder1496Test.java b/src/test/java/com/fasterxml/jackson/failing/ObjectIdWithBuilder1496Test.java
index 8338ed2..fea7b4f 100644
--- a/src/test/java/com/fasterxml/jackson/failing/ObjectIdWithBuilder1496Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/ObjectIdWithBuilder1496Test.java
@@ -57,7 +57,7 @@
     /**********************************************************
      */
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
     
     public void testBuilderId1496() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/failing/ParsingContext2525Test.java b/src/test/java/com/fasterxml/jackson/failing/ParsingContext2525Test.java
new file mode 100644
index 0000000..9f98853
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/ParsingContext2525Test.java
@@ -0,0 +1,237 @@
+package com.fasterxml.jackson.failing;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonPointer;
+import com.fasterxml.jackson.core.JsonToken;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.util.TokenBuffer;
+
+public class ParsingContext2525Test extends BaseMapTest
+{
+    private final ObjectMapper MAPPER = sharedMapper();
+
+    private final String MINIMAL_ARRAY_DOC = "[ 42 ]";
+    
+    private final String MINIMAL_OBJECT_DOC = "{\"answer\" : 42 }";
+
+    private final String FULL_DOC = aposToQuotes("{'a':123,'array':[1,2,[3],5,{'obInArray':4}],"
+            +"'ob':{'first':[false,true],'second':{'sub':37}},'b':true}");
+
+    /*
+    /**********************************************************************
+    /* Baseline sanity check first
+    /**********************************************************************
+     */
+
+    public void testAllWithRegularParser() throws Exception
+    {
+        try (JsonParser p = MAPPER.getFactory().createParser(MINIMAL_ARRAY_DOC)) {
+            _testSimpleArrayUsingPathAsPointer(p);
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(MINIMAL_OBJECT_DOC)) {
+            _testSimpleObjectUsingPathAsPointer(p);
+        }
+        try (JsonParser p = MAPPER.getFactory().createParser(FULL_DOC)) {
+            _testFullDocUsingPathAsPointer(p);
+        }
+    }
+
+    /*
+    /**********************************************************************
+    /* Then TokenBuffer-backed tests
+    /**********************************************************************
+     */
+
+    public void testSimpleArrayWithBuffer() throws Exception
+    {
+        try (TokenBuffer buf = _readAsTokenBuffer(MINIMAL_ARRAY_DOC)) {
+            _testSimpleArrayUsingPathAsPointer(buf.asParser());
+        }
+    }
+
+    public void testSimpleObjectWithBuffer() throws Exception
+    {
+        try (TokenBuffer buf = _readAsTokenBuffer(MINIMAL_OBJECT_DOC)) {
+            _testSimpleObjectUsingPathAsPointer(buf.asParser());
+        }
+    }
+
+    public void testFullDocWithBuffer() throws Exception
+    {
+        try (TokenBuffer buf = _readAsTokenBuffer(FULL_DOC)) {
+            _testFullDocUsingPathAsPointer(buf.asParser());
+        }
+    }
+
+    private TokenBuffer _readAsTokenBuffer(String doc) throws IOException
+    {
+        try (JsonParser p = MAPPER.getFactory().createParser(doc)) {
+            p.nextToken();
+            return TokenBuffer.asCopyOfValue(p)
+                    .overrideParentContext(null);
+        }
+    }
+
+    /*
+    /**********************************************************************
+    /* And Tree-backed tests
+    /**********************************************************************
+     */
+
+    public void testSimpleArrayWithTree() throws Exception
+    {
+        JsonNode root = MAPPER.readTree(MINIMAL_ARRAY_DOC);
+        try (JsonParser p = root.traverse(null)) {
+            _testSimpleArrayUsingPathAsPointer(p);
+        }
+    }
+
+    public void testSimpleObjectWithTree() throws Exception
+    {
+        JsonNode root = MAPPER.readTree(MINIMAL_OBJECT_DOC);
+        try (JsonParser p = root.traverse(null)) {
+            _testSimpleObjectUsingPathAsPointer(p);
+        }
+    }
+
+    public void testFullDocWithTree() throws Exception
+    {
+        JsonNode root = MAPPER.readTree(FULL_DOC);
+        try (JsonParser p = root.traverse(null)) {
+            _testFullDocUsingPathAsPointer(p);
+        }
+    }
+
+    /*
+    /**********************************************************************
+    /* Shared helper methods
+    /**********************************************************************
+     */
+    
+    private void _testSimpleArrayUsingPathAsPointer(JsonParser p) throws Exception
+    {
+        assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer());
+        assertTrue(p.getParsingContext().inRoot());
+
+        assertToken(JsonToken.START_ARRAY, p.nextToken());
+        assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer());
+        assertTrue(p.getParsingContext().inArray());
+
+        assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
+        assertEquals("/0", p.getParsingContext().pathAsPointer().toString());
+        
+        assertToken(JsonToken.END_ARRAY, p.nextToken());
+        assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer());
+        assertTrue(p.getParsingContext().inRoot());
+
+        assertNull(p.nextToken());
+    }
+
+    private void _testSimpleObjectUsingPathAsPointer(JsonParser p) throws Exception
+    {
+        assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer());
+        assertTrue(p.getParsingContext().inRoot());
+
+        assertToken(JsonToken.START_OBJECT, p.nextToken());
+        assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer());
+        assertTrue(p.getParsingContext().inObject());
+
+        assertToken(JsonToken.FIELD_NAME, p.nextToken());
+        assertEquals("/answer", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
+        assertEquals(42, p.getIntValue());
+        assertEquals("/answer", p.getParsingContext().pathAsPointer().toString());
+        
+        assertToken(JsonToken.END_OBJECT, p.nextToken());
+        assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer());
+        assertTrue(p.getParsingContext().inRoot());
+
+        assertNull(p.nextToken());
+    }
+    
+    private void _testFullDocUsingPathAsPointer(JsonParser p) throws Exception
+    {
+        // by default should just get "empty"
+        assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer());
+        assertTrue(p.getParsingContext().inRoot());
+
+        // let's just traverse, then:
+        assertToken(JsonToken.START_OBJECT, p.nextToken());
+        assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer());
+        assertTrue(p.getParsingContext().inObject());
+
+        assertToken(JsonToken.FIELD_NAME, p.nextToken()); // a
+        assertEquals("/a", p.getParsingContext().pathAsPointer().toString());
+
+        assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
+        assertEquals("/a", p.getParsingContext().pathAsPointer().toString());
+
+        assertToken(JsonToken.FIELD_NAME, p.nextToken()); // array
+        assertEquals("/array", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.START_ARRAY, p.nextToken());
+        assertEquals("/array", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); // 1
+        assertEquals("/array/0", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); // 2
+        assertEquals("/array/1", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.START_ARRAY, p.nextToken());
+        assertEquals("/array/2", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); // 3
+        assertEquals("/array/2/0", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.END_ARRAY, p.nextToken());
+        assertEquals("/array/2", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); // 5
+        assertEquals("/array/3", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.START_OBJECT, p.nextToken());
+        assertEquals("/array/4", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.FIELD_NAME, p.nextToken()); // obInArray
+        assertEquals("/array/4/obInArray", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); // 4
+        assertEquals("/array/4/obInArray", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.END_OBJECT, p.nextToken());
+        assertEquals("/array/4", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.END_ARRAY, p.nextToken()); // /array
+        assertEquals("/array", p.getParsingContext().pathAsPointer().toString());
+
+        assertToken(JsonToken.FIELD_NAME, p.nextToken()); // ob
+        assertEquals("/ob", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.START_OBJECT, p.nextToken());
+        assertEquals("/ob", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.FIELD_NAME, p.nextToken()); // first
+        assertEquals("/ob/first", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.START_ARRAY, p.nextToken());
+        assertEquals("/ob/first", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.VALUE_FALSE, p.nextToken());
+        assertEquals("/ob/first/0", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.VALUE_TRUE, p.nextToken());
+        assertEquals("/ob/first/1", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.END_ARRAY, p.nextToken());
+        assertEquals("/ob/first", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.FIELD_NAME, p.nextToken()); // second
+        assertEquals("/ob/second", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.START_OBJECT, p.nextToken());
+        assertEquals("/ob/second", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.FIELD_NAME, p.nextToken()); // sub
+        assertEquals("/ob/second/sub", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); // 37
+        assertEquals("/ob/second/sub", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.END_OBJECT, p.nextToken());
+        assertEquals("/ob/second", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.END_OBJECT, p.nextToken()); // /ob
+        assertEquals("/ob", p.getParsingContext().pathAsPointer().toString());
+
+        assertToken(JsonToken.FIELD_NAME, p.nextToken()); // b
+        assertEquals("/b", p.getParsingContext().pathAsPointer().toString());
+        assertToken(JsonToken.VALUE_TRUE, p.nextToken());
+        assertEquals("/b", p.getParsingContext().pathAsPointer().toString());
+
+        assertToken(JsonToken.END_OBJECT, p.nextToken());
+        assertSame(JsonPointer.empty(), p.getParsingContext().pathAsPointer());
+        assertTrue(p.getParsingContext().inRoot());
+
+        assertNull(p.nextToken());
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/RecursiveIgnoreProperties1755Test.java b/src/test/java/com/fasterxml/jackson/failing/RecursiveIgnoreProperties1755Test.java
index 9090429..55b9078 100644
--- a/src/test/java/com/fasterxml/jackson/failing/RecursiveIgnoreProperties1755Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/RecursiveIgnoreProperties1755Test.java
@@ -31,7 +31,7 @@
 
     // for [databind#1755]
 
-    private final ObjectMapper MAPPER = newObjectMapper();
+    private final ObjectMapper MAPPER = newJsonMapper();
 
     public void testRecursiveIgnore1755() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/failing/RequireSetterForGetter736Test.java b/src/test/java/com/fasterxml/jackson/failing/RequireSetterForGetter736Test.java
index b96f83c..881fc96 100644
--- a/src/test/java/com/fasterxml/jackson/failing/RequireSetterForGetter736Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/RequireSetterForGetter736Test.java
@@ -29,11 +29,12 @@
     // for [databind#736]
     public void testNeedForSetters() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper(); 
-        mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
-        mapper.setVisibility(PropertyAccessor.GETTER, Visibility.PUBLIC_ONLY);
-        mapper.setVisibility(PropertyAccessor.SETTER, Visibility.PUBLIC_ONLY);
-        mapper.enable(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS);
+        ObjectMapper mapper = jsonMapperBuilder()
+                .visibility(PropertyAccessor.ALL, Visibility.NONE)
+                .visibility(PropertyAccessor.GETTER, Visibility.PUBLIC_ONLY)
+                .visibility(PropertyAccessor.SETTER, Visibility.PUBLIC_ONLY)
+                .enable(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS)
+                .build();
         DataB dataB = new DataB();
 
         String json = mapper.writeValueAsString(dataB);
diff --git a/src/test/java/com/fasterxml/jackson/failing/SingleArgCreator2305Test.java b/src/test/java/com/fasterxml/jackson/failing/SingleArgCreator2305Test.java
new file mode 100644
index 0000000..6bb3ebe
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/SingleArgCreator2305Test.java
@@ -0,0 +1,92 @@
+package com.fasterxml.jackson.failing;
+
+import java.util.*;
+
+import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.databind.*;
+
+// For [databind#2305]: regression/unintentional change, but not sure if behavior
+// should or should not be changed.
+public class SingleArgCreator2305Test extends BaseMapTest
+{
+    // [databind#2305]
+    static class ExportRequest2305 {
+        private final String heading;
+        private List<Format2305> fields;
+
+        @JsonCreator
+        public ExportRequest2305(@JsonProperty("fields") List<Format2305> fields,
+                             @JsonProperty("heading") String heading) {
+            this.fields = fields;
+            this.heading = heading;
+        }
+
+        public List<Format2305> getFields() { return fields; }
+        public String getHeading() { return heading; }
+
+        public static class Format2305 {
+            private final Object value;
+            private final String pattern;
+            private final String currency;
+            private int maxChars;
+            private Double proportion;
+
+            public Format2305(String value) { this(value, "", null); }
+
+            @JsonCreator
+            public Format2305(@JsonProperty("value") Object value,
+                          @JsonProperty("pattern") String pattern,
+                          @JsonProperty("currency") String currency) {
+                this.value = (value == null ? "" : value);
+                this.currency = currency;
+                this.pattern = pattern;
+            }
+
+            public String getValue() {
+                return value == null ? null : value.toString();
+            }
+
+            @JsonIgnore
+            public String getPattern() {
+                return pattern;
+            }
+
+            @JsonIgnore
+            public String getCurrency() {
+                return currency;
+            }
+
+            public int getMaxChars() {
+                return maxChars;
+            }
+
+            public void setMaxChars(int maxChars) {
+                this.maxChars = maxChars;
+            }
+
+            public Double getProportion() {
+                return proportion;
+            }
+
+            public void setProportion(Double proportion) {
+                this.proportion = proportion;
+            }
+        }
+    }
+
+    /*
+    /**********************************************************
+    /* Test methods
+    /**********************************************************
+     */
+
+    private final ObjectMapper MAPPER = objectMapper();
+
+    // [databind#2305]
+    public void testIssue2305() throws Exception
+    {
+        Map<?,?> result = MAPPER.readValue("{\"heading\": \"TEST\",\"fields\":[\"field1\",\"field2\"] }", Map.class);
+        ExportRequest2305 exportReqt = MAPPER.convertValue(result, ExportRequest2305.class);
+        assertNotNull(exportReqt);
+    }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/StaticTyping1515Test.java b/src/test/java/com/fasterxml/jackson/failing/StaticTyping1515Test.java
index 7a1a554..7cc8fbb 100644
--- a/src/test/java/com/fasterxml/jackson/failing/StaticTyping1515Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/StaticTyping1515Test.java
@@ -58,10 +58,9 @@
     /**********************************************************
      */
 
-    private final ObjectMapper STAT_MAPPER = newObjectMapper();
-    {
-        STAT_MAPPER.enable(MapperFeature.USE_STATIC_TYPING);
-    }
+    private final ObjectMapper STAT_MAPPER = jsonMapperBuilder()
+            .enable(MapperFeature.USE_STATIC_TYPING)
+            .build();
 
     public void testStaticTypingForProperties() throws Exception
     {
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithUnwrapping1298.java b/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithUnwrapping1298.java
index d039140..25261f3 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithUnwrapping1298.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestObjectIdWithUnwrapping1298.java
@@ -5,9 +5,10 @@
 import java.util.List;
 
 import com.fasterxml.jackson.annotation.*;
-import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.StreamWriteFeature;
 import com.fasterxml.jackson.databind.BaseMapTest;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 
 // Test case for https://github.com/FasterXML/jackson-databind/issues/1298
 public class TestObjectIdWithUnwrapping1298 extends BaseMapTest
@@ -44,9 +45,10 @@
 
     public void testObjectIdWithRepeatedChild() throws Exception
     {
-        ObjectMapper mapper = new ObjectMapper();
-        // to keep output faithful to original, prevent auto-closing...
-        mapper.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
+        ObjectMapper mapper = JsonMapper.builder()
+                // to keep output faithful to original, prevent auto-closing...
+                .disable(StreamWriteFeature.AUTO_CLOSE_CONTENT)
+                .build();
 
         // Equivalent to Spring _embedded for Bean w/ List property
         ListOfParents parents = new ListOfParents();
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestSetterlessProperties501.java b/src/test/java/com/fasterxml/jackson/failing/TestSetterlessProperties501.java
index 8363e75..d29ddd1 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestSetterlessProperties501.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestSetterlessProperties501.java
@@ -5,6 +5,7 @@
 import com.fasterxml.jackson.annotation.*;
 
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
 
 public class TestSetterlessProperties501
     extends BaseMapTest
@@ -46,13 +47,14 @@
     /**********************************************************
      */
 
-    // For [Issue#501]
+    // For [databind#501]
     public void testSetterlessWithPolymorphic() throws Exception
     {
         Issue501Bean input = new Issue501Bean("a", new Poly(13));
         ObjectMapper m = new ObjectMapper();
         assertTrue(m.isEnabled(MapperFeature.USE_GETTERS_AS_SETTERS));
-        m.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        m.activateDefaultTyping(NoCheckSubTypeValidator.instance,
+                ObjectMapper.DefaultTyping.NON_FINAL);
 
         String json = m.writerWithDefaultPrettyPrinter().writeValueAsString(input);
 
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java b/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java
index 48a9ff2..09b3226 100644
--- a/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java
+++ b/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java
@@ -18,7 +18,7 @@
         public void setUserId(CharSequence id) {
             // 21-Dec-2015, tatu: With a fix in 2.7, use of String would not
             //   trigger the problem, so use CharSequence...
-            setUserId(new Integer(id.toString()));
+            setUserId(Integer.valueOf(id.toString()));
         }
 
         public Integer getUserId() {
@@ -38,6 +38,7 @@
 
     private final ObjectMapper MAPPER = new ObjectMapper();
 
+    // Aside from [databind#426], also relevant: [databind#1044]?
     public void testIssue426() throws Exception
     {
         final String JSON = aposToQuotes("{'userId': 9, 'firstName': 'Mike' }");
diff --git a/src/test/java/com/fasterxml/jackson/failing/UnwrappedCaching2461Test.java b/src/test/java/com/fasterxml/jackson/failing/UnwrappedCaching2461Test.java
new file mode 100644
index 0000000..ab7bde9
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/UnwrappedCaching2461Test.java
@@ -0,0 +1,53 @@
+package com.fasterxml.jackson.failing;
+
+import com.fasterxml.jackson.annotation.JsonUnwrapped;
+import com.fasterxml.jackson.databind.*;
+
+public class UnwrappedCaching2461Test extends BaseMapTest
+{
+    // [databind#2461]
+    static class Base {
+        public String id;
+
+        Base(String id) {
+            this.id = id;
+        }
+    }
+
+    static class InnerContainer {
+        @JsonUnwrapped(prefix = "base.")
+        public Base base;
+
+        InnerContainer(Base base) {
+            this.base = base;
+        }
+    }
+
+    static class OuterContainer {
+        @JsonUnwrapped(prefix = "container.")
+        public InnerContainer container;
+
+        OuterContainer(InnerContainer container) {
+            this.container = container;
+        }
+    }
+
+    // [databind#2461]
+    public void testUnwrappedCaching() throws Exception {
+        final InnerContainer inner = new InnerContainer(new Base("12345"));
+        final OuterContainer outer = new OuterContainer(inner);
+
+        final String EXP_INNER = "{\"base.id\":\"12345\"}";
+        final String EXP_OUTER = "{\"container.base.id\":\"12345\"}";
+        
+        final ObjectMapper mapperOrder1 = newJsonMapper();
+        assertEquals(EXP_OUTER, mapperOrder1.writeValueAsString(outer));
+        assertEquals(EXP_INNER, mapperOrder1.writeValueAsString(inner));
+        assertEquals(EXP_OUTER, mapperOrder1.writeValueAsString(outer));
+
+        final ObjectMapper mapperOrder2 = newJsonMapper();
+        assertEquals(EXP_INNER, mapperOrder2.writeValueAsString(inner));
+        //  Will fail here
+        assertEquals(EXP_OUTER, mapperOrder2.writeValueAsString(outer));
+    }
+}
diff --git a/src/test/java/com/mchange/v2/c3p0/jacksontest/ComboPooledDataSource.java b/src/test/java/com/mchange/v2/c3p0/jacksontest/ComboPooledDataSource.java
deleted file mode 100644
index 56f0889..0000000
--- a/src/test/java/com/mchange/v2/c3p0/jacksontest/ComboPooledDataSource.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.mchange.v2.c3p0.jacksontest;
-
-// test class for [databind#1931]
-public class ComboPooledDataSource {
-
-}
diff --git a/src/test/java/org/springframework/jacksontest/AbstractApplicationContext.java b/src/test/java/org/springframework/jacksontest/AbstractApplicationContext.java
deleted file mode 100644
index e537782..0000000
--- a/src/test/java/org/springframework/jacksontest/AbstractApplicationContext.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.springframework.jacksontest;
-
-public class AbstractApplicationContext {
-
-}
diff --git a/src/test/java/org/springframework/jacksontest/AbstractPointcutAdvisor.java b/src/test/java/org/springframework/jacksontest/AbstractPointcutAdvisor.java
deleted file mode 100644
index 0ee87e0..0000000
--- a/src/test/java/org/springframework/jacksontest/AbstractPointcutAdvisor.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.springframework.jacksontest;
-
-public class AbstractPointcutAdvisor {
-
-}
diff --git a/src/test/java/org/springframework/jacksontest/BogusApplicationContext.java b/src/test/java/org/springframework/jacksontest/BogusApplicationContext.java
deleted file mode 100644
index 55dba37..0000000
--- a/src/test/java/org/springframework/jacksontest/BogusApplicationContext.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.springframework.jacksontest;
-
-//Made-up test class that should trigger checks for [databind#1855]
-public class BogusApplicationContext extends AbstractApplicationContext {
-    public BogusApplicationContext(String s) {
-        super();
-        throw new Error("Wrong!");
-    }
-}
diff --git a/src/test/java/org/springframework/jacksontest/BogusPointcutAdvisor.java b/src/test/java/org/springframework/jacksontest/BogusPointcutAdvisor.java
deleted file mode 100644
index c21d923..0000000
--- a/src/test/java/org/springframework/jacksontest/BogusPointcutAdvisor.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.springframework.jacksontest;
-
-// Made-up test class that should trigger checks for [databind#1855]
-public class BogusPointcutAdvisor extends AbstractPointcutAdvisor {
-    public BogusPointcutAdvisor(String s) {
-        super();
-        throw new Error("Wrong!");
-    }
-}
diff --git a/src/test/java/org/springframework/jacksontest/GrantedAuthority.java b/src/test/java/org/springframework/jacksontest/GrantedAuthority.java
deleted file mode 100644
index ea9fc9a..0000000
--- a/src/test/java/org/springframework/jacksontest/GrantedAuthority.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.springframework.jacksontest;
-
-public interface GrantedAuthority {
-
-}
diff --git a/src/test/java/perf/ManualReadPerfUntyped.java b/src/test/java/perf/ManualReadPerfUntyped.java
index 4766e78..6a49ca3 100644
--- a/src/test/java/perf/ManualReadPerfUntyped.java
+++ b/src/test/java/perf/ManualReadPerfUntyped.java
@@ -4,6 +4,7 @@
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 
 public class ManualReadPerfUntyped extends ObjectReaderTestBase
 {
@@ -18,13 +19,13 @@
         }
         byte[] data = readAll(args[0]);
 
-        JsonFactory f = new JsonFactory();
         boolean doIntern = true;
-
-        f.configure(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES, doIntern);
-        f.configure(JsonFactory.Feature.INTERN_FIELD_NAMES, doIntern);
+        JsonFactory f = JsonFactory.builder()
+                .configure(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES, doIntern)
+                .configure(JsonFactory.Feature.INTERN_FIELD_NAMES, doIntern)
+                .build();
         
-        ObjectMapper m = new ObjectMapper();
+        JsonMapper m = new JsonMapper(f);
         
         // Either Object or Map
         final Class<?> UNTYPED = Map.class;
diff --git a/src/test/java/perf/ManualReadPerfUntypedReader.java b/src/test/java/perf/ManualReadPerfUntypedReader.java
index 49c424e..08a03e8 100644
--- a/src/test/java/perf/ManualReadPerfUntypedReader.java
+++ b/src/test/java/perf/ManualReadPerfUntypedReader.java
@@ -4,6 +4,7 @@
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 
 public class ManualReadPerfUntypedReader extends ObjectReaderTestBase
 {
@@ -18,13 +19,14 @@
         }
         byte[] data = readAll(args[0]);
 
-        JsonFactory f = new JsonFactory();
         boolean doIntern = true;
 
-        f.configure(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES, doIntern);
-        f.configure(JsonFactory.Feature.INTERN_FIELD_NAMES, doIntern);
+        JsonFactory f = JsonFactory.builder()
+                .configure(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES, doIntern)
+                .configure(JsonFactory.Feature.INTERN_FIELD_NAMES, doIntern)
+                .build();
         
-        ObjectMapper m = new ObjectMapper();
+        JsonMapper m = new JsonMapper(f);
         Object input1 = m.readValue(data, Object.class);
         JsonNode input2 = m.readTree(data);
 
diff --git a/src/test/java/perf/ManualReadPerfUntypedStream.java b/src/test/java/perf/ManualReadPerfUntypedStream.java
index 5b84c9e..cab09f3 100644
--- a/src/test/java/perf/ManualReadPerfUntypedStream.java
+++ b/src/test/java/perf/ManualReadPerfUntypedStream.java
@@ -4,6 +4,7 @@
 
 import com.fasterxml.jackson.core.*;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 
 public class ManualReadPerfUntypedStream extends ObjectReaderTestBase
 {
@@ -18,13 +19,14 @@
         }
         byte[] data = readAll(args[0]);
 
-        JsonFactory f = new JsonFactory();
         boolean doIntern = true;
 
-        f.configure(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES, doIntern);
-        f.configure(JsonFactory.Feature.INTERN_FIELD_NAMES, doIntern);
-        
-        ObjectMapper m = new ObjectMapper();
+        JsonFactory f = JsonFactory.builder()
+                .configure(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES, doIntern)
+                .configure(JsonFactory.Feature.INTERN_FIELD_NAMES, doIntern)
+                .build();
+
+        JsonMapper m = new JsonMapper(f);
         Object input1 = m.readValue(data, Object.class);
         JsonNode input2 = m.readTree(data);
 
diff --git a/src/test/java/perf/ManualReadPerfWithMedia.java b/src/test/java/perf/ManualReadPerfWithMedia.java
index e87a1e7..4c9e6b1 100644
--- a/src/test/java/perf/ManualReadPerfWithMedia.java
+++ b/src/test/java/perf/ManualReadPerfWithMedia.java
@@ -1,9 +1,9 @@
 package perf;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.introspect.Annotated;
 import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 
 public class ManualReadPerfWithMedia extends ObjectReaderTestBase
 {
@@ -32,9 +32,9 @@
         input.addPhoto(new MediaItem.Photo("http://a.com", "title1", 200, 100, MediaItem.Size.LARGE));
         input.addPhoto(new MediaItem.Photo("http://b.org", "title2", 640, 480, MediaItem.Size.SMALL));
 
-        ObjectMapper m1 = new ObjectMapper();
+        JsonMapper m1 = new JsonMapper();
         m1.setAnnotationIntrospector(new NoFormatIntrospector());
-        ObjectMapper m2 = new ObjectMapper();
+        JsonMapper m2 = new JsonMapper();
         new ManualReadPerfWithRecord().testFromBytes(m1, "JSON-as-Object", input, MediaItem.class,
                 m2, "JSON-as-Array", input, MediaItem.class);
     }
diff --git a/src/test/java/perf/ManualReadPerfWithRecord.java b/src/test/java/perf/ManualReadPerfWithRecord.java
index 35b3661..5551b51 100644
--- a/src/test/java/perf/ManualReadPerfWithRecord.java
+++ b/src/test/java/perf/ManualReadPerfWithRecord.java
@@ -1,6 +1,6 @@
 package perf;
 
-import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 
 /**
  * Simple manually run micro-benchmark for checking effects of (de)serializer
@@ -19,7 +19,7 @@
         }
         Record input = new Record(44, "BillyBob", "Bumbler", 'm', true);
         RecordAsArray input2 = new RecordAsArray(44, "BillyBob", "Bumbler", 'm', true);
-        ObjectMapper m = new ObjectMapper();
+        JsonMapper m = new JsonMapper();
         new ManualReadPerfWithRecord().testFromBytes(m, "JSON-as-Object", input, Record.class,
                 m, "JSON-as-Array", input2, RecordAsArray.class);
     }
diff --git a/src/test/java/perf/ManualReadPerfWithUUID.java b/src/test/java/perf/ManualReadPerfWithUUID.java
index 3411577..678ade1 100644
--- a/src/test/java/perf/ManualReadPerfWithUUID.java
+++ b/src/test/java/perf/ManualReadPerfWithUUID.java
@@ -5,9 +5,9 @@
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 
 public class ManualReadPerfWithUUID extends ObjectReaderTestBase
 {
@@ -53,7 +53,7 @@
         UUIDNative input1 = new UUIDNative(uuids);
         UUIDWithJdk input2 = new UUIDWithJdk(uuids);
 
-        ObjectMapper m = new ObjectMapper();
+        JsonMapper m = new JsonMapper();
 
         new ManualReadPerfWithRecord().testFromBytes(
                 m, "JSON-as-Object", input1, UUIDNative.class,
diff --git a/src/test/java/perf/ManualReadWithTypeResolution.java b/src/test/java/perf/ManualReadWithTypeResolution.java
index 3f3f358..174be9a 100644
--- a/src/test/java/perf/ManualReadWithTypeResolution.java
+++ b/src/test/java/perf/ManualReadWithTypeResolution.java
@@ -5,6 +5,7 @@
 
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 
 /**
  * Variant that uses hard-coded input but compares cost of generic type
@@ -35,7 +36,7 @@
     private ManualReadWithTypeResolution() throws IOException {
         _desc1 = "Raw type";
         _desc2 = "Generic type";
-        _mapper = new ObjectMapper();
+        _mapper = new JsonMapper();
 
         _input = "[\"value\",\"123\"]".getBytes("UTF-8");
         _inputType = List.class;
diff --git a/src/test/java/perf/ManualWritePerfUntyped.java b/src/test/java/perf/ManualWritePerfUntyped.java
index 0a4d68a..e76aee6 100644
--- a/src/test/java/perf/ManualWritePerfUntyped.java
+++ b/src/test/java/perf/ManualWritePerfUntyped.java
@@ -3,8 +3,8 @@
 import java.io.File;
 import java.util.*;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectWriter;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 
 /* Test modified from json-parsers-benchmark, to be able to profile
  * Jackson implementation.
@@ -21,7 +21,7 @@
             System.err.println("Usage: java [input]");
             System.exit(1);
         }
-        ObjectMapper mapper = new ObjectMapper();
+        JsonMapper mapper = new JsonMapper();
         Map<?,?> stuff = mapper.readValue(new File(args[0]), Map.class);
         new ManualWritePerfUntyped().test(mapper,
                 "Untyped-1", stuff, Object.class,
diff --git a/src/test/java/perf/ManualWritePerfWithAllTypes.java b/src/test/java/perf/ManualWritePerfWithAllTypes.java
index 2613845..e3daebf 100644
--- a/src/test/java/perf/ManualWritePerfWithAllTypes.java
+++ b/src/test/java/perf/ManualWritePerfWithAllTypes.java
@@ -4,8 +4,8 @@
 import java.math.BigInteger;
 import java.util.*;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectWriter;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 
 /* Test modified from json-parsers-benchmark, to be able to profile
  * Jackson implementation.
@@ -22,7 +22,7 @@
             System.err.println("Usage: java ...");
             System.exit(1);
         }
-        ObjectMapper m = new ObjectMapper();
+        JsonMapper m = new JsonMapper();
         AllTypes input1 = AllTypes.bigObject();
         AllTypes input2 = AllTypes.bigObject();
         new ManualWritePerfWithAllTypes().test(m,
diff --git a/src/test/java/perf/ManualWritePerfWithRecord.java b/src/test/java/perf/ManualWritePerfWithRecord.java
index 9e9cc0a..23c6366 100644
--- a/src/test/java/perf/ManualWritePerfWithRecord.java
+++ b/src/test/java/perf/ManualWritePerfWithRecord.java
@@ -1,6 +1,6 @@
 package perf;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 
 public class ManualWritePerfWithRecord
     extends ObjectWriterTestBase<Record, RecordAsArray>
@@ -16,7 +16,7 @@
         }
         Record input1 = new Record(44, "BillyBob", "Bumbler", 'm', true);
         RecordAsArray input2 = new RecordAsArray(44, "BillyBob", "Bumbler", 'm', true);
-        ObjectMapper m = new ObjectMapper();
+        JsonMapper m = new JsonMapper();
         new ManualWritePerfWithRecord().test(m,
                 "JSON-as-Object", input1, Record.class,
                 "JSON-as-Array", input2, RecordAsArray.class);
diff --git a/src/test/java/perf/ManulWritePerfWithUUID.java b/src/test/java/perf/ManualWritePerfWithUUID.java
similarity index 89%
rename from src/test/java/perf/ManulWritePerfWithUUID.java
rename to src/test/java/perf/ManualWritePerfWithUUID.java
index a782c3a..f87dfa9 100644
--- a/src/test/java/perf/ManulWritePerfWithUUID.java
+++ b/src/test/java/perf/ManualWritePerfWithUUID.java
@@ -5,12 +5,13 @@
 
 import com.fasterxml.jackson.core.JsonGenerationException;
 import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.ObjectMapper;
+
 import com.fasterxml.jackson.databind.SerializerProvider;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.json.JsonMapper;
 import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
 
-public class ManulWritePerfWithUUID
+public class ManualWritePerfWithUUID
     extends ObjectWriterTestBase<UUIDFast, UUIDSlow>
 {
     @Override
@@ -26,8 +27,7 @@
         for (int i = 0; i < uuids.length; ++i) {
             uuids[i] = UUID.randomUUID();
         }
-        ObjectMapper m = new ObjectMapper();
-        new ManulWritePerfWithUUID().test(m,
+        new ManualWritePerfWithUUID().test(new JsonMapper(),
                 "faster-UUID", new UUIDFast(uuids), UUIDFast.class,
                 "JDK-UUID", new UUIDSlow(uuids), UUIDSlow.class);
     }