diff --git a/pom.xml b/pom.xml
index 4a0b1f0454925a1a0abc7c3fcbb46dd835928a5a..2b5604137e291510bb99c826b8677d0d2a6188b2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,7 +84,7 @@
         <artifactId>maven-surefire-plugin</artifactId>
         <version>2.14.1</version>
         <configuration>
-          <skipTests>true</skipTests>
+          <skipTests>${skipTests}</skipTests>
         </configuration>
       </plugin>
       <plugin>
@@ -174,6 +174,7 @@
     <maven.build.timestamp.format>yyyyMMdd-HHmm
     </maven.build.timestamp.format>
     <timestamp>${maven.build.timestamp}</timestamp>
+    <skipTests>true</skipTests>
   </properties>
   <dependencies>
     <dependency>
@@ -191,11 +192,6 @@
       <artifactId>codemirror</artifactId>
       <version>3.21</version>
     </dependency>
-    <dependency>
-      <groupId>HTTPClient</groupId>
-      <artifactId>HTTPClient</artifactId>
-      <version>0.3-3</version>
-    </dependency>
     <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>servlet-api</artifactId>
@@ -205,19 +201,13 @@
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>4.13.1</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>httpunit</groupId>
-      <artifactId>httpunit</artifactId>
-      <version>1.7</version>
+      <version>4.13.2</version>
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>rhino</groupId>
-      <artifactId>js</artifactId>
-      <version>1.7R2</version>
+      <groupId>net.sourceforge.htmlunit</groupId>
+      <artifactId>htmlunit</artifactId>
+      <version>2.53.0</version>
       <scope>test</scope>
     </dependency>
     <dependency>
diff --git a/src/main/java/net/sourceforge/plantuml/servlet/OldProxyServlet.java b/src/main/java/net/sourceforge/plantuml/servlet/OldProxyServlet.java
index 9aeecc55b482fde14ebfb4af4de80cc7f828fc5e..50b068494c5bce06023961f3d43bee4ecd7e043d 100644
--- a/src/main/java/net/sourceforge/plantuml/servlet/OldProxyServlet.java
+++ b/src/main/java/net/sourceforge/plantuml/servlet/OldProxyServlet.java
@@ -23,23 +23,19 @@
  */
 package net.sourceforge.plantuml.servlet;
 
+import java.io.BufferedReader;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.net.URL;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import HTTPClient.CookieModule;
-import HTTPClient.HTTPConnection;
-import HTTPClient.HTTPResponse;
-import HTTPClient.ModuleException;
-import HTTPClient.ParseException;
-
 import net.sourceforge.plantuml.FileFormat;
 import net.sourceforge.plantuml.FileFormatOption;
 import net.sourceforge.plantuml.SourceStringReader;
@@ -52,54 +48,50 @@ import net.sourceforge.plantuml.SourceStringReader;
 @SuppressWarnings("serial")
 public class OldProxyServlet extends HttpServlet {
 
-    private static final Pattern PROXY_PATTERN = Pattern.compile("/\\w+/proxy/((\\d+)/)?((\\w+)/)?(http://.*)");
+    private static final Pattern PROXY_PATTERN = Pattern.compile("/\\w+/proxy/((\\d+)/)?((\\w+)/)?(https?://.*)");
     private String format;
 
     @Override
     public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
-
         final String uri = request.getRequestURI();
 
+        // Check if the src URL is valid
         Matcher proxyMatcher = PROXY_PATTERN.matcher(uri);
-        if (proxyMatcher.matches()) {
-            String num = proxyMatcher.group(2); // Optional number of the diagram source
-            format = proxyMatcher.group(4); // Expected format of the generated diagram
-            String sourceURL = proxyMatcher.group(5);
-            handleImageProxy(response, num, sourceURL);
-        } else {
-            request.setAttribute("net.sourceforge.plantuml.servlet.decoded", "ERROR Invalid proxy syntax : " + uri);
-            request.removeAttribute("net.sourceforge.plantuml.servlet.encoded");
-
-            // forward to index.jsp
-            RequestDispatcher dispatcher = request.getRequestDispatcher("/index.jsp");
-            dispatcher.forward(request, response);
+        if (!proxyMatcher.matches()) {
+            // Bad URI format.
+            response.setStatus(400);
+            return;
         }
+
+        String num = proxyMatcher.group(2); // Optional number of the diagram source
+        format = proxyMatcher.group(4); // Expected format of the generated diagram
+        String sourceURL = proxyMatcher.group(5);
+        handleImageProxy(response, num, sourceURL);
     }
 
     private void handleImageProxy(HttpServletResponse response, String num, String source) throws IOException {
         SourceStringReader reader = new SourceStringReader(getSource(source));
         int n = num == null ? 0 : Integer.parseInt(num);
 
-        reader.generateImage(response.getOutputStream(), n, new FileFormatOption(getOutputFormat(), false));
+        FileFormat fileFormat = getOutputFormat();
+        response.addHeader("Content-Type", fileFormat.getMimeType());
+        reader.outputImage(response.getOutputStream(), n, new FileFormatOption(fileFormat, false));
     }
 
-    private String getSource(String uri) throws IOException {
-        CookieModule.setCookiePolicyHandler(null);
-
-        final Pattern p = Pattern.compile("http://[^/]+(/?.*)");
-        final Matcher m = p.matcher(uri);
-        if (m.find() == false) {
-            throw new IOException(uri);
-        }
+    private String getSource(final String uri) throws IOException {
         final URL url = new URL(uri);
-        final HTTPConnection httpConnection = new HTTPConnection(url);
-        try {
-            final HTTPResponse resp = httpConnection.Get(m.group(1));
-            return resp.getText();
-        } catch (ModuleException e) {
-            throw new IOException(e.toString());
-        } catch (ParseException e) {
-            throw new IOException(e.toString());
+        try (
+            InputStream responseStream = url.openStream();
+            InputStreamReader isr = new InputStreamReader(responseStream);
+            BufferedReader br = new BufferedReader(isr);
+        ) {
+            String line;
+            StringBuffer sb = new StringBuffer();
+            while ((line = br.readLine()) != null) {
+                sb.append(line);
+                sb.append("\n");
+            }
+            return sb.toString().trim();
         }
     }
 
diff --git a/src/main/java/net/sourceforge/plantuml/servlet/ProxyServlet.java b/src/main/java/net/sourceforge/plantuml/servlet/ProxyServlet.java
index eed3887d44fd341eb59bc5d21a49a3f163e7511f..d1d0053db207ac71170f65e75d1baa9db0a3c22d 100644
--- a/src/main/java/net/sourceforge/plantuml/servlet/ProxyServlet.java
+++ b/src/main/java/net/sourceforge/plantuml/servlet/ProxyServlet.java
@@ -76,6 +76,7 @@ public class ProxyServlet extends HttpServlet {
             srcUrl = new URL(source);
         } catch (MalformedURLException mue) {
             mue.printStackTrace();
+            response.setStatus(400);
             return;
         }
 
diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp
index 36100efece8775d4f08cdda7e03f694a6fcbced9..717df36763a363bd2f03694b88779f7847a422d5 100644
--- a/src/main/webapp/index.jsp
+++ b/src/main/webapp/index.jsp
@@ -33,7 +33,7 @@
     <!-- <script src="mode/plantuml.js"></script> -->
     <script>
         window.onload = function() {
-            var myCodeMirror = CodeMirror.fromTextArea(
+            document.myCodeMirror = CodeMirror.fromTextArea(
                 document.getElementById("text"), 
                 {lineNumbers: true}
             );
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestAsciiArt.java b/src/test/java/net/sourceforge/plantuml/servlet/TestAsciiArt.java
index ad66186ccbb9106bc58cab0605e857bd85b9eecc..f35fe755556b55c25e9c78d86471f3f316df7d9f 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/TestAsciiArt.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/TestAsciiArt.java
@@ -1,25 +1,27 @@
 package net.sourceforge.plantuml.servlet;
 
-import com.meterware.httpunit.GetMethodWebRequest;
-import com.meterware.httpunit.WebConversation;
-import com.meterware.httpunit.WebRequest;
-import com.meterware.httpunit.WebResponse;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
 
 public class TestAsciiArt extends WebappTestCase {
 
     /**
      * Verifies the generation of the ascii art for the Bob -> Alice sample
      */
-    public void testSimpleSequenceDiagram() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "txt/" + TestUtils.SEQBOB);
-        WebResponse response = conversation.getResource(request);
+    public void testSimpleSequenceDiagram() throws IOException {
+        final URL url = new URL(getServerUrl() + "/txt/" + TestUtils.SEQBOB);
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        assertEquals("Response content type is not TEXT PLAIN", "text/plain", response.getContentType());
-        assertEquals("Response character set is not UTF-8", "UTF-8", response.getCharacterSet());
+        assertEquals(
+            "Response content type is not TEXT PLAIN or UTF-8",
+            "text/plain;charset=utf-8",
+            conn.getContentType().toLowerCase()
+        );
         // Get the content and verify its size
-        String diagram = response.getText();
+        String diagram = getContentText(conn);
         int diagramLen = diagram.length();
         assertTrue(diagramLen > 200);
         assertTrue(diagramLen < 250);
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestCharset.java b/src/test/java/net/sourceforge/plantuml/servlet/TestCharset.java
index 1ce3e53933300aaf3f1d1ad0769c4a8fb94d8cbe..aa488ed6fe2d0d61f65aca20c75783500063018c 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/TestCharset.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/TestCharset.java
@@ -1,24 +1,27 @@
 package net.sourceforge.plantuml.servlet;
 
-import com.meterware.httpunit.GetMethodWebRequest;
-import com.meterware.httpunit.WebConversation;
-import com.meterware.httpunit.WebRequest;
-import com.meterware.httpunit.WebResponse;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
 
 public class TestCharset extends WebappTestCase {
 
     /**
      * Verifies the preservation of unicode characters for the "Bob -> Alice : hell‽" sample
      */
-    public void testUnicodeSupport() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "txt/SyfFKj2rKt3CoKnELR1Io4ZDoNdKi1S0");
-        WebResponse response = conversation.getResource(request);
+    public void testUnicodeSupport() throws IOException {
+        final URL url = new URL(getServerUrl() + "/txt/SyfFKj2rKt3CoKnELR1Io4ZDoNdKi1S0");
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        assertEquals("Response content type is not TEXT PLAIN", "text/plain", response.getContentType());
+        assertEquals(
+            "Response content type is not TEXT PLAIN or UTF-8",
+            "text/plain;charset=utf-8",
+            conn.getContentType().toLowerCase()
+        );
         // Get the content and verify that the interrobang unicode character is present
-        String diagram = response.getText();
+        String diagram = getContentText(conn);
         assertTrue("Interrobang unicode character is not preserved", diagram.contains("‽"));
     }
 
@@ -26,18 +29,22 @@ public class TestCharset extends WebappTestCase {
      * Verifies the preservation of unicode characters for the
      * "participant Bob [[http://www.snow.com/❄]]\nBob -> Alice" sample
      */
-    public void testUnicodeInCMap() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl()
-                + "map/AqWiAibCpYn8p2jHSCfFKeYEpYWfAR3IroylBzShpiilrqlEpzL_DBSbDfOB9Azhf-2OavcS2W00");
-        WebResponse response = conversation.getResource(request);
+    public void testUnicodeInCMap() throws IOException {
+        final URL url = new URL(
+            getServerUrl() +
+            "/map/AqWiAibCpYn8p2jHSCfFKeYEpYWfAR3IroylBzShpiilrqlEpzL_DBSbDfOB9Azhf-2OavcS2W00"
+        );
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        assertEquals("Response content type is not TEXT PLAIN", "text/plain", response.getContentType());
+        assertEquals(
+            "Response content type is not TEXT PLAIN or UTF-8",
+            "text/plain;charset=utf-8",
+            conn.getContentType().toLowerCase()
+        );
         // Get the content and verify that the snow unicode character is present
-        String map = response.getText();
+        String map = getContentText(conn);
         assertTrue("Snow unicode character is not preserved", map.contains("❄"));
     }
 
-
 }
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestCheck.java b/src/test/java/net/sourceforge/plantuml/servlet/TestCheck.java
index 88ca721ca150224d0906530accad6998ec23ea26..f7f5a4837e9a9681b693e49eb235b00d4e4e9ca2 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/TestCheck.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/TestCheck.java
@@ -1,28 +1,32 @@
 package net.sourceforge.plantuml.servlet;
 
-import com.meterware.httpunit.GetMethodWebRequest;
-import com.meterware.httpunit.WebConversation;
-import com.meterware.httpunit.WebRequest;
-import com.meterware.httpunit.WebResponse;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
 
 public class TestCheck extends WebappTestCase {
+
     /**
      * Verifies the generation of a syntax check for the following sample:
      * Bob -> Alice : hello
      */
-    public void testCorrectSequenceDiagram() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl()
-            + "check/" + TestUtils.SEQBOB);
-        WebResponse response = conversation.getResource(request);
+    public void testCorrectSequenceDiagram() throws IOException {
+        final URL url = new URL(getServerUrl() + "/check/" + TestUtils.SEQBOB);
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        assertEquals("Response content type is not TEXT PLAIN", "text/plain", response.getContentType());
-        assertEquals("Response character set is not UTF-8", "UTF-8", response.getCharacterSet());
+        assertEquals(
+            "Response content type is not TEXT PLAIN or UTF-8",
+            "text/plain;charset=utf-8",
+            conn.getContentType().toLowerCase()
+        );
         // Get the content, check its first characters and verify its size
-        String checkResult = response.getText();
-        assertTrue("Response content is not starting with (2 participants)",
-                checkResult.startsWith("(2 participants)"));
+        String checkResult = getContentText(conn);
+        assertTrue(
+            "Response content is not starting with (2 participants)",
+            checkResult.startsWith("(2 participants)")
+        );
         int checkLen = checkResult.length();
         assertTrue(checkLen > 1);
         assertTrue(checkLen < 100);
@@ -32,12 +36,10 @@ public class TestCheck extends WebappTestCase {
      * Check the syntax of an invalid sequence diagram :
      * Bob -
      */
-    public void testWrongDiagramSyntax() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "check/SyfFKj050000");
-        WebResponse response = conversation.getResource(request);
+    public void testWrongDiagramSyntax() throws IOException {
+        final URL url = new URL(getServerUrl() + "/check/SyfFKj050000");
         // Analyze response
-        String checkResult = response.getText();
+        String checkResult = getContentText(url);
         assertTrue("Response is not an error", checkResult.startsWith("(Error)"));
     }
 
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestEPS.java b/src/test/java/net/sourceforge/plantuml/servlet/TestEPS.java
index 7fd3544f540564aae29117f13286a77787400206..e6cd39de7d85881124bf6c7d832554aa27dd70a5 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/TestEPS.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/TestEPS.java
@@ -1,27 +1,30 @@
 package net.sourceforge.plantuml.servlet;
 
-import com.meterware.httpunit.GetMethodWebRequest;
-import com.meterware.httpunit.WebConversation;
-import com.meterware.httpunit.WebRequest;
-import com.meterware.httpunit.WebResponse;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
 
-import java.util.Scanner;
 
 public class TestEPS extends WebappTestCase {
+
     /**
      * Verifies the generation of the EPS for the Bob -> Alice sample
      */
-    public void testSimpleSequenceDiagram() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "eps/" + TestUtils.SEQBOB);
-        WebResponse response = conversation.getResource(request);
+    public void testSimpleSequenceDiagram() throws IOException {
+        final URL url = new URL(getServerUrl() + "/eps/" + TestUtils.SEQBOB);
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        assertEquals("Response content type is not EPS", "application/postscript", response.getContentType());
+        assertEquals(
+            "Response content type is not EPS",
+            "application/postscript",
+            conn.getContentType().toLowerCase()
+        );
         // Get the content and verify its size
-        String diagram = response.getText();
+        String diagram = getContentText(conn);
         int diagramLen = diagram.length();
         assertTrue(diagramLen > 10000);
         assertTrue(diagramLen < 12000);
     }
+
 }
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestForm.java b/src/test/java/net/sourceforge/plantuml/servlet/TestForm.java
index 5e2871f910d0c258fb0a0cc9edf0cab22ca1f75a..7a1a1e5a86d145796c8aaf93e72fa88d89ebf68d 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/TestForm.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/TestForm.java
@@ -1,155 +1,219 @@
 package net.sourceforge.plantuml.servlet;
 
-import com.meterware.httpunit.GetMethodWebRequest;
-import com.meterware.httpunit.HTMLElement;
-import com.meterware.httpunit.WebConversation;
-import com.meterware.httpunit.WebForm;
-import com.meterware.httpunit.WebRequest;
-import com.meterware.httpunit.WebResponse;
+import static org.junit.Assert.assertNotEquals;
+
+import java.io.IOException;
+import java.util.List;
+
+import com.gargoylesoftware.htmlunit.WebClient;
+import com.gargoylesoftware.htmlunit.html.DomElement;
+import com.gargoylesoftware.htmlunit.html.HtmlForm;
+import com.gargoylesoftware.htmlunit.html.HtmlImage;
+import com.gargoylesoftware.htmlunit.html.HtmlInput;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
+import com.gargoylesoftware.htmlunit.html.HtmlTextArea;
+
 
 public class TestForm extends WebappTestCase {
 
     /**
      * Verifies that the welcome page has exactly two form with the Bob --> Alice sample
      */
-    public void testWelcomePage() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl());
-        WebResponse response = conversation.getResponse(request);
-        // Analyze response
-        WebForm[] forms = response.getForms();
-        assertEquals(2, forms.length);
-        assertEquals("url", forms[1].getParameterNames()[0]);
-        assertTrue(forms[1].getParameterValue("url").endsWith("/png/" + TestUtils.SEQBOB));
-        // Ensure the generated image is present
-        assertNotNull(response.getImageWithAltText("PlantUML diagram"));
+    public void testWelcomePage() throws IOException {
+        try (final WebClient webClient = new WebClient()) {
+            HtmlPage page = webClient.getPage(getServerUrl());
+            // Analyze response
+            List<HtmlForm> forms = page.getForms();
+            assertEquals(2, forms.size());
+            // Ensure the Text field is correct
+            String text = ((HtmlTextArea)(forms.get(0).getFirstByXPath("//textarea[contains(@name, 'text')]"))).getTextContent();
+            assertEquals("@startuml\nBob -> Alice : hello\n@enduml", text);
+            // Ensure the URL field is correct
+            HtmlInput url = forms.get(1).getInputByName("url");
+            assertNotNull(url);
+            assertTrue(url.getAttribute("value").endsWith("/png/" + TestUtils.SEQBOB));
+            // Ensure the generated image is present
+            HtmlImage img = page.getFirstByXPath("//img[contains(@alt, 'PlantUML diagram')]");
+            assertNotEquals(0, img.getImageReader().getHeight(0));  // 131
+            assertNotEquals(0, img.getImageReader().getWidth(0));   // 120
+        }
     }
 
     /**
      * Verifies that the version image is generated
      */
-    public void testVersion() throws Exception {
-        WebConversation conversation = new WebConversation();
-        // Fill the form and submit it
-        WebRequest request = new GetMethodWebRequest(getServerUrl());
-        WebResponse response = conversation.getResponse(request);
-        WebForm formUMLText = response.getForms()[0];
-        formUMLText.setParameter("text", "version");
-        response = formUMLText.submit();
-        // Analyze response
-        WebForm[] forms = response.getForms();
-        assertEquals(2, forms.length);
-        // Ensure the Text field is correct
-        assertEquals("version", forms[0].getParameterValue("text"));
-        // Ensure the URL field is correct
-        assertTrue(forms[1].getParameterValue("url").endsWith("/png/" + TestUtils.VERSION));
-        // Ensure the image is present
-        assertNotNull(response.getImageWithAltText("PlantUML diagram"));
+    public void testVersion() throws IOException {
+        try (final WebClient webClient = new WebClient()) {
+            HtmlPage page = webClient.getPage(getServerUrl());
+            page.initialize();
+            // Fill the form and submit it
+            page.executeJavaScript("document.myCodeMirror.setValue('version')");
+            HtmlForm form = page.getForms().get(0);
+            HtmlSubmitInput btn = form.getFirstByXPath("//input[contains(@type, 'submit')]");
+            page = btn.click();
+            // Analyze response
+            List<HtmlForm> forms = page.getForms();
+            assertEquals(2, forms.size());
+            // Ensure the Text field is correct
+            String text = ((HtmlTextArea)(forms.get(0).getFirstByXPath("//textarea[contains(@name, 'text')]"))).getTextContent();
+            assertEquals("@startuml\nversion\n@enduml", text);
+            // Ensure the URL field is correct
+            HtmlInput url = forms.get(1).getInputByName("url");
+            assertNotNull(url);
+            assertTrue(url.getAttribute("value").endsWith("/png/" + TestUtils.VERSION));
+            // Ensure the generated image is present
+            HtmlImage img = page.getFirstByXPath("//img[contains(@alt, 'PlantUML diagram')]");
+            assertNotEquals(0, img.getImageReader().getHeight(0));  // 186
+            assertNotEquals(0, img.getImageReader().getWidth(0));   // 519
+        }
     }
 
     /**
-     * Verifies that when the UML text is empty, no image is generated
+     * Verifies that when the UML text is empty, default page and image is generated
      */
-    public void testEmptyText() throws Exception {
-        WebConversation conversation = new WebConversation();
-        // Fill the form and submit it
-        WebRequest request = new GetMethodWebRequest(getServerUrl());
-        WebResponse response = conversation.getResponse(request);
-        WebForm formUMLText = response.getForms()[0];
-        formUMLText.setParameter("text", "");
-        response = formUMLText.submit();
-        // Analyze response
-        WebForm[] forms = response.getForms();
-        assertEquals(2, forms.length);
-        // Ensure the Text field is empty
-        assertNull(forms[0].getParameterValue("text"));
-        // Ensure the URL field is empty
-        assertTrue(forms[1].getParameterValue("url").isEmpty());
-        // Ensure there is no image
-        assertNull(response.getImageWithAltText("PlantUML diagram"));
+    public void testEmptyText() throws IOException {
+        try (final WebClient webClient = new WebClient()) {
+            HtmlPage page = webClient.getPage(getServerUrl());
+            page.initialize();
+            // Fill the form and submit it
+            page.executeJavaScript("document.myCodeMirror.setValue('')");
+            HtmlForm form = page.getForms().get(0);
+            HtmlSubmitInput btn = form.getFirstByXPath("//input[contains(@type, 'submit')]");
+            page = btn.click();
+            // Analyze response
+            List<HtmlForm> forms = page.getForms();
+            assertEquals(2, forms.size());
+            // Ensure the Text field is correct
+            String text = ((HtmlTextArea)(forms.get(0).getFirstByXPath("//textarea[contains(@name, 'text')]"))).getTextContent();
+            assertEquals("@startuml\nBob -> Alice : hello\n@enduml", text);
+            // Ensure the URL field is correct
+            HtmlInput url = forms.get(1).getInputByName("url");
+            assertNotNull(url);
+            assertTrue(url.getAttribute("value").endsWith("/png/" + TestUtils.SEQBOB));
+            // Ensure the generated image is present
+            HtmlImage img = page.getFirstByXPath("//img[contains(@alt, 'PlantUML diagram')]");
+            assertNotEquals(0, img.getImageReader().getHeight(0));  // 131
+            assertNotEquals(0, img.getImageReader().getWidth(0));   // 120
+        }
     }
 
     /**
-     * Verifies that when the encoded URL is empty, no image is generated
+     * Verifies that when the encoded URL is empty, default page and image is generated
      */
-    public void testEmptyUrl() throws Exception {
-        WebConversation conversation = new WebConversation();
-        // Fill the form and submit it
-        WebRequest request = new GetMethodWebRequest(getServerUrl());
-        WebResponse response = conversation.getResponse(request);
-        WebForm formUrl = response.getForms()[1];
-        formUrl.setParameter("url", "");
-        response = formUrl.submit();
-        // Analyze response
-        WebForm[] forms = response.getForms();
-        assertEquals(2, forms.length);
-        // Ensure the Text field is empty
-        assertNull(forms[0].getParameterValue("text"));
-        // Ensure the URL field is empty
-        assertTrue(forms[1].getParameterValue("url").isEmpty());
-        // Ensure there is no image
-        assertNull(response.getImageWithAltText("PlantUML diagram"));
+    public void testEmptyUrl() throws IOException {
+        try (final WebClient webClient = new WebClient()) {
+            HtmlPage page = webClient.getPage(getServerUrl());
+            page.initialize();
+            // Fill the form and submit it
+            List<HtmlForm> forms = page.getForms();
+            HtmlInput url = forms.get(1).getInputByName("url");
+            url.setAttribute("value", "");
+            HtmlSubmitInput btn = forms.get(1).getFirstByXPath("//input[contains(@type, 'submit')]");
+            page = btn.click();
+            // Analyze response
+            forms = page.getForms();
+            assertEquals(2, forms.size());
+            // Ensure the Text field is correct
+            String text = ((HtmlTextArea)(forms.get(0).getFirstByXPath("//textarea[contains(@name, 'text')]"))).getTextContent();
+            assertEquals("@startuml\nBob -> Alice : hello\n@enduml", text);
+            // Ensure the URL field is correct
+            url = forms.get(1).getInputByName("url");
+            assertNotNull(url);
+            assertTrue(url.getAttribute("value").endsWith("/png/" + TestUtils.SEQBOB));
+            // Ensure the generated image is present
+            HtmlImage img = page.getFirstByXPath("//img[contains(@alt, 'PlantUML diagram')]");
+            assertNotEquals(0, img.getImageReader().getHeight(0));  // 131
+            assertNotEquals(0, img.getImageReader().getWidth(0));   // 120
+        }
     }
 
     /**
      * Verifies that a ditaa diagram is generated
      */
-    public void testDitaaText() throws Exception {
-        WebConversation conversation = new WebConversation();
-        // Fill the form and submit it
-        WebRequest request = new GetMethodWebRequest(getServerUrl());
-        WebResponse response = conversation.getResponse(request);
-        WebForm formDitaaText = response.getForms()[0];
-        formDitaaText.setParameter("text", "@startditaa \n*--> \n@endditaa");
-        response = formDitaaText.submit();
-        // Analyze response
-        WebForm[] forms = response.getForms();
-        assertEquals(2, forms.length);
-        // Ensure the Text field is correct
-        assertTrue(forms[0].getParameterValue("text").startsWith("@startditaa"));
-        // Ensure the URL field is correct
-        assertTrue(forms[1].getParameterValue("url").endsWith("/png/SoWkIImgISaiIKnKuDBIrRLJu798pKi12m00"));
-        // Ensure the image is present
-        assertNotNull(response.getImageWithAltText("PlantUML diagram"));
+    public void testDitaaText() throws IOException {
+        try (final WebClient webClient = new WebClient()) {
+            HtmlPage page = webClient.getPage(getServerUrl());
+            page.initialize();
+            // Fill the form and submit it
+            page.executeJavaScript("document.myCodeMirror.setValue(`@startditaa \n*--> \n@endditaa`)");
+            HtmlForm form = page.getForms().get(0);
+            HtmlSubmitInput btn = form.getFirstByXPath("//input[contains(@type, 'submit')]");
+            page = btn.click();
+            // Analyze response
+            List<HtmlForm> forms = page.getForms();
+            assertEquals(2, forms.size());
+            // Ensure the Text field is correct
+            String text = ((HtmlTextArea)(forms.get(0).getFirstByXPath("//textarea[contains(@name, 'text')]"))).getTextContent();
+            assertEquals("@startditaa \n*--> \n@endditaa", text);
+            // Ensure the URL field is correct
+            HtmlInput url = forms.get(1).getInputByName("url");
+            assertNotNull(url);
+            assertTrue(url.getAttribute("value").endsWith("/png/SoWkIImgISaiIKnKuDBIrRLJu798pKi12m00"));
+            // Ensure the generated image is present
+            HtmlImage img = page.getFirstByXPath("//img[contains(@alt, 'PlantUML diagram')]");
+            assertNotEquals(0, img.getImageReader().getHeight(0));  // 70
+            assertNotEquals(0, img.getImageReader().getWidth(0));   // 90
+        }
     }
 
     /**
      * Verifies that an image map is produced if the diagram contains a link
      */
-    public void testImageMap() throws Exception {
-        WebConversation conversation = new WebConversation();
-        // Fill the form and submit it
-        WebRequest request = new GetMethodWebRequest(getServerUrl());
-        WebResponse response = conversation.getResponse(request);
-        WebForm formText = response.getForms()[0];
-        formText.setParameter("text", "@startuml \nBob -> Alice : [[http://yahoo.com]] Hello \n@enduml");
-        response = formText.submit();
-        // Analyze response
-        // Ensure the generated image is present
-        assertNotNull(response.getImageWithAltText("PlantUML diagram"));
-        // Ensure the image map is present
-        HTMLElement[] maps = response.getElementsByTagName("map");
-        assertEquals(1, maps.length);
+    public void testImageMap() throws IOException {
+        try (final WebClient webClient = new WebClient()) {
+            HtmlPage page = webClient.getPage(getServerUrl());
+            page.initialize();
+            // Fill the form and submit it
+            page.executeJavaScript("document.myCodeMirror.setValue(`@startuml\nBob -> Alice : [[http://yahoo.com]] Hello\n@enduml`)");
+            HtmlForm form = page.getForms().get(0);
+            HtmlSubmitInput btn = form.getFirstByXPath("//input[contains(@type, 'submit')]");
+            page = btn.click();
+            // Analyze response
+            List<HtmlForm> forms = page.getForms();
+            assertEquals(2, forms.size());
+            // Ensure the Text field is correct
+            String text = ((HtmlTextArea)(forms.get(0).getFirstByXPath("//textarea[contains(@name, 'text')]"))).getTextContent();
+            assertEquals("@startuml\nBob -> Alice : [[http://yahoo.com]] Hello\n@enduml", text);
+            // Ensure the URL field is correct
+            HtmlInput url = forms.get(1).getInputByName("url");
+            assertNotNull(url);
+            assertTrue(url.getAttribute("value").endsWith("/png/SyfFKj2rKt3CoKnELR1IY8xEA2afiDBNhqpCoC_NIyxFZOrLy4ZDoSa70000"));
+            // Ensure the generated image is present
+            HtmlImage img = page.getFirstByXPath("//img[contains(@alt, 'PlantUML diagram')]");
+            assertNotEquals(0, img.getImageReader().getHeight(0));  // 131
+            assertNotEquals(0, img.getImageReader().getWidth(0));   // 231
+            // TODO: Ensure the image map is present
+            //DomElement map = page.getElementById("plantuml_map");
+            //assertNotNull(map);
+            //assertEquals(1, map.getChildElementCount());
+        }
     }
 
     /**
      * Verifies that when the encoded source is specified as an URL parameter
      * the diagram is displayed and the source is decoded
      */
-    public void testUrlParameter() throws Exception {
-        WebConversation conversation = new WebConversation();
-        // Submit the request with a url parameter
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "form?url=" + TestUtils.SEQBOB);
-        WebResponse response = conversation.getResponse(request);
-        // Analyze response
-        WebForm[] forms = response.getForms();
-        assertEquals(2, forms.length);
-        // Ensure the Text field is filled
-        assertEquals(forms[0].getParameterValue("text"), "@startuml\nBob -> Alice : hello\n@enduml");
-        // Ensure the URL field is filled
-        assertEquals(forms[1].getParameterValue("url"), getServerUrl() + "png/" + TestUtils.SEQBOB);
-        // Ensure the image is present
-        assertNotNull(response.getImageWithAltText("PlantUML diagram"));
+    public void testUrlParameter() throws IOException {
+        try (final WebClient webClient = new WebClient()) {
+            // Submit the request with a url parameter
+            HtmlPage page = webClient.getPage(getServerUrl() + "/form?url=" + TestUtils.SEQBOB);
+            page.initialize();
+            // Analyze response
+            List<HtmlForm> forms = page.getForms();
+            assertEquals(2, forms.size());
+            // Ensure the Text field is correct
+            String text = ((HtmlTextArea)(forms.get(0).getFirstByXPath("//textarea[contains(@name, 'text')]"))).getTextContent();
+            assertEquals("@startuml\nBob -> Alice : hello\n@enduml", text);
+            // Ensure the URL field is correct
+            HtmlInput url = forms.get(1).getInputByName("url");
+            assertNotNull(url);
+            assertTrue(url.getAttribute("value").endsWith("/png/" + TestUtils.SEQBOB));
+            // Ensure the generated image is present
+            HtmlImage img = page.getFirstByXPath("//img[contains(@alt, 'PlantUML diagram')]");
+            assertNotEquals(0, img.getImageReader().getHeight(0));  // 131
+            assertNotEquals(0, img.getImageReader().getWidth(0));   // 120
+        }
     }
 
 }
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestImage.java b/src/test/java/net/sourceforge/plantuml/servlet/TestImage.java
index cbeeb6cd4d87e7c36f53b0a0a1e77bde98acbd3e..3b76ec58f6641a4adefed2628e3e2403288962b3 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/TestImage.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/TestImage.java
@@ -1,84 +1,76 @@
 package net.sourceforge.plantuml.servlet;
 
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Locale;
 
-import com.meterware.httpunit.GetMethodWebRequest;
-import com.meterware.httpunit.WebConversation;
-import com.meterware.httpunit.WebRequest;
-import com.meterware.httpunit.WebResponse;
 
 public class TestImage extends WebappTestCase {
+
     /**
      * Verifies the generation of the version image from an encoded URL
      */
-    public void testVersionImage() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "png/" + TestUtils.VERSION);
-        WebResponse response = conversation.getResource(request);
+    public void testVersionImage() throws IOException {
+        final URL url = new URL(getServerUrl() + "/png/" + TestUtils.VERSION);
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        assertEquals("Response content type is not PNG", "image/png", response.getContentType());
+        assertEquals(
+            "Response content type is not PNG",
+            "image/png",
+            conn.getContentType().toLowerCase()
+        );
         // Get the image and verify its size
-        InputStream responseStream = response.getInputStream();
-        ByteArrayOutputStream imageStream = new ByteArrayOutputStream();
-        byte[] buf = new byte[1024];
-        int n = 0;
-        while ((n = responseStream.read(buf)) != -1) {
-            imageStream.write(buf, 0, n);
-        }
-        imageStream.close();
-        byte[] inMemoryImage = imageStream.toByteArray();
+        byte[] inMemoryImage = getContentAsBytes(conn);
         int diagramLen = inMemoryImage.length;
         assertTrue(diagramLen > 10000);
         assertTrue(diagramLen < 20000);
-        responseStream.close();
     }
 
     /**
      * Verifies that the HTTP header of a diagram incites the browser to cache it.
      */
-    public void testDiagramHttpHeader() throws Exception {
-        WebConversation conversation = new WebConversation();
-        // Bob -> Alice : hello
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "png/" + TestUtils.SEQBOB);
-        WebResponse response = conversation.getResource(request);
+    public void testDiagramHttpHeader() throws IOException, ParseException {
+        final URL url = new URL(getServerUrl() + "/png/" + TestUtils.SEQBOB);
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        assertEquals("Response content type is not PNG", "image/png", response.getContentType());
+        assertEquals(
+            "Response content type is not PNG",
+            "image/png",
+            conn.getContentType().toLowerCase()
+        );
         // Verifies the availability of the Expires entry in the response header
-        assertNotNull(response.getHeaderField("Expires"));
+        assertNotNull(conn.getHeaderField("Expires"));
         // Verifies the availability of the Last-Modified entry in the response header
-        assertNotNull(response.getHeaderField("Last-Modified"));
+        assertNotNull(conn.getHeaderField("Last-Modified"));
         // Verifies the Last-Modified value is in the past
         SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss ZZZ", Locale.ENGLISH);
-        Date lastModified = format.parse(response.getHeaderField("Last-Modified"));
+        Date lastModified = format.parse(conn.getHeaderField("Last-Modified"));
         assertTrue("Last-Modified is not in the past", lastModified.before(new Date()));
-        // Consume the response
-        InputStream responseStream = response.getInputStream();
-        while (responseStream.read() != -1) {
-            // Do nothing
-        }
+        // Consume the response but do nothing with it
+        getContentAsBytes(conn);
     }
 
     /**
      * Verifies that the HTTP header of a diagram incites the browser to cache it.
      */
-    public void testOldImgURL() throws Exception {
-        WebConversation conversation = new WebConversation();
-        // Bob -> Alice : hello
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "img/" + TestUtils.SEQBOB);
-        WebResponse response = conversation.getResource(request);
+    public void testOldImgURL() throws IOException {
+        final URL url = new URL(getServerUrl() + "/img/" + TestUtils.SEQBOB);
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        assertEquals("Response content type is not PNG", "image/png", response.getContentType());
-        // Consume the response
-        InputStream responseStream = response.getInputStream();
-        while (responseStream.read() != -1) {
-            // Do nothing
-        }
+        assertEquals(
+            "Response content type is not PNG",
+            "image/png",
+            conn.getContentType().toLowerCase()
+        );
+        // Consume the response but do nothing with it
+        getContentAsBytes(conn);
     }
+
 }
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestLanguage.java b/src/test/java/net/sourceforge/plantuml/servlet/TestLanguage.java
index c5eb3cf22d2e0438ebe489ff0c704961b49243e5..af0187366fa906b33509d8bb876be1ce20a8e546 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/TestLanguage.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/TestLanguage.java
@@ -1,11 +1,8 @@
 package net.sourceforge.plantuml.servlet;
 
-import com.meterware.httpunit.GetMethodWebRequest;
-import com.meterware.httpunit.WebConversation;
-import com.meterware.httpunit.WebRequest;
-import com.meterware.httpunit.WebResponse;
-
 import java.io.IOException;
+import java.net.URL;
+
 
 public class TestLanguage extends WebappTestCase {
 
@@ -13,10 +10,8 @@ public class TestLanguage extends WebappTestCase {
      * Tests that the language for the current PlantUML server can be obtained through HTTP
      */
     public void testRetrieveLanguage() throws IOException {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "/language");
-        WebResponse response = conversation.getResource(request);
-        String languageText = response.getText();
+        final URL url = new URL(getServerUrl() + "/language");
+        String languageText = getContentText(url);
         assertTrue("Language contains @startuml", languageText.indexOf("@startuml") > 0);
     }
 
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestMap.java b/src/test/java/net/sourceforge/plantuml/servlet/TestMap.java
index 89f81abe4226af4ea69f7641d0396ed78e6c6d85..0e344f4bc649c046c1414f4ab9e6d0c72ef0fd04 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/TestMap.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/TestMap.java
@@ -1,29 +1,41 @@
 package net.sourceforge.plantuml.servlet;
 
-import com.meterware.httpunit.GetMethodWebRequest;
-import com.meterware.httpunit.WebConversation;
-import com.meterware.httpunit.WebRequest;
-import com.meterware.httpunit.WebResponse;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
 
 public class TestMap extends WebappTestCase {
+
     /**
      * Verifies the generation of the MAP for the following sample:
      *
      * participant Bob [[http://www.yahoo.com]]
      * Bob -> Alice : [[http://www.google.com]] hello
      */
-    public void testSimpleSequenceDiagram() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl()
-            + "map/AqWiAibCpYn8p2jHSCfFKeYEpYWfAR3IroylBzUhJCp8pzTBpi-DZUK2IUhQAJZcP2QdAbYXgalFpq_FIOKeLCX8pSd91m00");
-        WebResponse response = conversation.getResource(request);
+    public void testSimpleSequenceDiagram() throws IOException {
+        final URL url = new URL(
+            getServerUrl() +
+            "/map/AqWiAibCpYn8p2jHSCfFKeYEpYWfAR3IroylBzUhJCp8pzTBpi-DZUK2IUhQAJZcP2QdAbYXgalFpq_FIOKeLCX8pSd91m00"
+        );
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        assertEquals("Response content type is not TEXT PLAIN", "text/plain", response.getContentType());
-        assertEquals("Response character set is not UTF-8", "UTF-8", response.getCharacterSet());
+        assertEquals(
+            "Response content type is not TEXT PLAIN or UTF-8",
+            "text/plain;charset=utf-8",
+            conn.getContentType().toLowerCase()
+        );
         // Get the content, check its first characters and verify its size
-        String diagram = response.getText();
-        assertTrue("Response content is not starting with <area", diagram.startsWith("<area"));
+        String diagram = getContentText(conn);
+        assertTrue(
+            "Response content is not starting with <map",
+            diagram.startsWith("<map")
+        );
+        assertTrue(
+            "Response content (2. line) is not starting with <area",
+            diagram.split("\\n", 2)[1].startsWith("<area")
+        );
         int diagramLen = diagram.length();
         assertTrue(diagramLen > 200);
         assertTrue(diagramLen < 300);
@@ -33,33 +45,43 @@ public class TestMap extends WebappTestCase {
      * Check the content of the MAP for the sequence diagram sample
      * Verify structure of the area tags
      */
-    public void testSequenceDiagramContent() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl()
-            + "map/AqWiAibCpYn8p2jHSCfFKeYEpYWfAR3IroylBzUhJCp8pzTBpi-DZUK2IUhQAJZcP2QdAbYXgalFpq_FIOKeLCX8pSd91m00");
-        WebResponse response = conversation.getResource(request);
+    public void testSequenceDiagramContent() throws IOException {
+        final URL url = new URL(
+            getServerUrl() +
+            "/map/AqWiAibCpYn8p2jHSCfFKeYEpYWfAR3IroylBzUhJCp8pzTBpi-DZUK2IUhQAJZcP2QdAbYXgalFpq_FIOKeLCX8pSd91m00"
+        );
         // Analyze response
         // Get the data contained in the XML
-        String map = response.getText();
-        assertTrue("Response is not a list of tags", map.matches("(<([^<>]+)>)+"));
-        assertTrue("Response doesn't contain the area structure",
-                map.matches(".*(area shape=\".+\" id=\".+\" href=\".+\").*"));
+        String map = getContentText(url);
+        // Verify shape:
+        // <map id="..." name="...">
+        // <area shape="..." id="..." href="..." ... />
+        // <area shape="..." id="..." href="..." ... />
+        // </map>
+        assertTrue(
+            "Response doesn't match shape",
+            map.matches("^<map id=\".+\" name=\".+\">\n(<area shape=\".+\" id=\".+\" href=\".+\".*/>\n){2}</map>\n*$")
+        );
     }
 
     /**
      * Check the empty MAP of a sequence diagram without link
      * This test uses the simple Bob -> Alice
      */
-    public void testSequenceDiagramWithoutLink() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "map/" + TestUtils.SEQBOB);
-        WebResponse response = conversation.getResource(request);
+    public void testSequenceDiagramWithoutLink() throws IOException {
+        final URL url = new URL(getServerUrl() + "/map/" + TestUtils.SEQBOB);
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        assertEquals("Response content type is not TEXT PLAIN", "text/plain", response.getContentType());
-        // Get the content, check it's an empty response
-        String diagram = response.getText();
+        assertEquals(
+            "Response content type is not TEXT PLAIN or UTF-8",
+            "text/plain;charset=utf-8",
+            conn.getContentType().toLowerCase()
+        );
+        // Get the data contained in the XML
+        String diagram = getContentText(conn);
         int diagramLen = diagram.length();
         assertEquals(0, diagramLen);
     }
+
 }
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestOldProxy.java b/src/test/java/net/sourceforge/plantuml/servlet/TestOldProxy.java
index 2ea912b98027df5eefe40dbffdfa964bcce7d1b9..c08674b63b4e2ca1db2a0fddb71514de4d2b9dd1 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/TestOldProxy.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/TestOldProxy.java
@@ -1,52 +1,45 @@
 package net.sourceforge.plantuml.servlet;
 
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
 
-import com.meterware.httpunit.GetMethodWebRequest;
-import com.meterware.httpunit.WebConversation;
-import com.meterware.httpunit.WebForm;
-import com.meterware.httpunit.WebRequest;
-import com.meterware.httpunit.WebResponse;
 
 public class TestOldProxy extends WebappTestCase {
+
     /**
      * Verifies the proxified reception of the default Bob and Alice diagram
      */
-    public void testDefaultProxy() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "proxy/" + getServerUrl()
-                + "resource/test2diagrams.txt");
-        WebResponse response = conversation.getResource(request);
+    public void testDefaultProxy() throws IOException {
+        final URL url = new URL(getServerUrl() + "/proxy/" + getServerUrl() + "/resource/test2diagrams.txt");
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        // assertEquals( "Response content type is not PNG", "image/png", response.getContentType());
+        assertEquals(
+            "Response content type is not PNG",
+            "image/png",
+            conn.getContentType().toLowerCase()
+        );
         // Get the image and verify its size (~2000 bytes)
-        InputStream responseStream = response.getInputStream();
-        ByteArrayOutputStream imageStream = new ByteArrayOutputStream();
-        byte[] buf = new byte[1024];
-        int n = 0;
-        while ((n = responseStream.read(buf)) != -1) {
-            imageStream.write(buf, 0, n);
-        }
-        imageStream.close();
-        responseStream.close();
-        byte[] inMemoryImage = imageStream.toByteArray();
+        byte[] inMemoryImage = getContentAsBytes(conn);
         int diagramLen = inMemoryImage.length;
-        assertTrue(diagramLen > 1500);
-        assertTrue(diagramLen < 2500);
+        assertTrue(diagramLen > 2000);
+        assertTrue(diagramLen < 3000);
     }
 
-    public void testProxyWithFormat() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "proxy/svg/" + getServerUrl()
-                + "resource/test2diagrams.txt");
-        WebResponse response = conversation.getResource(request);
+    public void testProxyWithFormat() throws IOException {
+        final URL url = new URL(getServerUrl() + "/proxy/svg/" + getServerUrl() + "/resource/test2diagrams.txt");
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        // TODO assertEquals( "Response content type is not SVG", "image/svg+xml", response.getContentType());
+        assertEquals(
+            "Response content type is not SVG",
+            "image/svg+xml",
+            conn.getContentType().toLowerCase()
+        );
         // Get the content and verify its size
-        String diagram = response.getText();
+        String diagram = getContentText(conn);
         int diagramLen = diagram.length();
         assertTrue(diagramLen > 1000);
         assertTrue(diagramLen < 3000);
@@ -55,15 +48,22 @@ public class TestOldProxy extends WebappTestCase {
     /**
      * Verifies that the HTTP header of a diagram incites the browser to cache it.
      */
-    public void testInvalidUrl() throws Exception {
-        WebConversation conversation = new WebConversation();
-        // Try to proxify an invalid address
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "proxy/invalidURL");
-        WebResponse response = conversation.getResource(request);
-        // Analyze response, it must be the empty form
-        // Verifies the Content-Type header
-        assertEquals("Response content type is not HTML", "text/html", response.getContentType());
-        WebForm[] forms = response.getForms();
-        assertEquals(2, forms.length);
+    public void testInvalidUrl() throws IOException {
+        final URL url = new URL(getServerUrl() + "/proxy/invalidURL");
+        final HttpURLConnection conn = (HttpURLConnection)url.openConnection();
+        // Analyze response
+        // Get the content and verify its size
+        assertEquals(
+            "Response is not empty",
+            0,
+            conn.getContentLength()
+        );
+        // Check if status code is 400
+        assertEquals(
+            "Bad HTTP status received",
+            400,
+            conn.getResponseCode()
+        );
     }
+
 }
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestProxy.java b/src/test/java/net/sourceforge/plantuml/servlet/TestProxy.java
index 014e04f9256ca79505667e5c4f71a42c18c87cc2..1d769ff7321d1294bb8095ca5d9a916d22d6a083 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/TestProxy.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/TestProxy.java
@@ -1,65 +1,105 @@
 package net.sourceforge.plantuml.servlet;
 
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
 
-import com.meterware.httpunit.GetMethodWebRequest;
-import com.meterware.httpunit.WebConversation;
-import com.meterware.httpunit.WebRequest;
-import com.meterware.httpunit.WebResponse;
 
 public class TestProxy extends WebappTestCase {
+
     /**
      * Verifies the proxified reception of the default Bob and Alice diagram
      */
-    public void testDefaultProxy() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl()
-            + "proxy?src=" + getServerUrl() + "resource/test2diagrams.txt");
-        WebResponse response = conversation.getResource(request);
+    public void testDefaultProxy() throws IOException {
+        final URL url = new URL(getServerUrl() + "/proxy?src=" + getServerUrl() + "/resource/test2diagrams.txt");
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        assertEquals("Response content type is not PNG", "image/png", response.getContentType());
+        assertEquals(
+            "Response content type is not PNG",
+            "image/png",
+            conn.getContentType().toLowerCase()
+        );
         // Get the image and verify its size (~2000 bytes)
-        InputStream responseStream = response.getInputStream();
-        ByteArrayOutputStream imageStream = new ByteArrayOutputStream();
-        byte[] buf = new byte[1024];
-        int n = 0;
-        while ((n = responseStream.read(buf)) != -1) {
-            imageStream.write(buf, 0, n);
-        }
-        imageStream.close();
-        responseStream.close();
-        byte[] inMemoryImage = imageStream.toByteArray();
+        byte[] inMemoryImage = getContentAsBytes(conn);
         int diagramLen = inMemoryImage.length;
-        assertTrue(diagramLen > 1500);
-        assertTrue(diagramLen < 2500);
+        assertTrue(diagramLen > 2000);
+        assertTrue(diagramLen < 3000);
     }
-/*
-    public void testProxyWithFormat() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl()
-            + "proxy?format=svg&src=" + getServerUrl() + "resource/test2diagrams.txt");
-        WebResponse response = conversation.getResource(request);
+
+    /**
+     * Verifies the proxified reception of the default Bob and Alice diagram with defined format.
+     */
+    public void testProxyWithFormat() throws IOException {
+        final URL url = new URL(getServerUrl() + "/proxy?fmt=svg&src=" + getServerUrl() + "/resource/test2diagrams.txt");
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        assertEquals( "Response content type is not SVG", "image/svg+xml", response.getContentType());
+        assertEquals(
+            "Response content type is not SVG",
+            "image/svg+xml",
+            conn.getContentType().toLowerCase()
+        );
         // Get the content and verify its size
-        String diagram = response.getText();
+        String diagram = getContentText(conn);
         int diagramLen = diagram.length();
-        assertTrue(diagramLen > 1000);
+        assertTrue(diagramLen > 2000);
         assertTrue(diagramLen < 3000);
     }
 
+    /**
+     * Verifies the proxified reception of the default Bob and Alice diagram with defined format and format (idx=0).
+     */
+    public void testProxyWithFormatIdx0() throws IOException {
+        final URL url = new URL(getServerUrl() + "/proxy?fmt=svg&idx=0&src=" + getServerUrl() + "/resource/test2diagrams.txt");
+        final URLConnection conn = url.openConnection();
+        // Analyze response
+        // Verifies the Content-Type header
+        assertEquals(
+            "Response content type is not SVG",
+            "image/svg+xml",
+            conn.getContentType().toLowerCase()
+        );
+        // Get the content and verify its size
+        String diagram = getContentText(conn);
+        int diagramLen = diagram.length();
+        assertTrue(diagramLen > 2000);
+        assertTrue(diagramLen < 3000);
+    }
+
+    /**
+     * Verifies the proxified reception of the default Bob and Alice diagram with defined format and format (idx=1).
+     */
+    public void testProxyWithFormatIdx1() throws IOException {
+        final URL url = new URL(getServerUrl() + "/proxy?fmt=svg&idx=1&src=" + getServerUrl() + "/resource/test2diagrams.txt");
+        final URLConnection conn = url.openConnection();
+        // Analyze response
+        // Verifies the Content-Type header
+        assertEquals(
+            "Response content type is not SVG",
+            "image/svg+xml",
+            conn.getContentType().toLowerCase()
+        );
+        // Get the content and verify its size
+        String diagram = getContentText(conn);
+        int diagramLen = diagram.length();
+        assertTrue(diagramLen > 5000);
+        assertTrue(diagramLen < 6000);
+    }
+
     /**
      * Verifies that the HTTP header of a diagram incites the browser to cache it.
      */
-    public void testInvalidUrl() throws Exception {
-        WebConversation conversation = new WebConversation();
-        // Try to proxify an invalid address
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "proxy?src=invalidURL");
-        WebResponse response = conversation.getResource(request);
-        // Analyze response, it must be HTTP error 500
-        //assertEquals("Bad HTTP status received", 500, response.getResponseCode());
+    public void testInvalidUrl() throws IOException {
+        final URL url = new URL(getServerUrl() + "/proxy?src=invalidURL");
+        final HttpURLConnection conn = (HttpURLConnection)url.openConnection();
+        // Analyze response, it must be HTTP error 400
+        assertEquals(
+            "Bad HTTP status received",
+            400,
+            conn.getResponseCode()
+        );
     }
+
 }
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestSVG.java b/src/test/java/net/sourceforge/plantuml/servlet/TestSVG.java
index 4928df6dd3054929b799879c6d0ee4dbbe5217ec..59af92aa6ade0b76216d4fb23019dbfbafa28ae9 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/TestSVG.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/TestSVG.java
@@ -1,28 +1,31 @@
 package net.sourceforge.plantuml.servlet;
 
-import com.meterware.httpunit.GetMethodWebRequest;
-import com.meterware.httpunit.PostMethodWebRequest;
-import com.meterware.httpunit.WebConversation;
-import com.meterware.httpunit.WebRequest;
-import com.meterware.httpunit.WebResponse;
-
-import java.io.ByteArrayInputStream;
-import java.nio.charset.Charset;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
 import java.util.Scanner;
 
+
 public class TestSVG extends WebappTestCase {
+
     /**
      * Verifies the generation of the SVG for the Bob -> Alice sample
      */
-    public void testSimpleSequenceDiagram() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "svg/" + TestUtils.SEQBOB);
-        WebResponse response = conversation.getResource(request);
+    public void testSimpleSequenceDiagram() throws IOException {
+        final URL url = new URL(getServerUrl() + "/svg/" + TestUtils.SEQBOB);
+        final URLConnection conn = url.openConnection();
         // Analyze response
         // Verifies the Content-Type header
-        assertEquals("Response content type is not SVG", "image/svg+xml", response.getContentType());
+        assertEquals(
+            "Response content type is not SVG",
+            "image/svg+xml",
+            conn.getContentType().toLowerCase()
+        );
         // Get the content and verify its size
-        String diagram = response.getText();
+        String diagram = getContentText(conn);
         int diagramLen = diagram.length();
         assertTrue(diagramLen > 1000);
         assertTrue(diagramLen < 3000);
@@ -31,24 +34,31 @@ public class TestSVG extends WebappTestCase {
     /**
      * Verifies the generation of the SVG for the Bob -> Alice sample
      */
-    public void testPostedSequenceDiagram() throws Exception {
-        WebConversation conversation = new WebConversation();
-        PostMethodWebRequest request = new PostMethodWebRequest(
-                getServerUrl() + "svg/",
-                new ByteArrayInputStream("@startuml\nBob -> Alice\n@enduml".getBytes(Charset.defaultCharset())),
-                "text/plain");
-
-        WebResponse response = conversation.getResource(request);
-
-        assertEquals(200, response.getResponseCode());
-
+    public void testPostedSequenceDiagram() throws IOException {
+        final URL url = new URL(getServerUrl() + "/svg");
+        final HttpURLConnection conn = (HttpURLConnection)url.openConnection();
+        conn.setRequestMethod("POST");
+        conn.setDoOutput(true);
+        conn.setRequestProperty("Content-type", "text/plain");
+        try (final OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream())) {
+            writer.write("@startuml\nBob -> Alice\n@enduml");
+            writer.flush();
+        }
         // Analyze response
+        // HTTP response 200
+        assertEquals(
+            "Bad HTTP status received",
+            200,
+            conn.getResponseCode()
+        );
         // Verifies the Content-Type header
-        assertEquals("Response content type is not SVG", "image/svg+xml", response.getContentType());
+        assertEquals(
+            "Response content type is not SVG",
+            "image/svg+xml",
+            conn.getContentType().toLowerCase()
+        );
         // Get the content and verify its size
-
-        String diagram = response.getText();
-
+        String diagram = getContentText(conn.getInputStream());
         int diagramLen = diagram.length();
         assertTrue(diagramLen > 1000);
         assertTrue(diagramLen < 3000);
@@ -57,40 +67,51 @@ public class TestSVG extends WebappTestCase {
     /**
      * Verifies the generation of the SVG for the Bob -> Alice sample
      */
-    public void testPostedInvalidSequenceDiagram() throws Exception {
-        WebConversation conversation = new WebConversation();
-        PostMethodWebRequest request = new PostMethodWebRequest(
-                getServerUrl() + "svg/",
-                new ByteArrayInputStream("@startuml\n[Bob\n@enduml".getBytes(Charset.defaultCharset())),
-                "text/plain");
-
-        WebResponse response = conversation.getResource(request);
-
-        assertEquals(400, response.getResponseCode());
+    public void testPostedInvalidSequenceDiagram() throws IOException {
+        final URL url = new URL(getServerUrl() + "/svg");
+        final HttpURLConnection conn = (HttpURLConnection)url.openConnection();
+        conn.setRequestMethod("POST");
+        conn.setDoOutput(true);
+        conn.setRequestProperty("Content-type", "text/plain");
+        try (final OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream())) {
+            writer.write("@startuml\n[Bob\n@enduml");
+            writer.flush();
+        }
+        // Analyze response
+        // HTTP response 400
+        assertEquals(
+            "Bad HTTP status received",
+            400,
+            conn.getResponseCode()
+        );
     }
 
     /**
      * Check the content of the SVG
      */
-    public void testSequenceDiagramContent() throws Exception {
-        WebConversation conversation = new WebConversation();
-        WebRequest request = new GetMethodWebRequest(getServerUrl() + "svg/" + TestUtils.SEQBOB);
-        WebResponse response = conversation.getResource(request);
+    public void testSequenceDiagramContent() throws IOException {
+        final URL url = new URL(getServerUrl() + "/svg/" + TestUtils.SEQBOB);
         // Analyze response
         // Get the data contained in the XML
-        Scanner s = new Scanner(response.getInputStream()).useDelimiter("(<([^<>]+)>)+");
-        String token;
-        int bobCounter = 0, aliceCounter = 0;
-        while (s.hasNext()) {
-            token = s.next();
-            if (token.startsWith("Bob")) {
-                bobCounter++;
-            }
-            if (token.startsWith("Alice")) {
-                aliceCounter++;
+        try (
+            final InputStream responseStream = url.openStream();
+            final Scanner scanner = new Scanner(responseStream).useDelimiter("(<([^<>]+)>)+")
+        ) {
+            String token;
+            int bobCounter = 0;
+            int aliceCounter = 0;
+            while (scanner.hasNext()) {
+                token = scanner.next();
+                if (token.startsWith("Bob")) {
+                    bobCounter++;
+                }
+                if (token.startsWith("Alice")) {
+                    aliceCounter++;
+                }
             }
+            assertTrue(bobCounter == 2);
+            assertTrue(aliceCounter == 2);
         }
-        assertTrue(bobCounter == 2);
-        assertTrue(aliceCounter == 2);
     }
+
 }
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/TestUtils.java b/src/test/java/net/sourceforge/plantuml/servlet/TestUtils.java
index 168999a24b8499c1b902bc11d7b60cb36cf88db2..3ec7cb11f72ab554afd7fe3d15aa0674768136f5 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/TestUtils.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/TestUtils.java
@@ -4,7 +4,7 @@ package net.sourceforge.plantuml.servlet;
 /**
  * Utility class for the unit tests
  */
-public class TestUtils {
+public abstract class TestUtils {
 
     /*
      * Theses strings are the compressed form of a PlantUML diagram.
@@ -20,8 +20,4 @@ public class TestUtils {
      */
     public static final String SEQBOB = "SyfFKj2rKt3CoKnELR1Io4ZDoSa70000";
 
-    protected TestUtils() {
-        // prevents calls from subclass
-        throw new UnsupportedOperationException();
-    }
 }
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/WebappTestCase.java b/src/test/java/net/sourceforge/plantuml/servlet/WebappTestCase.java
index 25c51723f38092bc9a7e7f720fcf5addcc302079..6ff12c084cad06d052a03222f73c957d48c17573 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/WebappTestCase.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/WebappTestCase.java
@@ -1,22 +1,47 @@
 package net.sourceforge.plantuml.servlet;
 
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLConnection;
+
 import junit.framework.TestCase;
+import net.sourceforge.plantuml.servlet.server.EmbeddedJettyServer;
+import net.sourceforge.plantuml.servlet.server.ExternalServer;
+import net.sourceforge.plantuml.servlet.server.ServerUtils;
+
 
 public abstract class WebappTestCase extends TestCase {
 
-    private ServerUtils serverUtils;
+    private final ServerUtils serverUtils;
 
     public WebappTestCase() {
-        super();
+        this(null);
     }
 
     public WebappTestCase(String name) {
         super(name);
+
+        String uri = System.getProperty("system.test.server", "");
+        //uri = "http://localhost:8080/plantuml";
+        if (!uri.isEmpty()) {
+            // mvn test -DskipTests=false -DargLine="-Dsystem.test.server=http://localhost:8080/plantuml"
+            System.out.println("Test against external server: " + uri);
+            serverUtils = new ExternalServer(uri);
+            return;
+        }
+
+        // mvn test -DskipTests=false
+        System.out.println("Test against embedded jetty server.");
+        serverUtils = new EmbeddedJettyServer();
     }
 
     @Override
     public void setUp() throws Exception {
-        serverUtils = new ServerUtils(true);
+        serverUtils.startServer();
     }
 
     @Override
@@ -28,4 +53,54 @@ public abstract class WebappTestCase extends TestCase {
         return serverUtils.getServerUrl();
     }
 
+    public String getContentText(final URL url) throws IOException {
+        try (final InputStream responseStream = url.openStream()) {
+            return getContentText(responseStream);
+        }
+    }
+
+    public String getContentText(final URLConnection conn) throws IOException {
+        try (final InputStream responseStream = conn.getInputStream()) {
+            return getContentText(responseStream);
+        }
+    }
+
+    public String getContentText(final InputStream stream) throws IOException {
+        try (
+            final InputStreamReader isr = new InputStreamReader(stream);
+            final BufferedReader br = new BufferedReader(isr);
+        ) {
+            String line;
+            StringBuffer sb = new StringBuffer();
+            while ((line = br.readLine()) != null) {
+                sb.append(line);
+                sb.append("\n");
+            }
+            return sb.toString().trim();
+        }
+    }
+
+    public byte[] getContentAsBytes(final URL url) throws IOException {
+        try (final InputStream responseStream = url.openStream()) {
+            return getContentAsBytes(responseStream);
+        }
+    }
+
+    public byte[] getContentAsBytes(final URLConnection conn) throws IOException {
+        try (final InputStream responseStream = conn.getInputStream()) {
+            return getContentAsBytes(responseStream);
+        }
+    }
+
+    public byte[] getContentAsBytes(final InputStream stream) throws IOException {
+        try (final ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) {
+            byte[] buf = new byte[1024];
+            int n = 0;
+            while ((n = stream.read(buf)) != -1) {
+                byteStream.write(buf, 0, n);
+            }
+            return byteStream.toByteArray();
+        }
+    }
+
 }
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/ServerUtils.java b/src/test/java/net/sourceforge/plantuml/servlet/server/EmbeddedJettyServer.java
similarity index 63%
rename from src/test/java/net/sourceforge/plantuml/servlet/ServerUtils.java
rename to src/test/java/net/sourceforge/plantuml/servlet/server/EmbeddedJettyServer.java
index 1f692ed69d08b0876d3205c6bf4efa519c2586bd..75b81de6f9f1815728b0a19a3dcb8006d186ed1a 100644
--- a/src/test/java/net/sourceforge/plantuml/servlet/ServerUtils.java
+++ b/src/test/java/net/sourceforge/plantuml/servlet/server/EmbeddedJettyServer.java
@@ -1,4 +1,4 @@
-package net.sourceforge.plantuml.servlet;
+package net.sourceforge.plantuml.servlet.server;
 
 import java.net.InetSocketAddress;
 
@@ -6,20 +6,14 @@ import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.webapp.WebAppContext;
 
-public class ServerUtils {
+
+public class EmbeddedJettyServer implements ServerUtils {
 
     private Server server;
 
-    public ServerUtils(boolean start) throws Exception {
+    public EmbeddedJettyServer() {
         server = new Server(new InetSocketAddress("127.0.0.1", 0));
         server.addBean(new WebAppContext(server, "src/main/webapp", "/plantuml"));
-        if (start) {
-            startServer();
-        }
-    }
-
-    public ServerUtils() throws Exception {
-        this(false);
     }
 
     public void startServer() throws Exception {
@@ -32,7 +26,7 @@ public class ServerUtils {
 
     public String getServerUrl() {
         Connector connector = server.getConnectors()[0];
-        return String.format("http://%s:%d/plantuml/", connector.getHost(), connector.getLocalPort());
+        return String.format("http://%s:%d/plantuml", connector.getHost(), connector.getLocalPort());
     }
 
 }
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/server/ExternalServer.java b/src/test/java/net/sourceforge/plantuml/servlet/server/ExternalServer.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f50452c38a440adc83c27ea33eed51df3b8f89b
--- /dev/null
+++ b/src/test/java/net/sourceforge/plantuml/servlet/server/ExternalServer.java
@@ -0,0 +1,23 @@
+package net.sourceforge.plantuml.servlet.server;
+
+
+public class ExternalServer implements ServerUtils {
+
+    private final String uri;
+
+    public ExternalServer(String uri) {
+        this.uri = uri;
+    }
+
+    @Override
+    public void startServer() throws Exception { }
+
+    @Override
+    public void stopServer() throws Exception { }
+
+    @Override
+    public String getServerUrl() {
+        return this.uri;
+    }
+    
+}
diff --git a/src/test/java/net/sourceforge/plantuml/servlet/server/ServerUtils.java b/src/test/java/net/sourceforge/plantuml/servlet/server/ServerUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..d4a0c1d63a46dba3d830e4a47bd23e702e136452
--- /dev/null
+++ b/src/test/java/net/sourceforge/plantuml/servlet/server/ServerUtils.java
@@ -0,0 +1,12 @@
+package net.sourceforge.plantuml.servlet.server;
+
+
+public interface ServerUtils {
+
+    public void startServer() throws Exception;
+
+    public void stopServer() throws Exception;
+
+    public abstract String getServerUrl();
+
+}