{"id":188,"date":"2010-03-09T13:19:46","date_gmt":"2010-03-09T13:19:46","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/2010\/03\/09\/why-and-how-to-use-jetty-in-mission-critical-production\/"},"modified":"2017-12-26T23:03:53","modified_gmt":"2017-12-26T23:03:53","slug":"why-and-how-to-use-jetty-in-mission-critical-production","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/why-and-how-to-use-jetty-in-mission-critical-production\/","title":{"rendered":"Why and how to use Jetty in mission-critical production"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-4137 aligncenter\" src=\"http:\/\/www.scmgalaxy.com\/tutorials\/wp-content\/uploads\/2010\/03\/how-to-use-jetty.png\" alt=\"how-to-use-jetty\" width=\"600\" height=\"400\" srcset=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2010\/03\/how-to-use-jetty.png 600w, https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2010\/03\/how-to-use-jetty-300x200.png 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\n<p>This article is a summary of a seminar I had on the topic. If it seems like it\u2019s a continuation of an existing discussion that\u2019s because, to some extent, it is. If you haven\u2019t been discussing exchanging your app server, this article probably isn\u2019t very interesting to you.<\/p>\n<p>By putting the application server inside my application instead of the other way around, I was able to leap tall buildings in a single bound.<\/p>\n<p>The embedded application server<\/p>\n<p>This is how I deploy <a href=\"http:\/\/svn.brodwall.com\/demo\/embedded-container\/\" target=\"_blank\" rel=\"noopener\">my sample application<\/a> to a new test environment (or to production):<\/p>\n<ol>\n<li>mvn install<\/li>\n<li>scp -server\/target\/-1.0.onejar.jar appuser@appserver:\/home\/appuser\/test-env1\/<\/li>\n<li>ssh appuser@appserver \u201ccd \/home\/appuser\/test-env1\/ &amp;&amp; java -jar -1.0.onejar.jar&amp;\u201d<\/li>\n<\/ol>\n<p>This require no prior installed software on the appserver (with the exception of the JVM). It requires no prior configuration. Rolling back is a matter of replacing one jar-file with another. Clustering is a matter of deploying the same application several times.<\/p>\n<p>In order to make this work in a real environment, there are a many details you as a developer need to take care of. As a matter of fact, you will have to take responsibility for your operational environment. The good news is that creating a good operational environment is not more time-consuming than trying to cope with the feed and care of a big-a Application Server.<\/p>\n<p>In this scheme every application comes with its own application server in the form of jetty\u2019s jar-files embedded in the deployed jar-file.<\/p>\n<p>The advantages<\/p>\n<p>Why would you want to do something like this?<\/p>\n<ul>\n<li><strong>Independent application<\/strong>: If you\u2019ve ever been told that you can\u2019t use Java 1.5 because that would require an upgrade of the application server. And if we upgrade the application server, that could affect someone else adversely. So we need to start a huge undertaking to find out who could possibly be affected.<\/li>\n<li><strong>Developer managed libraries<\/strong>: Similar problems can occur with libraries. Especially those that come with the application server. For example: Oracle OC4J helpfully places a preview version of JPA 1.0 first in your classpath. If you want to use Hibernate with JPA 1.0-FINAL, it will mostly work. Until you try to use a annotation that was changed after the preview version (@Discriminator, for example). The general rule is: <em>If an API comes with your app server, you\u2019re better served by staying away from it.<\/em> A rather bizarre state of affairs.<\/li>\n<li><strong>Deployment, configuration and upgrades<\/strong>: Each version of the application, including all its dependencies is packaged into a single jar-file that can be deployed on several application server, or several times on the same application server (with different ports). The configuration is read from a properties-file in the current working directory. On the minus side, there\u2019s no fancy web UI where you can step through a wizard to deploy the application or change the configuration. On the plus side, there is no fancy web UI \u2026. If you\u2019ve used one such web UI, you know what I mean.<\/li>\n<li><strong>Continuous deployment<\/strong>: As your maven-repository will contain stand alone applications, creating a continuous deployment scheme is very easy. In my previous environment, a cron job running wget periodically was all that was needed to connect the dots. Having each server environment PULL the latest version gives a bit more flexibility if you want many test environments. (However, if you\u2019re doing automated PUSH deployment, it\u2019s probably just as practical for you).<\/li>\n<li><strong>Same code in test and production<\/strong>: The fact that you can <a href=\"http:\/\/svn.brodwall.com\/demo\/embedded-container\/embedded-container-web\/src\/test\/java\/no\/steria\/embeddedcontainer\/web\/HelloWebTest.java\" target=\"_blank\" rel=\"noopener\">start Jetty inside a plain old JUnit test<\/a> means that it is ideal for taking your automated tests one step further. However, if you test with Jetty and deploy on a different Application Server, the difference will occasionally trip you. It\u2019s not a big deal. You have to test in the server environment anyway. But why not eliminate the extra source of pain if you can?<\/li>\n<li><strong>Licenses<\/strong>: Sure, you can afford to pay a few million $ for an application server. You probably don\u2019t have any better use for that money, anyway, right? However, if you have to pay licenses for each test-server in addition, it will probably mean that you will test less. We don\u2019t want that.<\/li>\n<li><strong>Operations<\/strong>: In my experience, operations people don\u2019t like to mess around with the internals of an Application Server. An executable jar file plus a script that can be run with [start|status|stop] may be a much better match.<\/li>\n<\/ul>\n<p>The missing bits<\/p>\n<p>Taking control of the application server takes away a lot of complex technology. This simplifies and makes a lot of stuff cheaper. It also puts you back in control of the environment. However, it forces you to think about some things that might\u2019ve been solved for you before:<\/p>\n<ul>\n<li><strong>Monitoring<\/strong>: The first step of monitoring is simple: Just make sure you write to a log file that is being monitored by your operations department. The second step requires some work: Create a servlet (or a Jetty Handler) that a monitoring tool can ping to check that everything is okay. Taking control of this means that you can improve it: Check if your data sources can connect, if your file share is visible, if that service answers. Maybe add application-calibrated load reporting. Beyond that, Jetty has good JMX support, but I\u2019ve never needed it myself.<\/li>\n<li><strong>Load balancing<\/strong>: My setup supports no load balancing or failover out of the box. However, this is normally something that the web server or routers in front of the application server anyway. You might want to look into <a href=\"http:\/\/docs.codehaus.org\/display\/JETTY\/Configuring+mod_proxy\" target=\"_blank\" rel=\"noopener\">Jetty\u2019s options for session affinity<\/a>, if you need that.<\/li>\n<li><strong>Security<\/strong>: Jetty supports JAAS, of course. Also: In all the environments I\u2019ve been working with (CA SiteMinder, Sun OpenSSO, Oracle SSO), the SSO server sends the user name of the currently logged in user as an HTTP header. You can get far by just using that.<\/li>\n<li><strong>Consistency<\/strong>: If you deploy more than one application as an embedded application server, the file structure used by an application (if any) should be standardized. As should the commands to start and stop the application. And the location of logs. Beyond that, reuse what you like, recreate what you don\u2019t.<\/li>\n<\/ul>\n<p>Taking control of your destiny<\/p>\n<p>Using an embedded application server means using the application server as a library instead of a framework. It means taking control of your \u201cmain\u201d method. There\u2019s a surprisingly small number of things you need to work out yourself. In exchange, you get the control to do many things that are impossible with a big-A Application Server.<\/p>\n<p><strong>Reference:<\/strong> <a href=\"http:\/\/www.javaworld.com\/community\/?q=node\/4133\" target=\"_blank\" rel=\"noopener\">http:\/\/www.javaworld.com\/community\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article is a summary of a seminar I had on the topic. If it seems like it\u2019s a continuation of an existing discussion that\u2019s because, to some extent, it is. If you haven\u2019t been discussing exchanging your app server, this article probably isn\u2019t very interesting to you. By putting the application server inside my&#8230;<\/p>\n","protected":false},"author":1,"featured_media":4137,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","_joinchat":[],"footnotes":""},"categories":[2],"tags":[3452,1122,3113,3449,3454,1806,3446,3455,3447,3448,3453,213,1980,842,3451,3450],"class_list":["post-188","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorised","tag-application-server","tag-guide","tag-how-to","tag-how-to-use-jetty","tag-how-to-use-jetty-in-test-environment","tag-instruction","tag-jetty","tag-jetty-advantages-in-test-environment","tag-mission-critical","tag-production","tag-test-environment","tag-tutorial","tag-use","tag-why","tag-why-jetty","tag-why-use-jetty"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/188","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=188"}],"version-history":[{"count":2,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/188\/revisions"}],"predecessor-version":[{"id":4139,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/188\/revisions\/4139"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media\/4137"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=188"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=188"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=188"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}