diff --git a/src/DataType/DataTypePluginManager.php b/src/DataType/DataTypePluginManager.php
index 0349533..b416556 100644
--- a/src/DataType/DataTypePluginManager.php
+++ b/src/DataType/DataTypePluginManager.php
@@ -21,11 +21,21 @@ class DataTypePluginManager extends DefaultPluginManager {
    *
    * @var \Drupal\search_api\DataType\DataTypeInterface[]
    *
+   * @see \Drupal\search_api\DataType\DataTypePluginManager::createInstance()
    * @see \Drupal\search_api\DataType\DataTypePluginManager::getInstances()
    */
   protected $dataTypes;
 
   /**
+   * Whether all plugin instances have already been created.
+   *
+   * @var bool
+   *
+   * @see \Drupal\search_api\DataType\DataTypePluginManager::getInstances()
+   */
+  protected $allCreated = FALSE;
+
+  /**
    * Constructs a DataTypePluginManager object.
    *
    * @param \Traversable $namespaces
@@ -44,19 +54,43 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac
   }
 
   /**
+   * Creates or retrieves a data type plugin.
+   *
+   * @param string $plugin_id
+   *   The ID of the plugin being instantiated.
+   * @param array $configuration
+   *   (optional) An array of configuration relevant to the plugin instance.
+   *   Ignored for data type plugins.
+   *
+   * @return \Drupal\search_api\DataType\DataTypeInterface
+   *   The requested data type plugin.
+   *
+   * @throws \Drupal\Component\Plugin\Exception\PluginException
+   *   If the instance cannot be created, such as if the ID is invalid.
+   */
+  public function createInstance($plugin_id, array $configuration = array()) {
+    if (empty($this->dataTypes[$plugin_id])) {
+      $this->dataTypes[$plugin_id] = parent::createInstance($plugin_id, $configuration);
+    }
+    return $this->dataTypes[$plugin_id];
+  }
+
+  /**
    * Returns all known data types.
    *
    * @return \Drupal\search_api\DataType\DataTypeInterface[]
    *   An array of data type plugins, keyed by type identifier.
    */
   public function getInstances() {
-    if (!isset($this->dataTypes)) {
-      $this->dataTypes = array();
+    if (!$this->allCreated) {
+      if (!isset($this->dataTypes)) {
+        $this->dataTypes = array();
+      }
 
-      foreach ($this->getDefinitions() as $name => $data_type_definition) {
-        if (class_exists($data_type_definition['class']) && empty($this->dataTypes[$name])) {
-          $data_type = $this->createInstance($name);
-          $this->dataTypes[$name] = $data_type;
+      foreach ($this->getDefinitions() as $plugin_id => $definition) {
+        if (class_exists($definition['class']) && empty($this->dataTypes[$plugin_id])) {
+          $data_type = $this->createInstance($plugin_id);
+          $this->dataTypes[$plugin_id] = $data_type;
         }
       }
     }
diff --git a/src/Utility.php b/src/Utility.php
index bbcfd6d..701feda 100644
--- a/src/Utility.php
+++ b/src/Utility.php
@@ -59,14 +59,18 @@ class Utility {
    *
    * @return bool
    *   TRUE if $type is one of the specified types, FALSE otherwise.
-   *
-   * @see https://drupal.org/node/2644502
    */
   public static function isTextType($type, array $text_types = array('text')) {
-    // @todo Currently, this is useless, but later we could also check
-    //   automatically for custom types that have one of the passed types as their
-    //   fallback.
-    return in_array($type, $text_types);
+    if (in_array($type, $text_types)) {
+      return TRUE;
+    }
+    $data_type = \Drupal::getContainer()
+      ->get('plugin.manager.search_api.data_type')
+      ->createInstance($type);
+    if ($data_type && !$data_type->isDefault()) {
+      return in_array($data_type->getFallbackType(), $text_types);
+    }
+    return FALSE;
   }
 
   /**
@@ -160,8 +164,10 @@ public static function getDataTypeFallbackMapping(IndexInterface $index) {
         // custom types.
       }
       static::$dataTypeFallbackMapping[$index_id] = array();
-      /** @var \Drupal\search_api\DataType\DataTypeInterface $data_type */
-      foreach (\Drupal::service('plugin.manager.search_api.data_type')->getInstances() as $type_id => $data_type) {
+      $data_types = \Drupal::getContainer()
+        ->get('plugin.manager.search_api.data_type')
+        ->getInstances();
+      foreach ($data_types as $type_id => $data_type) {
         // We know for sure that we do not need to fall back for the default
         // data types as they are always present and are required to be
         // supported by all backends.
diff --git a/tests/src/Unit/Plugin/Processor/HtmlFilterTest.php b/tests/src/Unit/Plugin/Processor/HtmlFilterTest.php
index 1de8371..d32a629 100644
--- a/tests/src/Unit/Plugin/Processor/HtmlFilterTest.php
+++ b/tests/src/Unit/Plugin/Processor/HtmlFilterTest.php
@@ -2,6 +2,7 @@
 
 namespace Drupal\Tests\search_api\Unit\Plugin\Processor;
 
+use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\search_api\Plugin\search_api\processor\HtmlFilter;
 use Drupal\search_api\Utility;
 use Drupal\Tests\UnitTestCase;
@@ -47,7 +48,6 @@ public function testTitleConfiguration($passed_value, $expected_value, $title_co
     $type = 'text';
     $this->invokeMethod('processFieldValue', array(&$passed_value, &$type));
     $this->assertEquals($expected_value, $passed_value);
-
   }
 
   /**
@@ -229,6 +229,13 @@ public function tagConfigurationDataProvider() {
    * @dataProvider stringProcessingDataProvider
    */
   public function testStringProcessing(array $config) {
+    $data_type_manager = $this->getMockBuilder('Drupal\search_api\DataType\DataTypePluginManager')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $container = new ContainerBuilder();
+    $container->set('plugin.manager.search_api.data_type', $data_type_manager);
+    \Drupal::setContainer($container);
+
     $this->processor->setConfiguration($config);
 
     $passed_value = '<h2>Foo Bar <em>Baz</em></h2>
