This is an automated email from the ASF dual-hosted git repository.

pdallig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git


The following commit(s) were added to refs/heads/master by this push:
     new 55a614ad16 [ZEPPELIN-5933] Polish jetty (#4621)
55a614ad16 is described below

commit 55a614ad16d220842324f425a159cf41612d76f6
Author: Philipp Dallig <philipp.dal...@gmail.com>
AuthorDate: Tue Jun 27 09:52:53 2023 +0200

    [ZEPPELIN-5933] Polish jetty (#4621)
    
    * Rewrite index.html handling
    
    * Polish initialize of the Rest API
    
    * Don't break the WebApp Classloader Isolation
    
    * Use default SessionHandler
    
    * Add simple session tests
---
 .../apache/zeppelin/server/HtmlAddonResource.java  | 173 ---------------------
 .../apache/zeppelin/server/IndexHtmlServlet.java   |  89 +++++++++++
 .../apache/zeppelin/server/RestApiApplication.java |  59 +++++++
 .../org/apache/zeppelin/server/ZeppelinServer.java |  54 +------
 .../apache/zeppelin/rest/SessionRestApiTest.java   |  84 ++++++++++
 .../zeppelin/server/HtmlAddonResourceTest.java     |  71 ---------
 .../zeppelin/server/IndexHtmlServletTest.java      | 111 +++++++++++++
 zeppelin-web-angular/WEB-INF/web.xml               |  22 +--
 zeppelin-web/src/WEB-INF/web.xml                   |   9 --
 9 files changed, 352 insertions(+), 320 deletions(-)

diff --git 
a/zeppelin-server/src/main/java/org/apache/zeppelin/server/HtmlAddonResource.java
 
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/HtmlAddonResource.java
deleted file mode 100644
index f504bf2007..0000000000
--- 
a/zeppelin-server/src/main/java/org/apache/zeppelin/server/HtmlAddonResource.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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.zeppelin.server;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.charset.StandardCharsets;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.eclipse.jetty.util.resource.Resource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Resource for enabling html addons in index.html.
- */
-public class HtmlAddonResource extends Resource {
-
-    private static final Logger LOGGER = 
LoggerFactory.getLogger(HtmlAddonResource.class);
-
-    private static final String TAG_BODY_OPENING = "<body"; // ignore bracket 
here to support potential html attributes
-    private static final String TAG_BODY_CLOSING = "</body>";
-    private static final String TAG_HEAD_CLOSING = "</head>";
-    private static final String TAG_HTML_CLOSING = "</html>";
-
-    public static final String HTML_ADDON_IDENTIFIER = 
"zeppelin-index-with-addon";
-    public static final String INDEX_HTML_PATH = "/index.html";
-
-    private final Resource indexResource;
-    private File alteredTempFile = null;
-    private byte[] alteredContent;
-
-    public HtmlAddonResource(final Resource indexResource, final String 
bodyAddon, final String headAddon) {
-        LOGGER.info("Enabling html addons in {}: body='{}' head='{}'", 
indexResource, bodyAddon, headAddon);
-        this.indexResource = indexResource;
-        try {
-            // read original content from resource
-            String content = IOUtils.toString(indexResource.getInputStream(), 
StandardCharsets.UTF_8);
-
-            // process body addon
-            if (bodyAddon != null) {
-                if (content.contains(TAG_BODY_CLOSING)) {
-                    content = content.replace(TAG_BODY_CLOSING, bodyAddon + 
TAG_BODY_CLOSING);
-                } else if (content.contains(TAG_HTML_CLOSING)) {
-                    content = content.replace(TAG_HTML_CLOSING, bodyAddon + 
TAG_HTML_CLOSING);
-                } else {
-                    content = content + bodyAddon;
-                }
-            }
-
-            // process head addon
-            if (headAddon != null) {
-                if (content.contains(TAG_HEAD_CLOSING)) {
-                    content = content.replace(TAG_HEAD_CLOSING, headAddon + 
TAG_HEAD_CLOSING);
-                } else if (content.contains(TAG_BODY_OPENING)) {
-                    content = content.replace(TAG_BODY_OPENING, headAddon + 
TAG_BODY_OPENING);
-                } else {
-                    LOGGER.error("Unable to process Head html addon. Could not 
find proper anchor in index.html.");
-                }
-            }
-
-            this.alteredContent = content.getBytes(StandardCharsets.UTF_8);
-
-            // only relevant in development mode: create altered temp file (as 
zeppelin web archives are addressed via local
-            // filesystem folders)
-            if (indexResource.getFile() != null) {
-                this.alteredTempFile = 
File.createTempFile(HTML_ADDON_IDENTIFIER, ".html");
-                this.alteredTempFile.deleteOnExit();
-                FileUtils.writeByteArrayToFile(this.alteredTempFile, 
this.alteredContent);
-            }
-
-        } catch (IOException e) {
-            LOGGER.error("Error initializing html addons.", e);
-        }
-
-    }
-
-    @Override
-    public File getFile() throws IOException {
-        return this.alteredTempFile;
-    }
-
-    @Override
-    public InputStream getInputStream() throws IOException {
-        return new ByteArrayInputStream(this.alteredContent);
-    }
-
-    @Override
-    public String getName() {
-        return indexResource.getName();
-    }
-
-    @Override
-    public boolean isContainedIn(Resource r) throws MalformedURLException {
-        return indexResource.isContainedIn(r);
-    }
-
-    @Override
-    public boolean exists() {
-        return indexResource.exists();
-    }
-
-    @Override
-    public boolean isDirectory() {
-        return indexResource.isDirectory();
-    }
-
-    @Override
-    public long lastModified() {
-        return indexResource.lastModified();
-    }
-
-    @Override
-    public long length() {
-        return alteredContent.length;
-    }
-
-    @Override
-    public URL getURL() {
-        return indexResource.getURL();
-    }
-
-    @Override
-    public ReadableByteChannel getReadableByteChannel() throws IOException {
-        return Channels.newChannel(new 
ByteArrayInputStream(this.alteredContent));
-    }
-
-    @Override
-    public boolean delete() throws SecurityException {
-        throw new UnsupportedOperationException("Not supported");
-    }
-
-    @Override
-    public boolean renameTo(Resource dest) throws SecurityException {
-        throw new UnsupportedOperationException("Not supported");
-    }
-
-    @Override
-    public String[] list() {
-        throw new UnsupportedOperationException("Not supported");
-    }
-
-    @Override
-    public Resource addPath(String path) throws IOException, 
MalformedURLException {
-        throw new UnsupportedOperationException("Not supported");
-    }
-
-    @Override
-    public void close() {
-    }
-
-}
diff --git 
a/zeppelin-server/src/main/java/org/apache/zeppelin/server/IndexHtmlServlet.java
 
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/IndexHtmlServlet.java
new file mode 100644
index 0000000000..10e7cf9d55
--- /dev/null
+++ 
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/IndexHtmlServlet.java
@@ -0,0 +1,89 @@
+/*
+ * 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.zeppelin.server;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.zeppelin.conf.ZeppelinConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IndexHtmlServlet extends HttpServlet {
+
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(IndexHtmlServlet.class);
+
+  /**
+   *
+   */
+  private static final long serialVersionUID = 1L;
+
+  private static final String TAG_BODY_OPENING = "<body"; // ignore bracket 
here to support potential html attributes
+  private static final String TAG_BODY_CLOSING = "</body>";
+  private static final String TAG_HEAD_CLOSING = "</head>";
+  private static final String TAG_HTML_CLOSING = "</html>";
+
+  final String bodyAddon;
+  final String headAddon;
+
+  public IndexHtmlServlet(ZeppelinConfiguration conf) {
+    this.bodyAddon = conf.getHtmlBodyAddon();
+    this.headAddon = conf.getHtmlHeadAddon();
+  }
+
+  @Override
+  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+    throws ServletException, IOException {
+    try {
+      URL indexResource = getServletContext().getResource("/index.html");
+      String content = IOUtils.toString(indexResource, StandardCharsets.UTF_8);
+      // read original content from resource
+      if (bodyAddon != null) {
+        if (content.contains(TAG_BODY_CLOSING)) {
+          content = content.replace(TAG_BODY_CLOSING, bodyAddon + 
TAG_BODY_CLOSING);
+        } else if (content.contains(TAG_HTML_CLOSING)) {
+          content = content.replace(TAG_HTML_CLOSING, bodyAddon + 
TAG_HTML_CLOSING);
+        } else {
+          content = content + bodyAddon;
+        }
+      }
+      // process head addon
+      if (headAddon != null) {
+        if (content.contains(TAG_HEAD_CLOSING)) {
+          content = content.replace(TAG_HEAD_CLOSING, headAddon + 
TAG_HEAD_CLOSING);
+        } else if (content.contains(TAG_BODY_OPENING)) {
+          content = content.replace(TAG_BODY_OPENING, headAddon + 
TAG_BODY_OPENING);
+        } else {
+          LOGGER.error(
+            "Unable to process Head html addon. Could not find proper anchor 
in index.html.");
+        }
+      }
+      resp.setContentType("text/html");
+      resp.setStatus(HttpServletResponse.SC_OK);
+      resp.getWriter().append(content);
+    } catch (IOException e) {
+      LOGGER.error("Error rendering index.html.", e);
+    }
+  }
+}
diff --git 
a/zeppelin-server/src/main/java/org/apache/zeppelin/server/RestApiApplication.java
 
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/RestApiApplication.java
new file mode 100644
index 0000000000..56e29e8742
--- /dev/null
+++ 
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/RestApiApplication.java
@@ -0,0 +1,59 @@
+/*
+ * 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.zeppelin.server;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+
+import org.apache.zeppelin.rest.AdminRestApi;
+import org.apache.zeppelin.rest.ClusterRestApi;
+import org.apache.zeppelin.rest.ConfigurationsRestApi;
+import org.apache.zeppelin.rest.CredentialRestApi;
+import org.apache.zeppelin.rest.HeliumRestApi;
+import org.apache.zeppelin.rest.InterpreterRestApi;
+import org.apache.zeppelin.rest.LoginRestApi;
+import org.apache.zeppelin.rest.NotebookRepoRestApi;
+import org.apache.zeppelin.rest.NotebookRestApi;
+import org.apache.zeppelin.rest.SecurityRestApi;
+import org.apache.zeppelin.rest.SessionRestApi;
+import org.apache.zeppelin.rest.ZeppelinRestApi;
+import org.apache.zeppelin.rest.exception.WebApplicationExceptionMapper;
+
+public class RestApiApplication extends Application {
+  @Override
+  public Set<Class<?>> getClasses() {
+    Set<Class<?>> s = new HashSet<>();
+    s.add(AdminRestApi.class);
+    s.add(ClusterRestApi.class);
+    s.add(ConfigurationsRestApi.class);
+    s.add(CredentialRestApi.class);
+    s.add(HeliumRestApi.class);
+    s.add(InterpreterRestApi.class);
+    s.add(LoginRestApi.class);
+    s.add(NotebookRepoRestApi.class);
+    s.add(NotebookRestApi.class);
+    s.add(SecurityRestApi.class);
+    s.add(SessionRestApi.class);
+    s.add(ZeppelinRestApi.class);
+
+    // add ExceptionMapper
+    s.add(WebApplicationExceptionMapper.class);
+    return s;
+  }
+}
diff --git 
a/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java 
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java
index ae6846d554..86322ebb3b 100644
--- 
a/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java
+++ 
b/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java
@@ -20,8 +20,6 @@ import com.codahale.metrics.servlets.HealthCheckServlet;
 import com.codahale.metrics.servlets.PingServlet;
 import com.google.gson.Gson;
 
-import static 
org.apache.zeppelin.server.HtmlAddonResource.HTML_ADDON_IDENTIFIER;
-
 import io.micrometer.core.instrument.Clock;
 import io.micrometer.core.instrument.Metrics;
 import io.micrometer.core.instrument.Tags;
@@ -111,11 +109,8 @@ import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.ServerConnector;
 import org.eclipse.jetty.server.SslConnectionFactory;
 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
-import org.eclipse.jetty.server.session.SessionHandler;
-import org.eclipse.jetty.servlet.DefaultServlet;
 import org.eclipse.jetty.servlet.FilterHolder;
 import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.util.resource.Resource;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.webapp.WebAppContext;
 import 
org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
@@ -125,13 +120,12 @@ import org.glassfish.hk2.api.ServiceLocator;
 import org.glassfish.hk2.api.ServiceLocatorFactory;
 import org.glassfish.hk2.utilities.ServiceLocatorUtilities;
 import org.glassfish.hk2.utilities.binding.AbstractBinder;
-import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.servlet.ServletProperties;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /** Main class of Zeppelin. */
-public class ZeppelinServer extends ResourceConfig {
+public class ZeppelinServer {
   private static final Logger LOG = 
LoggerFactory.getLogger(ZeppelinServer.class);
   private static final String WEB_APP_CONTEXT_NEXT = "/next";
 
@@ -141,8 +135,6 @@ public class ZeppelinServer extends ResourceConfig {
   public ZeppelinServer(ZeppelinConfiguration conf) {
     LOG.info("Instantiated ZeppelinServer");
     InterpreterOutput.LIMIT = 
conf.getInt(ConfVars.ZEPPELIN_INTERPRETER_OUTPUT_LIMIT);
-
-    packages("org.apache.zeppelin.rest");
   }
 
   public static void main(String[] args) throws IOException {
@@ -549,9 +541,8 @@ public class ZeppelinServer extends ResourceConfig {
     final ServletHolder servletHolder =
         new ServletHolder(new org.glassfish.jersey.servlet.ServletContainer());
 
-    servletHolder.setInitParameter("javax.ws.rs.Application", 
ZeppelinServer.class.getName());
+    servletHolder.setInitParameter("javax.ws.rs.Application", 
RestApiApplication.class.getName());
     servletHolder.setName("rest");
-    webapp.setSessionHandler(new SessionHandler());
     webapp.addServlet(servletHolder, "/api/*");
 
     String shiroIniPath = conf.getShiroPath();
@@ -584,7 +575,6 @@ public class ZeppelinServer extends ResourceConfig {
       // Development mode, read from FS
       // webApp.setDescriptor(warPath+"/WEB-INF/web.xml");
       webApp.setResourceBase(warFile.getPath());
-      webApp.setParentLoaderPriority(true);
     } else {
       // use packaged WAR
       webApp.setWar(warFile.getAbsolutePath());
@@ -595,7 +585,7 @@ public class ZeppelinServer extends ResourceConfig {
       webApp.setTempDirectory(warTempDirectory);
     }
     // Explicit bind to root
-    webApp.addServlet(new ServletHolder(setupServlet(webApp, conf)), "/*");
+    webApp.addServlet(new ServletHolder(new IndexHtmlServlet(conf)), 
"/index.html");
     contexts.addHandler(webApp);
 
     webApp.addFilter(new FilterHolder(CorsFilter.class), "/*", 
EnumSet.allOf(DispatcherType.class));
@@ -606,44 +596,6 @@ public class ZeppelinServer extends ResourceConfig {
     return webApp;
   }
 
-  private static DefaultServlet setupServlet(
-      WebAppContext webApp,
-      ZeppelinConfiguration conf) {
-
-    // provide DefaultServlet as is in case html addon is not used
-    if (conf.getHtmlBodyAddon()==null && conf.getHtmlHeadAddon()==null) {
-      return new DefaultServlet();
-    }
-
-    // override ResourceFactory interface part of DefaultServlet for 
intercepting the static index.html properly.
-    return new DefaultServlet() {
-
-        private static final long serialVersionUID = 1L;
-
-        @Override
-        public Resource getResource(String pathInContext) {
-
-            // proceed for everything but '/index.html'
-            if (!HtmlAddonResource.INDEX_HTML_PATH.equals(pathInContext)) {
-                return super.getResource(pathInContext);
-            }
-
-            // create the altered 'index.html' resource and cache it via 
webapp attributes
-            if (webApp.getAttribute(HTML_ADDON_IDENTIFIER) == null) {
-                webApp.setAttribute(
-                    HTML_ADDON_IDENTIFIER,
-                    new HtmlAddonResource(
-                        super.getResource(pathInContext),
-                        conf.getHtmlBodyAddon(),
-                        conf.getHtmlHeadAddon()));
-            }
-
-            return (Resource) webApp.getAttribute(HTML_ADDON_IDENTIFIER);
-        }
-
-    };
-  }
-
   private static void initWebApp(WebAppContext webApp, ZeppelinConfiguration 
conf, ServiceLocator sharedServiceLocator, PrometheusMeterRegistry 
promMetricRegistry) {
     webApp.addEventListener(
             new ServletContextListener() {
diff --git 
a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/SessionRestApiTest.java
 
b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/SessionRestApiTest.java
new file mode 100644
index 0000000000..dfca0202dd
--- /dev/null
+++ 
b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/SessionRestApiTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.zeppelin.rest;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.util.EntityUtils;
+import org.apache.zeppelin.common.SessionInfo;
+import org.apache.zeppelin.server.JsonResponse;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
+import javax.ws.rs.core.Response.Status;
+
+class SessionRestApiTest extends AbstractTestRestApi {
+  Gson gson = new Gson();
+
+  @BeforeAll
+  static void init() throws Exception {
+    AbstractTestRestApi.startUp(SessionRestApi.class.getSimpleName());
+  }
+
+  @AfterAll
+  static void destroy() throws Exception {
+    AbstractTestRestApi.shutDown();
+  }
+
+  @Test
+  void testGetNotAvailableSession() throws IOException {
+    try (CloseableHttpResponse get = httpGet("/session/testSession")) {
+      assertEquals(Status.NOT_FOUND.getStatusCode(), 
get.getStatusLine().getStatusCode());
+    }
+  }
+
+  @Test
+  void testStartAndStopSession() throws IOException {
+    String interpreter = "testInterpreter";
+    try (CloseableHttpResponse post = httpPost("/session?interpreter=" + 
interpreter, "")) {
+      assertEquals(Status.OK.getStatusCode(), 
post.getStatusLine().getStatusCode());
+      Type collectionType = new TypeToken<JsonResponse<SessionInfo>>() {
+      }.getType();
+      JsonResponse<SessionInfo> resp = gson
+        .fromJson(EntityUtils.toString(post.getEntity(), 
StandardCharsets.UTF_8), collectionType);
+      SessionInfo info = resp.getBody();
+
+      // Get by interpreter name
+      try (CloseableHttpResponse get = httpGet("/session?interpreter" + 
interpreter)) {
+        assertEquals(Status.OK.getStatusCode(), 
get.getStatusLine().getStatusCode());
+      }
+
+      // Get by sessionId
+      try (CloseableHttpResponse get = httpGet("/session/" + 
info.getSessionId())) {
+        assertEquals(Status.OK.getStatusCode(), 
get.getStatusLine().getStatusCode());
+      }
+
+      // Delete session
+      try (CloseableHttpResponse delete = httpDelete("/session/" + 
info.getSessionId())) {
+        assertEquals(Status.OK.getStatusCode(), 
delete.getStatusLine().getStatusCode());
+      }
+    }
+
+  }
+}
diff --git 
a/zeppelin-server/src/test/java/org/apache/zeppelin/server/HtmlAddonResourceTest.java
 
b/zeppelin-server/src/test/java/org/apache/zeppelin/server/HtmlAddonResourceTest.java
deleted file mode 100644
index 65d51d9fe7..0000000000
--- 
a/zeppelin-server/src/test/java/org/apache/zeppelin/server/HtmlAddonResourceTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.zeppelin.server;
-
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-
-import org.apache.commons.io.IOUtils;
-import org.eclipse.jetty.util.resource.Resource;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-class HtmlAddonResourceTest {
-
-    private final static String TEST_BODY_ADDON = "<!-- foo -->";
-    private final static String TEST_HEAD_ADDON = "<!-- bar -->";
-
-    private final static String FILE_PATH_INDEX_HTML_ZEPPELIN_WEB = 
"../zeppelin-web/dist/index.html";
-    private final static String FILE_PATH_INDEX_HTML_ZEPPELIN_WEB_ANGULAR = 
"../zeppelin-web-angular/dist/zeppelin/index.html";
-
-    @Test
-    void testZeppelinWebHtmlAddon() throws IOException {
-        final Resource addonResource = 
getHtmlAddonResource(FILE_PATH_INDEX_HTML_ZEPPELIN_WEB);
-
-        final String content = 
IOUtils.toString(addonResource.getInputStream(), StandardCharsets.UTF_8);
-
-        assertThat(content, containsString(TEST_BODY_ADDON));
-        assertThat(content, containsString(TEST_HEAD_ADDON));
-
-    }
-
-    @Test
-    @Disabled // ignored due to zeppelin-web-angular not build for core tests
-    void testZeppelinWebAngularHtmlAddon() throws IOException {
-        final Resource addonResource = 
getHtmlAddonResource(FILE_PATH_INDEX_HTML_ZEPPELIN_WEB_ANGULAR);
-
-        final String content = 
IOUtils.toString(addonResource.getInputStream(), StandardCharsets.UTF_8);
-
-        assertThat(content, containsString(TEST_BODY_ADDON));
-        assertThat(content, containsString(TEST_HEAD_ADDON));
-
-    }
-
-    private Resource getHtmlAddonResource(final String indexHtmlPath) {
-        return getHtmlAddonResource(indexHtmlPath, TEST_BODY_ADDON, 
TEST_HEAD_ADDON);
-    }
-
-    private Resource getHtmlAddonResource(final String indexHtmlPath, final 
String bodyAddon, final String headAddon) {
-        final Resource indexResource = Resource.newResource(new 
File(indexHtmlPath));
-        return new HtmlAddonResource(indexResource, TEST_BODY_ADDON, 
TEST_HEAD_ADDON);
-    }
-
-}
diff --git 
a/zeppelin-server/src/test/java/org/apache/zeppelin/server/IndexHtmlServletTest.java
 
b/zeppelin-server/src/test/java/org/apache/zeppelin/server/IndexHtmlServletTest.java
new file mode 100644
index 0000000000..5e8173df96
--- /dev/null
+++ 
b/zeppelin-server/src/test/java/org/apache/zeppelin/server/IndexHtmlServletTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.zeppelin.server;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URL;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.zeppelin.conf.ZeppelinConfiguration;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+class IndexHtmlServletTest {
+
+    private final static String TEST_BODY_ADDON = "<!-- foo -->";
+    private final static String TEST_HEAD_ADDON = "<!-- bar -->";
+
+    private final static String FILE_PATH_INDEX_HTML_ZEPPELIN_WEB = 
"../zeppelin-web/dist/index.html";
+    private final static String FILE_PATH_INDEX_HTML_ZEPPELIN_WEB_ANGULAR = 
"../zeppelin-web-angular/dist/zeppelin/index.html";
+
+
+    @Test
+    void testZeppelinWebHtmlAddon() throws IOException, ServletException {
+      ZeppelinConfiguration conf = mock(ZeppelinConfiguration.class);
+      when(conf.getHtmlBodyAddon()).thenReturn(TEST_BODY_ADDON);
+      when(conf.getHtmlHeadAddon()).thenReturn(TEST_HEAD_ADDON);
+
+      ServletConfig sc = mock(ServletConfig.class);
+      ServletContext ctx = mock(ServletContext.class);
+      when(ctx.getResource("/index.html"))
+        .thenReturn(new URL("file:" + FILE_PATH_INDEX_HTML_ZEPPELIN_WEB));
+      when(sc.getServletContext()).thenReturn(ctx);
+
+      IndexHtmlServlet servlet = new IndexHtmlServlet(conf);
+      servlet.init(sc);
+
+      HttpServletResponse mockResponse = mock(HttpServletResponse.class);
+      HttpServletRequest mockRequest = mock(HttpServletRequest.class);
+
+      // Catch content in ByteArrayOutputStream
+      ByteArrayOutputStream out = new ByteArrayOutputStream();
+      PrintWriter writer = new PrintWriter(out);
+      when(mockResponse.getWriter()).thenReturn(writer);
+
+      servlet.doGet(mockRequest, mockResponse);
+      writer.flush();
+      // Get Content
+      String content = new String(out.toString());
+
+      assertThat(content, containsString(TEST_BODY_ADDON));
+      assertThat(content, containsString(TEST_HEAD_ADDON));
+
+    }
+
+    @Test
+    @Disabled("ignored due to zeppelin-web-angular not build for core tests")
+    void testZeppelinWebAngularHtmlAddon() throws IOException, 
ServletException {
+      ZeppelinConfiguration conf = mock(ZeppelinConfiguration.class);
+      when(conf.getHtmlBodyAddon()).thenReturn(TEST_BODY_ADDON);
+      when(conf.getHtmlHeadAddon()).thenReturn(TEST_HEAD_ADDON);
+
+      ServletConfig sc = mock(ServletConfig.class);
+      ServletContext ctx = mock(ServletContext.class);
+      when(ctx.getResource("/index.html"))
+        .thenReturn(new URL("file:" + 
FILE_PATH_INDEX_HTML_ZEPPELIN_WEB_ANGULAR));
+      when(sc.getServletContext()).thenReturn(ctx);
+
+      IndexHtmlServlet servlet = new IndexHtmlServlet(conf);
+      servlet.init(sc);
+
+      HttpServletResponse mockResponse = mock(HttpServletResponse.class);
+      HttpServletRequest mockRequest = mock(HttpServletRequest.class);
+      ByteArrayOutputStream out = new ByteArrayOutputStream();
+      PrintWriter writer = new PrintWriter(out);
+      when(mockResponse.getWriter()).thenReturn(writer);
+
+      servlet.doGet(mockRequest, mockResponse);
+      writer.flush();
+      // Get Content
+      String content = new String(out.toString());
+
+      assertThat(content, containsString(TEST_BODY_ADDON));
+      assertThat(content, containsString(TEST_HEAD_ADDON));
+
+    }
+}
diff --git a/zeppelin-web-angular/WEB-INF/web.xml 
b/zeppelin-web-angular/WEB-INF/web.xml
index f40bf86173..43524f4f90 100644
--- a/zeppelin-web-angular/WEB-INF/web.xml
+++ b/zeppelin-web-angular/WEB-INF/web.xml
@@ -12,25 +12,15 @@
   -->
 
 <web-app xmlns="http://java.sun.com/xml/ns/javaee"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd";
-       version="3.0">
+  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd";
+  version="3.0">
 
  <display-name>zeppelin-web-angular</display-name>
-       <servlet>
-               <servlet-name>default</servlet-name>
-    
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
-    <init-param>
-      <param-name>jersey.config.server.provider.packages</param-name>
-      <param-value>org.apache.zeppelin.rest</param-value>
-    </init-param>
 
-               <load-on-startup>1</load-on-startup>
-       </servlet>
-
-       <context-param>
-               <param-name>configuration</param-name>
-               <param-value>deployment</param-value>
-       </context-param>
+  <context-param>
+    <param-name>configuration</param-name>
+    <param-value>deployment</param-value>
+  </context-param>
 
   <session-config>
     <cookie-config>
diff --git a/zeppelin-web/src/WEB-INF/web.xml b/zeppelin-web/src/WEB-INF/web.xml
index f7094028fe..179bd02818 100644
--- a/zeppelin-web/src/WEB-INF/web.xml
+++ b/zeppelin-web/src/WEB-INF/web.xml
@@ -22,15 +22,6 @@
          version="3.0">
 
   <display-name>zeppelin-web</display-name>
-  <servlet>
-    <servlet-name>restServlet</servlet-name>
-    
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
-    <init-param>
-      <param-name>jersey.config.server.provider.packages</param-name>
-      <param-value>org.apache.zeppelin.rest</param-value>
-    </init-param>
-    <load-on-startup>1</load-on-startup>
-  </servlet>
 
   <error-page>
     <error-code>404</error-code>

Reply via email to