diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringItem.php
index ce78a40c07b3574b3264b6c4c70c6a8c6f2d5274..6a46aaa099223edba5d69efc17d18a79ca0be7d4 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/StringItem.php
@@ -62,4 +62,20 @@ public static function schema(FieldDefinitionInterface $field_definition) {
     );
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getConstraints() {
+    $constraints = parent::getConstraints();
+
+    if ($max_length = $this->getFieldSetting('max_length')) {
+      $constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager();
+      $constraints[] = $constraint_manager->create('ComplexData', array(
+        'value' => array('Length' => array('max' => $max_length))
+      ));
+    }
+
+    return $constraints;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php
index 4cad163ff39f1f33ce4aa6c9783b02d6c09825bc..d8c0b32492d20d422195118601546f2360021bff 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php
@@ -8,20 +8,26 @@
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
 use Drupal\Core\Field\FieldDefinitionInterface;
-use Drupal\Core\Field\FieldItemBase;
 use Drupal\Core\TypedData\DataDefinition;
 
 /**
  * Defines the 'uri' entity field type.
  *
+ * URIs are not length limited by RFC 2616, but we need to provide a sensible
+ * default. There is a de-facto limit of 2000 characters in browsers and other
+ * implementors, so we go with 2048.
+ *
  * @FieldType(
  *   id = "uri",
  *   label = @Translation("URI"),
  *   description = @Translation("An entity field containing a URI."),
+ *   settings = {
+ *     "max_length" = "2048"
+ *   },
  *   configurable = FALSE
  * )
  */
-class UriItem extends FieldItemBase {
+class UriItem extends StringItem {
 
   /**
    * Field definitions of the contained properties.
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UuidItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UuidItem.php
index 147c3fd9e99a871863c1c905b139ae2aa2face64..27ca9e94361d159e305f95da1727f6a6422e79d7 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UuidItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UuidItem.php
@@ -16,12 +16,10 @@
  *   id = "uuid",
  *   label = @Translation("UUID"),
  *   description = @Translation("An entity field containing a UUID."),
- *   configurable = FALSE,
- *   constraints = {
- *     "ComplexData" = {
- *       "value" = {"Length" = {"max" = 128}}
- *     }
- *   }
+ *   settings = {
+ *     "max_length" = "128"
+ *   },
+ *   configurable = FALSE
  * )
  */
 class UuidItem extends StringItem {
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
index 5ab26a048f30414eaafd728307b2ff02595c3d9a..91bd8fd34c59c778cbab040b4dd4e2e407b6b367 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
@@ -128,7 +128,7 @@ public static function baseFieldDefinitions($entity_type) {
       ->setLabel(t('Name'))
       ->setDescription(t('The name of the test entity.'))
       ->setTranslatable(TRUE)
-      ->setPropertyConstraints('value', array('Length' => array('max' => 32)));
+      ->setSetting('max_length', 32);
 
     // @todo: Add allowed values validation.
     $fields['type'] = FieldDefinition::create('string')
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php
index 32e0e9cf1241b9ec1af3c9b2d343ca481007ad29..d8f503c8a9ee2110c6d862a553b710f6816e9c4e 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php
@@ -208,6 +208,8 @@ public static function baseFieldDefinitions($entity_type) {
       ->setDescription(t('The term UUID.'))
       ->setReadOnly(TRUE);
 
+    // @todo Convert this to an entity_reference field, see
+    //   https://drupal.org/node/2181593
     $fields['vid'] = FieldDefinition::create('string')
       ->setLabel(t('Vocabulary ID'))
       ->setDescription(t('The ID of the vocabulary to which the term is assigned.'));
@@ -218,7 +220,9 @@ public static function baseFieldDefinitions($entity_type) {
 
     $fields['name'] = FieldDefinition::create('string')
       ->setLabel(t('Name'))
-      ->setDescription(t('The term name.'));
+      ->setDescription(t('The term name.'))
+      ->setRequired(TRUE)
+      ->setSetting('max_length', 255);
 
     $fields['description'] = FieldDefinition::create('text_long')
       ->setLabel(t('Description'))
@@ -230,12 +234,14 @@ public static function baseFieldDefinitions($entity_type) {
       ->setDescription(t('The weight of this term in relation to other terms.'))
       ->setSetting('default_value', 0);
 
+    // @todo Convert this to an entity_reference field, see
+    // https://drupal.org/node/1915056
     $fields['parent'] = FieldDefinition::create('integer')
       ->setLabel(t('Term Parents'))
       ->setDescription(t('The parents of this term.'))
       // Save new terms with no parents by default.
       ->setSetting('default_value', 0)
-      ->setComputed(TRUE);
+      ->setConstraints(array('TermParent' => array()));
 
     $fields['changed'] = FieldDefinition::create('integer')
       ->setLabel(t('Changed'))
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Validation/Constraint/TermParentConstraint.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Validation/Constraint/TermParentConstraint.php
new file mode 100644
index 0000000000000000000000000000000000000000..2e221d2cfece31a5e9bf00ddcca83beaca380b0a
--- /dev/null
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Validation/Constraint/TermParentConstraint.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\taxonomy\Plugin\Validation\Constraint\TermParentConstraint.
+ */
+
+namespace Drupal\taxonomy\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraint;
+use Drupal\Component\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Checks if a value is a valid taxonomy term parent (term id or 0).
+ *
+ * @Plugin(
+ *   id = "TermParent",
+ *   label = @Translation("Term parent", context = "Validation")
+ * )
+ */
+class TermParentConstraint extends Constraint {
+
+  /**
+   * The default violation message.
+   *
+   * @var string
+   */
+  public $message = '%id is not a valid parent for this term.';
+}
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Validation/Constraint/TermParentConstraintValidator.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Validation/Constraint/TermParentConstraintValidator.php
new file mode 100644
index 0000000000000000000000000000000000000000..53d2411d4c7729afa49674cda1e1b8c94de310ab
--- /dev/null
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Validation/Constraint/TermParentConstraintValidator.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\taxonomy\Plugin\Validation\Constraint\TermParentConstraintValidator.
+ */
+
+namespace Drupal\taxonomy\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidator;
+
+/**
+ * Validates the TermParent constraint.
+ */
+class TermParentConstraintValidator extends ConstraintValidator {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validate($field_item, Constraint $constraint) {
+    if ($field_item) {
+      $parent_term_id = $field_item->value;
+      // If a non-0 parent term id is specified, ensure it corresponds to a real
+      // term in the same vocabulary.
+      if ($parent_term_id && !\Drupal::entityManager()->getStorageController('taxonomy_term')->loadByProperties(array('tid' => $parent_term_id, 'vid' => $field_item->getEntity()->vid->value))) {
+        $this->context->addViolation($constraint->message, array('%id' => $parent_term_id));
+      }
+    }
+  }
+}
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermValidationTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermValidationTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..dfb9803fe1c00dcd08a9b4d4743d47a484390689
--- /dev/null
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermValidationTest.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\taxonomy\Tests\TermValidationTest.
+ */
+
+namespace Drupal\taxonomy\Tests;
+
+use Drupal\system\Tests\Entity\EntityUnitTestBase;
+
+/**
+ * Tests term validation constraints.
+ */
+class TermValidationTest extends EntityUnitTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('taxonomy');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Term Validation',
+      'description' => 'Tests the term validation constraints.',
+      'group' => 'Taxonomy',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setUp();
+    $this->installSchema('taxonomy', array('taxonomy_term_data'));
+  }
+
+  /**
+   * Tests the term validation constraints.
+   */
+  public function testValidation() {
+    $term = $this->entityManager->getStorageController('taxonomy_term')->create(array(
+      'name' => 'test',
+      'vid' => 'tags',
+    ));
+    $violations = $term->validate();
+    $this->assertEqual(count($violations), 0, 'No violations when validating a default term.');
+
+    $term->set('name', $this->randomString(256));
+    $violations = $term->validate();
+    $this->assertEqual(count($violations), 1, 'Violation found when name is too long.');
+    $this->assertEqual($violations[0]->getPropertyPath(), 'name.0.value');
+    $this->assertEqual($violations[0]->getMessage(), t('This value is too long. It should have %limit characters or less.', array('%limit' => 255)));
+
+    $term->set('name', NULL);
+    $violations = $term->validate();
+    $this->assertEqual(count($violations), 1, 'Violation found when name is NULL.');
+    $this->assertEqual($violations[0]->getPropertyPath(), 'name');
+    $this->assertEqual($violations[0]->getMessage(), t('This value should not be null.'));
+    $term->set('name', 'test');
+
+    $term->set('parent', 9999);
+    $violations = $term->validate();
+    $this->assertEqual(count($violations), 1, 'Violation found when term parent is invalid.');
+    $this->assertEqual($violations[0]->getMessage(), format_string('%id is not a valid parent for this term.', array('%id' => 9999)));
+  }
+}
diff --git a/core/modules/user/lib/Drupal/user/Entity/User.php b/core/modules/user/lib/Drupal/user/Entity/User.php
index f9db482376582010eaaca6600a1b1e1e5f0ed6fd..80c44eeb6991d1dd25783b3ae7c59d96667d7acb 100644
--- a/core/modules/user/lib/Drupal/user/Entity/User.php
+++ b/core/modules/user/lib/Drupal/user/Entity/User.php
@@ -472,8 +472,7 @@ public static function baseFieldDefinitions($entity_type) {
     // @todo Convert to a text field in https://drupal.org/node/1548204.
     $fields['signature'] = FieldDefinition::create('string')
       ->setLabel(t('Signature'))
-      ->setDescription(t('The signature of this user.'))
-      ->setPropertyConstraints('value', array('Length' => array('max' => 255)));
+      ->setDescription(t('The signature of this user.'));
     $fields['signature_format'] = FieldDefinition::create('string')
       ->setLabel(t('Signature format'))
       ->setDescription(t('The signature format of this user.'));
@@ -481,7 +480,7 @@ public static function baseFieldDefinitions($entity_type) {
     $fields['timezone'] = FieldDefinition::create('string')
       ->setLabel(t('Timezone'))
       ->setDescription(t('The timezone of this user.'))
-      ->setPropertyConstraints('value', array('Length' => array('max' => 32)));
+      ->setSetting('max_length', 32);
 
     $fields['status'] = FieldDefinition::create('boolean')
       ->setLabel(t('User status'))