You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by mp...@apache.org on 2014/01/23 17:30:13 UTC

git commit: AMBARI-4335. Configure Jetty to return errors as JSON. (mpapirkovskyy)

Updated Branches:
  refs/heads/trunk 49de3a349 -> 90f00a2a4


AMBARI-4335. Configure Jetty to return errors as JSON. (mpapirkovskyy)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/90f00a2a
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/90f00a2a
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/90f00a2a

Branch: refs/heads/trunk
Commit: 90f00a2a4267a7a94e8c89ade790ca7b71d8199a
Parents: 49de3a3
Author: Myroslav Papirkovskyy <mp...@hortonworks.com>
Authored: Thu Jan 23 18:28:01 2014 +0200
Committer: Myroslav Papirkovskyy <mp...@hortonworks.com>
Committed: Thu Jan 23 18:28:01 2014 +0200

----------------------------------------------------------------------
 .../ambari/server/api/AmbariErrorHandler.java   |  62 +++++++++++
 .../ambari/server/controller/AmbariServer.java  |   3 +
 .../server/controller/ControllerModule.java     |   3 +
 .../server/api/AmbariErrorHandlerTest.java      | 104 +++++++++++++++++++
 4 files changed, 172 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/90f00a2a/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariErrorHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariErrorHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariErrorHandler.java
new file mode 100644
index 0000000..ee4e56f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/AmbariErrorHandler.java
@@ -0,0 +1,62 @@
+/*
+ * 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.ambari.server.api;
+
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.http.MimeTypes;
+import org.eclipse.jetty.server.AbstractHttpConnection;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.ErrorHandler;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class AmbariErrorHandler extends ErrorHandler {
+  private final Gson gson;
+
+  @Inject
+  public AmbariErrorHandler(@Named("prettyGson") Gson prettyGson) {
+    this.gson = prettyGson;
+  }
+
+  @Override
+  public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException {
+    AbstractHttpConnection connection = AbstractHttpConnection.getCurrentConnection();
+    connection.getRequest().setHandled(true);
+
+    response.setContentType(MimeTypes.TEXT_PLAIN);
+
+    Map<String, Object> errorMap = new LinkedHashMap<String, Object>();
+    int code = connection.getResponse().getStatus();
+    errorMap.put("status", code);
+    String message = connection.getResponse().getReason();
+    if (message == null) {
+      message = HttpStatus.getMessage(code);
+    }
+    errorMap.put("message", message);
+
+    gson.toJson(errorMap, response.getWriter());
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/90f00a2a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index e745994..00f1b74 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -31,6 +31,7 @@ import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.ActionManager;
 import org.apache.ambari.server.agent.HeartBeatHandler;
 import org.apache.ambari.server.agent.rest.AgentResource;
+import org.apache.ambari.server.api.AmbariErrorHandler;
 import org.apache.ambari.server.api.AmbariPersistFilter;
 import org.apache.ambari.server.api.rest.BootStrapResource;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
@@ -167,6 +168,8 @@ public class AmbariServer {
       ServletContextHandler root = new ServletContextHandler(server, CONTEXT_PATH,
           ServletContextHandler.SECURITY | ServletContextHandler.SESSIONS);
 
+      root.setErrorHandler(injector.getInstance(AmbariErrorHandler.class));
+
       //Changing session cookie name to avoid conflicts
       root.getSessionHandler().getSessionManager().setSessionCookie("AMBARISESSIONID");
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/90f00a2a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index 2b93e54..adb78c3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -76,6 +76,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
 
+import com.google.gson.GsonBuilder;
 import static org.eclipse.persistence.config.PersistenceUnitProperties.CREATE_JDBC_DDL_FILE;
 import static org.eclipse.persistence.config.PersistenceUnitProperties.CREATE_ONLY;
 import static org.eclipse.persistence.config.PersistenceUnitProperties.CREATE_OR_EXTEND;
@@ -98,6 +99,7 @@ public class ControllerModule extends AbstractModule {
   private final Configuration configuration;
   private final HostsMap hostsMap;
   private boolean dbInitNeeded;
+  private final Gson prettyGson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();
 
   public ControllerModule() throws Exception {
     configuration = new Configuration();
@@ -116,6 +118,7 @@ public class ControllerModule extends AbstractModule {
     bind(Configuration.class).toInstance(configuration);
     bind(HostsMap.class).toInstance(hostsMap);
     bind(PasswordEncoder.class).toInstance(new StandardPasswordEncoder());
+    bind(Gson.class).annotatedWith(Names.named("prettyGson")).toInstance(prettyGson);
 
     install(buildJpaPersistModule());
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/90f00a2a/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java
new file mode 100644
index 0000000..fb41f6e
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/api/AmbariErrorHandlerTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.ambari.server.api;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+import com.sun.jersey.api.client.*;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.servlet.DefaultServlet;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.junit.Test;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+public class AmbariErrorHandlerTest {
+  Gson gson = new Gson();
+
+
+  @Test
+  public void testHandle() throws Exception {
+
+  }
+
+  @Test
+  public void testErrorWithJetty() throws Exception {
+    Server server = new Server(0);
+
+    ServletContextHandler root = new ServletContextHandler(server, "/",
+      ServletContextHandler.SECURITY | ServletContextHandler.SESSIONS);
+
+    root.addServlet(HelloServlet.class, "/hello");
+    root.addServlet(DefaultServlet.class, "/");
+    root.setErrorHandler(new AmbariErrorHandler(gson));
+
+    server.start();
+
+    int localPort = server.getConnectors()[0].getLocalPort();
+
+    Client client = new Client();
+    WebResource resource = client.resource("http://localhost:" + localPort + "/");
+
+
+    ClientResponse successResponse = resource.path("hello").get(ClientResponse.class);
+    assertEquals(HttpServletResponse.SC_OK, successResponse.getStatus());
+
+    ClientResponse failResponse = resource.path("fail").get(ClientResponse.class);
+
+    assertEquals(HttpServletResponse.SC_NOT_FOUND, failResponse.getStatus());
+
+    try {
+      String response = failResponse.getEntity(String.class);
+      System.out.println(response);
+      Map map;
+      map = gson.fromJson(response, Map.class);
+      System.out.println(map);
+      assertNotNull("Incorrect response status", map.get("status"));
+      assertNotNull("Incorrect response message", map.get("message"));
+    } catch (JsonSyntaxException e1) {
+      fail("Incorrect response");
+    }
+
+
+    server.stop();
+  }
+
+
+  @SuppressWarnings("serial")
+  public static class HelloServlet extends HttpServlet {
+    @Override
+    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+      response.setContentType("text/html");
+      response.setStatus(HttpServletResponse.SC_OK);
+      response.getWriter().println("hello");
+    }
+
+  }
+}