title: Spring Data, Mongo, and @TypeAlias: reading not working
body: <p><strong>The issue</strong></p>
  
  <p>Awhile back I started using MongoDB and Spring Data. I'd left most of the default functionality in place, and so all of my documents were stored in MongoDB with a <code>_class</code> field pointing to the entity's fully-qualified class name. </p>
  
  <p>Right away that didn't "smell" right to me, but I left it alone. Until recently, when I refactored a bunch of code, and suddenly none of my documents could be read back from MongoDB and converted into their (refactored/renamed) Java entities. I quickly realized that it was because there was now a fully-qualified-classname mismatch. I also quickly realized that--given that I might refactor again sometime in the future--if I didn't want all of my data to become unusable I'd need to figure something else out. </p>
  
  <p><strong>What I've tried</strong></p>
  
  <p>So that's what I'm doing, but I've hit a wall. I <em>think</em> that I need to do the following:</p>
  
  <ul>
  <li>Annotate each entity with <code>@TypeAlias("ta")</code> where "ta" is a unique, stable string.</li>
  <li>Configure and use a different <code>TypeInformationMapper</code> for Spring Data to use when converting my documents back into their Java entities; it needs to know, for example, that a type-alias of "widget.foo" refers to <code>com.myapp.document.FooWidget</code>.</li>
  </ul>
  
  <p>I determined that I should use a <code>TypeInformationMapper</code> of type <code>org.springframework.data.convert.MappingContextTypeInformationMapper</code>. Supposedly a MappingContextTypeInformationMapper will scan my entities/documents to find @TypeAlias'ed documents and store an alias->to->class mapping. But I can't pass that to my MappingMongoConverter; I have to pass a subtype of MongoTypeMapper. So I am configuring a <code>DefaultMongoTypeMapper</code>, and passing a List of one <code>MappingContextTypeInformationMapper</code> as its "mappers" constructor arg.</p>
  
  <p><strong>Code</strong></p>
  
  <p>Here's the relevant part of my spring XML config:</p>
  
  <pre><code>&lt;bean id="mongoTypeMapper" class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper"&gt;
      &lt;constructor-arg name="typeKey" value="_class"&gt;&lt;/constructor-arg&gt;
      &lt;constructor-arg name="mappers"&gt;
          &lt;list&gt;
              &lt;ref bean="mappingContextTypeMapper" /&gt;
          &lt;/list&gt;
      &lt;/constructor-arg&gt; 
  &lt;/bean&gt;
  
  &lt;bean id="mappingContextTypeMapper" class="org.springframework.data.convert.MappingContextTypeInformationMapper"&gt;
      &lt;constructor-arg ref="mappingContext" /&gt;
  &lt;/bean&gt;
  
  &lt;bean id="mappingMongoConverter"
      class="org.springframework.data.mongodb.core.convert.MappingMongoConverter"&gt;
      &lt;constructor-arg ref="mongoDbFactory" /&gt;
      &lt;constructor-arg ref="mappingContext" /&gt;
      &lt;property name="mapKeyDotReplacement" value="__dot__" /&gt;
      &lt;property name="typeMapper" ref="mongoTypeMapper"/&gt;
   &lt;/bean&gt;
  
   &lt;bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"&gt;
      &lt;constructor-arg ref="mongoDbFactory" /&gt;
      &lt;constructor-arg ref="mappingMongoConverter" /&gt;
   &lt;/bean&gt;
  </code></pre>
  
  <p>Here's a sample entity/document:</p>
  
  <pre><code>@Document(collection="widget")
  @TypeAlias("widget.foo")
  public class FooWidget extends Widget {
  
      // ...
  
  }
  </code></pre>
  
  <p>One important note is that any such "Widget" entity is stored as a nested document in Mongo. So in reality you won't really find a populated "Widget" collection in my MongoDB instance. Instead, a higher-level "Page" class can contain multiple "widgets" like so:</p>
  
  <pre><code>@Document(collection="page")
  @TypeAlias("page")
  public class Page extends BaseDocument {
  
      // ...
  
      private List&lt;Widget&gt; widgets = new ArrayList&lt;Widget&gt;();
  
  }
  </code></pre>
  
  <p><strong>The error I'm stuck on</strong></p>
  
  <p>What happens is that I can save a Page along with a number of nested Widgets in Mongo. But when I try to read said Page back out, I get something like the following:</p>
  
  <pre><code>org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.myapp.document.Widget]: Is it an abstract class?
  </code></pre>
  
  <p>I can indeed see pages in Mongo containing <code>"_class" : "page"</code>, with nested widgets also containing <code>"_class" : "widget.foo"</code>  It just appears like the mapping is not being applied in the reverse.</p>
  
  <p>Is there anything I might be missing?</p>