SQOOP-1466: Sqoop2: Validations: Execute validators during Connection and Job creation on Server side
diff --git a/client/src/main/java/org/apache/sqoop/client/SqoopClient.java b/client/src/main/java/org/apache/sqoop/client/SqoopClient.java
index 2b3171c..0e45a24 100644
--- a/client/src/main/java/org/apache/sqoop/client/SqoopClient.java
+++ b/client/src/main/java/org/apache/sqoop/client/SqoopClient.java
@@ -20,10 +20,9 @@
 import org.apache.sqoop.client.request.SqoopRequests;
 import org.apache.sqoop.common.Direction;
 import org.apache.sqoop.common.SqoopException;
-import org.apache.sqoop.json.ConnectionValidationBean;
 import org.apache.sqoop.json.ConnectorBean;
 import org.apache.sqoop.json.FrameworkBean;
-import org.apache.sqoop.json.JobValidationBean;
+import org.apache.sqoop.json.ValidationResultBean;
 import org.apache.sqoop.model.FormUtils;
 import org.apache.sqoop.model.MConnection;
 import org.apache.sqoop.model.MConnector;
@@ -31,7 +30,7 @@
 import org.apache.sqoop.model.MJob;
 import org.apache.sqoop.model.MSubmission;
 import org.apache.sqoop.validation.Status;
-import org.apache.sqoop.validation.Validation;
+import org.apache.sqoop.validation.ValidationResult;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -534,10 +533,11 @@
     return requests.readHistory(jid).getSubmissions();
   }
 
-  private Status applyValidations(ConnectionValidationBean bean, MConnection connection) {
-    Validation connector = bean.getConnectorValidation();
-    Validation framework = bean.getFrameworkValidation();
+  private Status applyValidations(ValidationResultBean bean, MConnection connection) {
+    ValidationResult connector = bean.getValidationResults()[0];
+    ValidationResult framework = bean.getValidationResults()[1];
 
+    // Apply validation results
     FormUtils.applyValidation(connection.getConnectorPart().getForms(), connector);
     FormUtils.applyValidation(connection.getFrameworkPart().getForms(), framework);
 
@@ -549,11 +549,12 @@
     return Status.getWorstStatus(connector.getStatus(), framework.getStatus());
   }
 
-  private Status applyValidations(JobValidationBean bean, MJob job) {
-    Validation fromConnector = bean.getConnectorValidation(Direction.FROM);
-    Validation toConnector = bean.getConnectorValidation(Direction.TO);
-    Validation framework = bean.getFrameworkValidation();
+  private Status applyValidations(ValidationResultBean bean, MJob job) {
+    ValidationResult fromConnector = bean.getValidationResults()[0];
+    ValidationResult toConnector = bean.getValidationResults()[1];
+    ValidationResult framework = bean.getValidationResults()[2];
 
+    // Apply validation results
     // @TODO(Abe): From/To validation.
     FormUtils.applyValidation(
         job.getConnectorPart(Direction.FROM).getForms(),
diff --git a/client/src/main/java/org/apache/sqoop/client/request/ConnectionRequest.java b/client/src/main/java/org/apache/sqoop/client/request/ConnectionRequest.java
index e0740a9..8436fc5 100644
--- a/client/src/main/java/org/apache/sqoop/client/request/ConnectionRequest.java
+++ b/client/src/main/java/org/apache/sqoop/client/request/ConnectionRequest.java
@@ -18,7 +18,7 @@
 package org.apache.sqoop.client.request;
 
 import org.apache.sqoop.json.ConnectionBean;
-import org.apache.sqoop.json.ConnectionValidationBean;
+import org.apache.sqoop.json.ValidationResultBean;
 import org.apache.sqoop.model.MConnection;
 import org.json.simple.JSONObject;
 import org.json.simple.JSONValue;
@@ -49,37 +49,32 @@
     return connectionBean;
   }
 
-  public ConnectionValidationBean create(String serverUrl, MConnection connection) {
-
+  public ValidationResultBean create(String serverUrl, MConnection connection) {
     ConnectionBean connectionBean = new ConnectionBean(connection);
 
     // Extract all form inputs including sensitive inputs
     JSONObject connectionJson = connectionBean.extract(false);
 
-    String response = super.post(serverUrl + RESOURCE,
-                                 connectionJson.toJSONString());
+    String response = super.post(serverUrl + RESOURCE, connectionJson.toJSONString());
 
-    ConnectionValidationBean connectionValidationBean = new ConnectionValidationBean();
-    connectionValidationBean.restore((JSONObject) JSONValue.parse(response));
+    ValidationResultBean validationBean = new ValidationResultBean();
+    validationBean.restore((JSONObject) JSONValue.parse(response));
 
-    return connectionValidationBean;
+    return validationBean;
   }
 
-  public ConnectionValidationBean update(String serverUrl, MConnection connection) {
-
+  public ValidationResultBean update(String serverUrl, MConnection connection) {
     ConnectionBean connectionBean = new ConnectionBean(connection);
 
     // Extract all form inputs including sensitive inputs
     JSONObject connectionJson = connectionBean.extract(false);
 
-    String response = super.put(serverUrl + RESOURCE
-                                  + connection.getPersistenceId(),
-                                connectionJson.toJSONString());
+    String response = super.put(serverUrl + RESOURCE + connection.getPersistenceId(), connectionJson.toJSONString());
 
-    ConnectionValidationBean connectionValidationBean = new ConnectionValidationBean();
-    connectionValidationBean.restore((JSONObject) JSONValue.parse(response));
+    ValidationResultBean validationBean = new ValidationResultBean();
+    validationBean.restore((JSONObject) JSONValue.parse(response));
 
-    return connectionValidationBean;
+    return validationBean;
   }
 
   public void delete(String serverUrl, Long id) {
diff --git a/client/src/main/java/org/apache/sqoop/client/request/JobRequest.java b/client/src/main/java/org/apache/sqoop/client/request/JobRequest.java
index b824512..e520883 100644
--- a/client/src/main/java/org/apache/sqoop/client/request/JobRequest.java
+++ b/client/src/main/java/org/apache/sqoop/client/request/JobRequest.java
@@ -18,7 +18,7 @@
 package org.apache.sqoop.client.request;
 
 import org.apache.sqoop.json.JobBean;
-import org.apache.sqoop.json.JobValidationBean;
+import org.apache.sqoop.json.ValidationResultBean;
 import org.apache.sqoop.model.MJob;
 import org.json.simple.JSONObject;
 import org.json.simple.JSONValue;
@@ -49,33 +49,29 @@
     return jobBean;
   }
 
-  public JobValidationBean create(String serverUrl, MJob job) {
-
+  public ValidationResultBean create(String serverUrl, MJob job) {
     JobBean jobBean = new JobBean(job);
 
     // Extract all form inputs including sensitive inputs
     JSONObject jobJson = jobBean.extract(false);
 
-    String response = super.post(serverUrl + RESOURCE,
-      jobJson.toJSONString());
+    String response = super.post(serverUrl + RESOURCE, jobJson.toJSONString());
 
-    JobValidationBean validationBean = new JobValidationBean();
+    ValidationResultBean validationBean = new ValidationResultBean();
     validationBean.restore((JSONObject) JSONValue.parse(response));
 
     return validationBean;
   }
 
-  public JobValidationBean update(String serverUrl, MJob job) {
-
+  public ValidationResultBean update(String serverUrl, MJob job) {
     JobBean jobBean = new JobBean(job);
 
     // Extract all form inputs including sensitive inputs
     JSONObject jobJson = jobBean.extract(false);
 
-    String response = super.put(serverUrl + RESOURCE + job.getPersistenceId(),
-                                jobJson.toJSONString());
+    String response = super.put(serverUrl + RESOURCE + job.getPersistenceId(), jobJson.toJSONString());
 
-    JobValidationBean validationBean = new JobValidationBean();
+    ValidationResultBean validationBean = new ValidationResultBean();
     validationBean.restore((JSONObject) JSONValue.parse(response));
 
     return validationBean;
diff --git a/client/src/main/java/org/apache/sqoop/client/request/SqoopRequests.java b/client/src/main/java/org/apache/sqoop/client/request/SqoopRequests.java
index d87bb78..0d13304 100644
--- a/client/src/main/java/org/apache/sqoop/client/request/SqoopRequests.java
+++ b/client/src/main/java/org/apache/sqoop/client/request/SqoopRequests.java
@@ -18,12 +18,11 @@
 package org.apache.sqoop.client.request;
 
 import org.apache.sqoop.json.ConnectionBean;
-import org.apache.sqoop.json.ConnectionValidationBean;
 import org.apache.sqoop.json.ConnectorBean;
 import org.apache.sqoop.json.FrameworkBean;
 import org.apache.sqoop.json.JobBean;
-import org.apache.sqoop.json.JobValidationBean;
 import org.apache.sqoop.json.SubmissionBean;
+import org.apache.sqoop.json.ValidationResultBean;
 import org.apache.sqoop.model.MConnection;
 import org.apache.sqoop.model.MJob;
 
@@ -92,7 +91,7 @@
     return getConnectorRequest().read(serverUrl, cid);
   }
 
-  public ConnectionValidationBean createConnection(MConnection connection) {
+  public ValidationResultBean createConnection(MConnection connection) {
     return getConnectionRequest().create(serverUrl, connection);
   }
 
@@ -100,7 +99,7 @@
     return getConnectionRequest().read(serverUrl, connectionId);
   }
 
-  public ConnectionValidationBean updateConnection(MConnection connection) {
+  public ValidationResultBean updateConnection(MConnection connection) {
     return getConnectionRequest().update(serverUrl, connection);
   }
 
@@ -112,7 +111,7 @@
     getConnectionRequest().delete(serverUrl, xid);
   }
 
-  public JobValidationBean createJob(MJob job) {
+  public ValidationResultBean createJob(MJob job) {
     return getJobRequest().create(serverUrl, job);
   }
 
@@ -120,7 +119,7 @@
     return getJobRequest().read(serverUrl, jobId);
   }
 
-  public JobValidationBean updateJob(MJob job) {
+  public ValidationResultBean updateJob(MJob job) {
     return getJobRequest().update(serverUrl, job);
   }
 
diff --git a/common/src/main/java/org/apache/sqoop/json/ValidationResultBean.java b/common/src/main/java/org/apache/sqoop/json/ValidationResultBean.java
new file mode 100644
index 0000000..89bc8db
--- /dev/null
+++ b/common/src/main/java/org/apache/sqoop/json/ValidationResultBean.java
@@ -0,0 +1,153 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.json;
+
+import org.apache.sqoop.validation.Message;
+import org.apache.sqoop.validation.Status;
+import org.apache.sqoop.validation.ValidationResult;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Serialize and transfer validation results (0..N).
+ */
+public class ValidationResultBean implements JsonBean {
+
+  private static final String ROOT = "ROOT";
+  private static final String ID = "ID";
+  private static final String STATUS = "STATUS";
+  private static final String TEXT = "TEXT";
+
+  private ValidationResult[] results;
+  private Long id;
+
+  public ValidationResultBean() {
+    // Empty, for restore
+  }
+
+  public ValidationResultBean(ValidationResult ... results) {
+    this.results = results;
+  }
+
+  public ValidationResult[] getValidationResults() {
+    return results;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public Long getId() {
+    return id;
+  }
+
+  @Override
+  public JSONObject extract(boolean skipSensitive) {
+    JSONArray array = new JSONArray();
+
+    for(ValidationResult result : results) {
+      JSONObject output = extractValidationResult(result);
+      array.add(output);
+    }
+
+    JSONObject object = new JSONObject();
+    object.put(ROOT, array);
+    if(id != null) {
+      object.put(ID, id);
+    }
+    return object;
+  }
+
+  private JSONObject extractValidationResult(ValidationResult result) {
+    JSONObject ret = new JSONObject();
+
+    for(Map.Entry<String, List<Message>> entry : result.getMessages().entrySet()) {
+      ret.put(entry.getKey(), extractMessageList(entry.getValue()));
+    }
+
+    return ret;
+  }
+
+  private Object extractMessageList(List<Message> messages) {
+    JSONArray array = new JSONArray();
+
+    for(Message message : messages) {
+      array.add(extractMessage(message));
+    }
+
+    return array;
+  }
+
+  private Object extractMessage(Message message) {
+    JSONObject ret = new JSONObject();
+
+    ret.put(STATUS, message.getStatus().toString());
+    ret.put(TEXT, message.getMessage());
+
+    return ret;
+  }
+
+  @Override
+  public void restore(JSONObject jsonObject) {
+    JSONArray array = (JSONArray) jsonObject.get(ROOT);
+    results = new ValidationResult[array.size()];
+
+    int i = 0;
+    for(Object item : array) {
+      results[i++] = restoreValidationResult((JSONObject) item);
+    }
+
+    if(jsonObject.containsKey(ID)) {
+      id = (Long) jsonObject.get(ID);
+    }
+  }
+
+  private ValidationResult restoreValidationResult(JSONObject item) {
+    ValidationResult result  = new ValidationResult();
+    Set<Map.Entry<String, JSONArray>> entrySet = item.entrySet();
+
+    for(Map.Entry<String, JSONArray> entry : entrySet) {
+      result.addMessages(entry.getKey(), restoreMessageList(entry.getValue()));
+    }
+
+
+    return result;
+  }
+
+  private List<Message> restoreMessageList(JSONArray array) {
+    List<Message> messages = new LinkedList<Message>();
+
+    for(Object item : array) {
+      messages.add(restoreMessage((JSONObject)item));
+    }
+
+    return messages;
+  }
+
+  private Message restoreMessage(JSONObject item) {
+    return new Message(
+      Status.valueOf((String) item.get(STATUS)),
+      (String) item.get(TEXT)
+    );
+  }
+}
diff --git a/common/src/main/java/org/apache/sqoop/model/FormUtils.java b/common/src/main/java/org/apache/sqoop/model/FormUtils.java
index d9666c8..927d4e6 100644
--- a/common/src/main/java/org/apache/sqoop/model/FormUtils.java
+++ b/common/src/main/java/org/apache/sqoop/model/FormUtils.java
@@ -19,8 +19,10 @@
 
 import org.apache.sqoop.common.SqoopException;
 import org.apache.sqoop.utils.ClassUtils;
+import org.apache.sqoop.validation.Message;
 import org.apache.sqoop.validation.Status;
 import org.apache.sqoop.validation.Validation;
+import org.apache.sqoop.validation.ValidationResult;
 import org.json.simple.JSONObject;
 import org.json.simple.JSONValue;
 
@@ -285,6 +287,43 @@
     }
   }
 
+
+  /**
+   * Apply given validations on list of forms.
+   *
+   * @param forms
+   * @param result
+   */
+  public static void applyValidation(List<MForm> forms, ValidationResult result) {
+    for(MForm form : forms) {
+      applyValidation(form, result);
+
+      for(MInput input : form.getInputs()) {
+        applyValidation(input, result);
+      }
+    }
+  }
+
+  /**
+   * Apply validation messages on given element.
+   *
+   * Element's state will be set to default if there are no associated messages.
+   *
+   * @param element
+   * @param result
+   */
+  public static void applyValidation(MValidatedElement element, ValidationResult result) {
+    List<Message> messages = result.getMessages().get(element.getName());
+
+    if(messages != null) {
+      // TODO(SQOOP-1465) Add support for multiple messages (showing only the first one for now)
+      Message message = messages.get(0);
+      element.setValidationMessage(message.getStatus(), message.getMessage());
+    } else {
+      element.setValidationMessage(Status.getDefault(), null);
+    }
+  }
+
   /**
    * Convert configuration object to JSON. Only filled properties are serialized,
    * properties with null value are skipped.
diff --git a/common/src/main/java/org/apache/sqoop/validation/ValidationResult.java b/common/src/main/java/org/apache/sqoop/validation/ValidationResult.java
index abe5b11..2782fac 100644
--- a/common/src/main/java/org/apache/sqoop/validation/ValidationResult.java
+++ b/common/src/main/java/org/apache/sqoop/validation/ValidationResult.java
@@ -72,6 +72,22 @@
     status = Status.getWorstStatus(status, result.status);
   }
 
+  /**
+   * Method to directly add messages for given name.
+   *
+   * This method will replace previous messages for given name.
+   *
+   * @param name Name of the entity
+   * @param messages List of messages associated with the name
+   */
+  public void addMessages(String name, List<Message> messages) {
+    this.messages.put(name, messages);
+
+    for(Message message : messages) {
+      this.status = Status.getWorstStatus(status, message.getStatus());
+    }
+  }
+
   public Status getStatus() {
     return status;
   }
diff --git a/common/src/test/java/org/apache/sqoop/json/TestValidationResultBean.java b/common/src/test/java/org/apache/sqoop/json/TestValidationResultBean.java
new file mode 100644
index 0000000..d9c2043
--- /dev/null
+++ b/common/src/test/java/org/apache/sqoop/json/TestValidationResultBean.java
@@ -0,0 +1,137 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sqoop.json;
+
+import org.apache.sqoop.validation.Message;
+import org.apache.sqoop.validation.Status;
+import org.apache.sqoop.validation.ValidationResult;
+import org.json.simple.JSONObject;
+import org.json.simple.JSONValue;
+import org.junit.Test;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ */
+public class TestValidationResultBean {
+
+  @Test
+  public void testEmptyTransfer() {
+    ValidationResult []empty = new ValidationResult[0];
+
+    ValidationResult []retrieved = transfer(empty);
+    assertEquals(0, retrieved.length);
+  }
+
+  @Test
+  public void testOneMessage() {
+    ValidationResult []empty = new ValidationResult[] {
+      getResultA()
+    };
+
+    ValidationResult []retrieved = transfer(empty);
+    assertEquals(1, retrieved.length);
+    verifyResultA(retrieved[0]);
+  }
+
+  @Test
+  public void testTwoMessages() {
+     ValidationResult []empty = new ValidationResult[] {
+      getResultA(),
+      getResultA()
+    };
+
+    ValidationResult []retrieved = transfer(empty);
+    assertEquals(2, retrieved.length);
+
+    verifyResultA(retrieved[0]);
+    verifyResultA(retrieved[1]);
+  }
+
+  @Test
+  public void testId() {
+    long id = transfer(10L);
+    assertEquals(10L, id);
+
+    Long idNull = transfer((Long)null);
+    assertNull(idNull);
+  }
+
+  public void verifyResultA(ValidationResult result) {
+    assertNotNull(result);
+    assertEquals(Status.UNACCEPTABLE, result.getStatus());
+
+    Map<String, List<Message>> messages = result.getMessages();
+    assertEquals(1, messages.size());
+
+    assertTrue(messages.containsKey("A"));
+    List<Message> messagesA = messages.get("A");
+    assertNotNull(messagesA);
+    assertEquals(2, messagesA.size());
+
+    assertEquals(Status.ACCEPTABLE, messagesA.get(0).getStatus());
+    assertEquals("A", messagesA.get(0).getMessage());
+
+    assertEquals(Status.UNACCEPTABLE, messagesA.get(1).getStatus());
+    assertEquals("B", messagesA.get(1).getMessage());
+  }
+
+  public ValidationResult getResultA() {
+    ValidationResult result = new ValidationResult();
+    List<Message> messages = new LinkedList<Message>();
+    messages.add(new Message(Status.ACCEPTABLE, "A"));
+    messages.add(new Message(Status.UNACCEPTABLE, "B"));
+    result.addMessages("A", messages);
+    return result;
+  }
+
+
+  private Long transfer(Long id) {
+    ValidationResultBean bean = new ValidationResultBean(new ValidationResult[0]);
+    bean.setId(id);
+    JSONObject json = bean.extract(false);
+
+    String string = json.toString();
+
+    JSONObject retrievedJson = (JSONObject) JSONValue.parse(string);
+    ValidationResultBean retrievedBean = new ValidationResultBean();
+    retrievedBean.restore(retrievedJson);
+
+    return retrievedBean.getId();
+  }
+
+  private ValidationResult[] transfer(ValidationResult [] results) {
+    ValidationResultBean bean = new ValidationResultBean(results);
+    JSONObject json = bean.extract(false);
+
+    String string = json.toString();
+
+    JSONObject retrievedJson = (JSONObject) JSONValue.parse(string);
+    ValidationResultBean retrievedBean = new ValidationResultBean();
+    retrievedBean.restore(retrievedJson);
+
+    return retrievedBean.getValidationResults();
+  }
+}
diff --git a/server/src/main/java/org/apache/sqoop/handler/ConnectionRequestHandler.java b/server/src/main/java/org/apache/sqoop/handler/ConnectionRequestHandler.java
index 2721846..89ad3ec 100644
--- a/server/src/main/java/org/apache/sqoop/handler/ConnectionRequestHandler.java
+++ b/server/src/main/java/org/apache/sqoop/handler/ConnectionRequestHandler.java
@@ -24,8 +24,8 @@
 import org.apache.sqoop.connector.spi.SqoopConnector;
 import org.apache.sqoop.framework.FrameworkManager;
 import org.apache.sqoop.json.ConnectionBean;
-import org.apache.sqoop.json.ConnectionValidationBean;
 import org.apache.sqoop.json.JsonBean;
+import org.apache.sqoop.json.ValidationResultBean;
 import org.apache.sqoop.model.FormUtils;
 import org.apache.sqoop.model.MConnection;
 import org.apache.sqoop.model.MConnectionForms;
@@ -36,8 +36,8 @@
 import org.apache.sqoop.server.common.ServerError;
 import org.apache.sqoop.utils.ClassUtils;
 import org.apache.sqoop.validation.Status;
-import org.apache.sqoop.validation.Validation;
-import org.apache.sqoop.validation.Validator;
+import org.apache.sqoop.validation.ValidationResult;
+import org.apache.sqoop.validation.ValidationRunner;
 import org.json.simple.JSONObject;
 import org.json.simple.JSONValue;
 
@@ -176,36 +176,24 @@
     }
 
     // Responsible connector for this session
-    SqoopConnector connector =
-      ConnectorManager.getInstance().getConnector(connection.getConnectorId());
-
-    // Get validator objects
-    Validator connectorValidator = connector.getValidator();
-    Validator frameworkValidator = FrameworkManager.getInstance().getValidator();
+    SqoopConnector connector = ConnectorManager.getInstance().getConnector(connection.getConnectorId());
 
     // We need translate forms to configuration objects
-    Object connectorConfig = ClassUtils.instantiate(
-      connector.getConnectionConfigurationClass());
-    Object frameworkConfig = ClassUtils.instantiate(
-      FrameworkManager.getInstance().getConnectionConfigurationClass());
+    Object connectorConfig = ClassUtils.instantiate(connector.getConnectionConfigurationClass());
+    Object frameworkConfig = ClassUtils.instantiate(FrameworkManager.getInstance().getConnectionConfigurationClass());
 
-    FormUtils.fromForms(
-      connection.getConnectorPart().getForms(), connectorConfig);
-    FormUtils.fromForms(
-      connection.getFrameworkPart().getForms(), frameworkConfig);
+    FormUtils.fromForms(connection.getConnectorPart().getForms(), connectorConfig);
+    FormUtils.fromForms(connection.getFrameworkPart().getForms(), frameworkConfig);
 
     // Validate both parts
-    Validation connectorValidation =
-      connectorValidator.validateConnection(connectorConfig);
-    Validation frameworkValidation =
-      frameworkValidator.validateConnection(frameworkConfig);
+    ValidationRunner validationRunner = new ValidationRunner();
+    ValidationResult connectorValidation = validationRunner.validate(connectorConfig);
+    ValidationResult frameworkValidation = validationRunner.validate(frameworkConfig);
 
-    Status finalStatus = Status.getWorstStatus(connectorValidation.getStatus(),
-      frameworkValidation.getStatus());
+    Status finalStatus = Status.getWorstStatus(connectorValidation.getStatus(), frameworkValidation.getStatus());
 
     // Return back validations in all cases
-    ConnectionValidationBean outputBean =
-      new ConnectionValidationBean(connectorValidation, frameworkValidation);
+    ValidationResultBean outputBean = new ValidationResultBean(connectorValidation, frameworkValidation);
 
     // If we're good enough let's perform the action
     if(finalStatus.canProceed()) {
diff --git a/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java b/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java
index ff99f98..e2fc86c 100644
--- a/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java
+++ b/server/src/main/java/org/apache/sqoop/handler/JobRequestHandler.java
@@ -25,8 +25,8 @@
 import org.apache.sqoop.connector.spi.SqoopConnector;
 import org.apache.sqoop.framework.FrameworkManager;
 import org.apache.sqoop.json.JobBean;
-import org.apache.sqoop.json.JobValidationBean;
 import org.apache.sqoop.json.JsonBean;
+import org.apache.sqoop.json.ValidationResultBean;
 import org.apache.sqoop.model.FormUtils;
 import org.apache.sqoop.model.MJob;
 import org.apache.sqoop.model.MJobForms;
@@ -37,8 +37,8 @@
 import org.apache.sqoop.server.common.ServerError;
 import org.apache.sqoop.utils.ClassUtils;
 import org.apache.sqoop.validation.Status;
-import org.apache.sqoop.validation.Validation;
-import org.apache.sqoop.validation.Validator;
+import org.apache.sqoop.validation.ValidationResult;
+import org.apache.sqoop.validation.ValidationRunner;
 import org.json.simple.JSONObject;
 import org.json.simple.JSONValue;
 
@@ -181,10 +181,8 @@
     }
 
     // Responsible connector for this session
-    SqoopConnector fromConnector =
-      ConnectorManager.getInstance().getConnector(job.getConnectorId(Direction.FROM));
-    SqoopConnector toConnector =
-      ConnectorManager.getInstance().getConnector(job.getConnectorId(Direction.TO));
+    SqoopConnector fromConnector = ConnectorManager.getInstance().getConnector(job.getConnectorId(Direction.FROM));
+    SqoopConnector toConnector = ConnectorManager.getInstance().getConnector(job.getConnectorId(Direction.TO));
 
     if (!fromConnector.getSupportedDirections().contains(Direction.FROM)) {
       throw new SqoopException(ServerError.SERVER_0004, "Connector " + fromConnector.getClass().getCanonicalName()
@@ -196,37 +194,25 @@
           + " does not support TO direction.");
     }
 
-    // Get validator objects
-    Validator fromConnectorValidator = fromConnector.getValidator();
-    Validator frameworkValidator = FrameworkManager.getInstance().getValidator();
-    Validator toConnectorValidator = toConnector.getValidator();
-
     // We need translate forms to configuration objects
-    Object fromConnectorConfig = ClassUtils.instantiate(
-        fromConnector.getJobConfigurationClass(Direction.FROM));
-    Object frameworkConfig = ClassUtils.instantiate(
-      FrameworkManager.getInstance().getJobConfigurationClass());
-    Object toConnectorConfig = ClassUtils.instantiate(
-      toConnector.getJobConfigurationClass(Direction.TO));
+    Object fromConnectorConfig = ClassUtils.instantiate(fromConnector.getJobConfigurationClass(Direction.FROM));
+    Object frameworkConfig = ClassUtils.instantiate(FrameworkManager.getInstance().getJobConfigurationClass());
+    Object toConnectorConfig = ClassUtils.instantiate(toConnector.getJobConfigurationClass(Direction.TO));
 
     FormUtils.fromForms(job.getConnectorPart(Direction.FROM).getForms(), fromConnectorConfig);
     FormUtils.fromForms(job.getFrameworkPart().getForms(), frameworkConfig);
     FormUtils.fromForms(job.getConnectorPart(Direction.TO).getForms(), toConnectorConfig);
 
     // Validate all parts
-    Validation fromConnectorValidation =
-      fromConnectorValidator.validateJob(fromConnectorConfig);
-    Validation frameworkValidation =
-      frameworkValidator.validateJob(frameworkConfig);
-    Validation toConnectorValidation =
-        toConnectorValidator.validateJob(toConnectorConfig);
+    ValidationRunner validationRunner = new ValidationRunner();
+    ValidationResult fromConnectorValidation = validationRunner.validate(fromConnectorConfig);
+    ValidationResult frameworkValidation = validationRunner.validate(frameworkConfig);
+    ValidationResult toConnectorValidation = validationRunner.validate(toConnectorConfig);
 
-    Status finalStatus = Status.getWorstStatus(fromConnectorValidation.getStatus(),
-        frameworkValidation.getStatus(), toConnectorValidation.getStatus());
+    Status finalStatus = Status.getWorstStatus(fromConnectorValidation.getStatus(), frameworkValidation.getStatus(), toConnectorValidation.getStatus());
 
     // Return back validations in all cases
-    JobValidationBean outputBean =
-      new JobValidationBean(fromConnectorValidation, frameworkValidation, toConnectorValidation);
+    ValidationResultBean outputBean = new ValidationResultBean(fromConnectorValidation, frameworkValidation, toConnectorValidation);
 
     // If we're good enough let's perform the action
     if(finalStatus.canProceed()) {