{"id":6509,"date":"2018-09-27T20:07:55","date_gmt":"2018-09-27T20:07:55","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=6509"},"modified":"2018-09-27T20:07:55","modified_gmt":"2018-09-27T20:07:55","slug":"self-hosting-tomcat-in-a-java-web-application","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/self-hosting-tomcat-in-a-java-web-application\/","title":{"rendered":"Self hosting Tomcat in a Java Web application"},"content":{"rendered":"<p>Following on from my previous post where I created a web application in Java, let&#8217;s now look at hosting the WAR within an embedded Tomcat instance.<\/p>\n<p><strong>Adding dependencies to include embedded Tomcat<\/strong><\/p>\n<p>Add the following to your pom.xml (after the description tag)<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;properties&gt;\r\n   &lt;tomcat.version&gt;9.0.0.M6&lt;\/tomcat.version&gt;\r\n&lt;\/properties&gt;\r\n<\/pre>\n<p><em>Note: There&#8217;s a newer version of a couple of the dependencies, but this version exists for all three of the dependencies we&#8217;re about to add.<\/em><\/p>\n<p>Now, add following dependencies<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;dependencies&gt;\r\n   &lt;dependency&gt;\r\n      &lt;groupId&gt;org.apache.tomcat.embed&lt;\/groupId&gt;\r\n      &lt;artifactId&gt;tomcat-embed-core&lt;\/artifactId&gt;\r\n      &lt;version&gt;${tomcat.version}&lt;\/version&gt;\r\n   &lt;\/dependency&gt;\r\n   &lt;dependency&gt;\r\n      &lt;groupId&gt;org.apache.tomcat.embed&lt;\/groupId&gt;\r\n      &lt;artifactId&gt;tomcat-embed-jasper&lt;\/artifactId&gt;\r\n      &lt;version&gt;${tomcat.version}&lt;\/version&gt;\r\n   &lt;\/dependency&gt;\r\n   &lt;dependency&gt;\r\n      &lt;groupId&gt;org.apache.tomcat.embed&lt;\/groupId&gt;\r\n      &lt;artifactId&gt;tomcat-embed-logging-juli&lt;\/artifactId&gt;\r\n      &lt;version&gt;${tomcat.version}&lt;\/version&gt;\r\n   &lt;\/dependency&gt;\r\n&lt;\/dependencies&gt;\r\n<\/pre>\n<p>Time to run <em>mvn install<\/em> if not auto-importing.<\/p>\n<p><strong>Time to create the entry point\/application<\/strong><\/p>\n<p>Let&#8217;s add a new package to the src folder, com.putridparrot now add a Java file, mine&#8217;s HostApp.java, here&#8217;s the code<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npackage com.putridparrot;\r\n\r\nimport org.apache.catalina.LifecycleException;\r\nimport org.apache.catalina.startup.Tomcat;\r\n\r\nimport javax.servlet.ServletException;\r\nimport java.io.File;\r\n\r\npublic class HostApp {\r\n    public static void main(String&#x5B;] args) throws ServletException, LifecycleException {\r\n\r\n        Tomcat tomcat = new Tomcat();\r\n        tomcat.setBaseDir(&quot;temp&quot;);\r\n        tomcat.setPort(8080);\r\n\r\n        String contextPath = &quot;&quot;;\r\n        String webappDir = new File(&quot;web&quot;).getAbsolutePath();\r\n\r\n        tomcat.addWebapp(contextPath, webappDir);\r\n\r\n        tomcat.start();\r\n        tomcat.getServer().await();\r\n    }\r\n}\r\n<\/pre>\n<p>In the above we create an instance of Tomcat and then set up the port and the context for the web app, including the path to the web folder where our index.jsp is hosted in our WAR file.<\/p>\n<p>We then start the server and then wait until the application is closed.<\/p>\n<p>By the way, it&#8217;s also worth adding logging to the pom.xml. The embedded Tomcat server using &#8220;standard&#8221; Java based logging, so we can add the following to the pom.xml dependencies<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;dependency&gt;\r\n   &lt;groupId&gt;log4j&lt;\/groupId&gt;\r\n   &lt;artifactId&gt;log4j&lt;\/artifactId&gt;\r\n   &lt;version&gt;1.2.15&lt;\/version&gt;\r\n&lt;\/dependency&gt;\r\n<\/pre>\n<p><strong>Create a run configuration<\/strong><\/p>\n<p>Now select Edit Configuration and add a configuration that runs main from HostApp.<\/p>\n<p>Adding gzip\/compression support, before we start the server. Hence select Application and set Main class to com.putridparrot.HostApp.<\/p>\n<p><strong>Testing<\/strong><\/p>\n<p>Run the newly added application configuration, don&#8217;t worry about the exceptions. You should see a line similar to <\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\nINFO: Starting ProtocolHandler &#x5B;http-nio-8080]\r\n<\/pre>\n<p>At this point the server is running, so navigate your browser to http:\/\/localhost:8080 and check that the index.jsp page is displayed.<\/p>\n<p><strong>Configuring the embedded Tomcat for gzip\/compression support<\/strong><\/p>\n<p>I&#8217;ve been looking into compression with gzip on some web code and hence wanted to configure this embedded Tomcat server to handle compression if\/when requested via Accept-Type: gzip etc.<\/p>\n<p>So add the following to the main method (before <em>tomcat.start()<\/em>)<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nConnector c = tomcat.getConnector();\r\nc.setProperty(&quot;compression&quot;, &quot;on&quot;);\r\nc.setProperty(&quot;compressionMinSize&quot;, &quot;1024&quot;);\r\nc.setProperty(&quot;noCompressionUserAgents&quot;, &quot;gozilla, traviata&quot;);\r\nc.setProperty(&quot;compressableMimeType&quot;, &quot;text\/html,text\/xml,text\/css,application\/json,application\/javascript&quot;);\r\ntomcat.setConnector(c);\r\n<\/pre>\n<p>You&#8217;ll also need the import <em>import org.apache.catalina.connector.Connector;<\/em>.<\/p>\n<p><strong>Testing gzip\/compression<\/strong><\/p>\n<p>To test whether Tomcat is using compression is best done with something like curl. I say this because, whilst you can use a browser (such as Chrome&#8217;s) debug tools and see a response with Content-Type: gzip, I really wanted to see the raw compressed data to feel I really was getting compressed responses, the browser automatically decompressed the responses for me.<\/p>\n<p>Go the main method and just change &#8220;on&#8221; to &#8220;force&#8221;<\/p>\n<p>i.e. <\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nc.setProperty(&quot;compression&quot;, &quot;force&quot;);\r\n<\/pre>\n<p>This just forces compression to be on all the time. <\/p>\n<p>Now to test our server is set up correctly. Thankfully Windows 10 seems to have curl available from a command prompt, so this works in Linux or Windows.<\/p>\n<p>Run the following<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\ncurl -H &quot;Accept-Encoding: gzip,deflate&quot; -I &quot;http:\/\/localhost:8080\/index.jsp&quot;\r\n<\/pre>\n<p>This command adds the header Accept-Encoding and then outputs the header (-I) results from accessing the URL. This should show a <em>Content-Encoding: gzip<\/em> if everything was set up correctly. <\/p>\n<p>To confirm everything is as expected, we can download the content from the URL and save it (in this case saved to index.jsp.gz) and then use gzip -d to decompress the file if we wish.<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\ncurl -H &quot;Accept-Encoding: gzip,deflate&quot; &quot;http:\/\/localhost:8080\/index.jsp&quot; -o index.jsp.gz\r\n<\/pre>\n<p>This will create <em>index.jsp.gz<\/em> which should be compressed so we can use<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\ngzip -d index.jsp.gz\r\n<\/pre>\n<p>to decompress it and we should see the expected web page.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Following on from my previous post where I created a web application in Java, let&#8217;s now look at hosting the WAR within an embedded Tomcat instance. Adding dependencies to include embedded Tomcat Add the following to your pom.xml (after the description tag) &lt;properties&gt; &lt;tomcat.version&gt;9.0.0.M6&lt;\/tomcat.version&gt; &lt;\/properties&gt; Note: There&#8217;s a newer version of a couple of the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[228,161,227],"tags":[],"class_list":["post-6509","post","type-post","status-publish","format-standard","hentry","category-j2ee","category-java","category-jsp"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6509","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=6509"}],"version-history":[{"count":4,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6509\/revisions"}],"predecessor-version":[{"id":6515,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6509\/revisions\/6515"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=6509"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=6509"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=6509"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}