{"id":114,"date":"2005-08-30T17:30:38","date_gmt":"2005-08-30T16:30:38","guid":{"rendered":"http:\/\/coding.mu\/archives\/2005\/08\/30\/experimenting-with-rapid-web-development\/"},"modified":"2022-05-15T15:11:34","modified_gmt":"2022-05-15T14:11:34","slug":"rapid-web-development","status":"publish","type":"post","link":"https:\/\/priscimon.net\/coding\/2005\/08\/30\/rapid-web-development\/","title":{"rendered":"Rapid web development"},"content":{"rendered":"<p>Lately, I have been experimenting with a technique to accelerate web application development in Java. It does without custom servlets and relies on Java Server Pages (JSP).<\/p>\n<p>Here is how it is implemented.<\/p>\n<p>First, define an interface called <code>Controller<\/code>. Declare a method called <code>handleRequest<\/code> that takes as arguments an <code>HttpServletRequest<\/code> and an <code>HttpServletResponse<\/code>. The method must throw an <code>Exception<\/code>.<\/p>\n<pre><code>package web;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\npublic interface Controller {\n\n    public void handleRequest(HttpServletRequest request, \n            HttpServletResponse response) throws Exception;\n}\n\n<\/code><\/pre>\n<p>Next, create a hierarchy of directories and JSP files. The structure must follow the logical organisation of the application. For example, assuming we are writing a page for users to register new accounts, we create the following files in a directory called <code>\/user\/register<\/code>.<\/p>\n<ul>\n<li>\u00c2\u00a0<strong>index.jsp &#8212;<\/strong> the entry point for our controller<\/li>\n<li><strong>default.jsp<\/strong> &#8212; the default view<\/li>\n<li><strong>success.jsp<\/strong> &#8212; the view for a successful registration<\/li>\n<\/ul>\n<p>Next, in file <code>index.jsp<\/code>, write the following code.<\/p>\n<pre><code>&lt;% web.Controller c = new web.Controller() {\n\n    public void handleRequest(HttpServletRequest request,\n            HttpServletResponse response) throws Exception {\n\n        account = null;\n\n        messages = new java.util.ArrayList();\n\n        username = request.getParameter(username);\n        password1 = request.getParameter(password1);\n        password2 = request.getParameter(password2);\n        email = request.getParameter(email);\n\n        if (request.getParameter(register) != null) {\n            registerActionPerformed(request, response);\n        }\n\n        request.setAttribute(messages, messages);\n\n        request.setAttribute(username, username);\n        request.setAttribute(email, email);\n\n        if (account != null) {\n            request.getRequestDispatcher(success.jsp).\n                    forward(request, response);\n        } else {\n            request.getRequestDispatcher(default.jsp).\n                    forward(request, response);\n        }\n    }\n\n    protected void registerActionPerformed(HttpServletRequest request,\n            HttpServletResponse response) throws Exception {\n\n        if (validate()) {\n            model.user.Account existing = model.user.AccountRepository.\n                    getByUsername(username);\n            if (existing != null)\n                messages.add(error.duplicate_username);\n\n            existing = model.user.AccountRepository.getByEmail(email);\n            if (existing != null)\n                messages.add(error.duplicate_email);\n\n            if (messages.isEmpty()) {\n                model.user.RegisterAccountService service = \n                        new model.user.RegisterAccountService();\n                account = service.register(username, password1, email);\n            }\n        }\n    }\n\n    protected boolean validate() throws Exception {\n        if (username == null || username.trim().length() == 0)\n            messages.add(error.username_missing);\n\n        if (password1 == null || password1.trim().length() == 0)\n            messages.add(error.password_missing);\n\n        if (password1 != null)\n            if (!password1.equals(password2))\n                messages.add(error.password_mismatch);\n\n        if (email == null || email.trim().length() == 0)\n            messages.add(error.email_missing);\n\n        return messages.isEmpty();\n    }\n\n    private model.user.Account account;\n\n    private java.util.ArrayList messages;\n\n    private String username;\n    private String password1, password2;\n    private String email;\n};\n\nc.handleRequest(request, response);\n%&gt;\n\n<\/code><\/pre>\n<p>Next, create files <code>default.jsp<\/code> and <code>success.jsp<\/code>. File <code>default.jsp<\/code> could look like this:<\/p>\n<pre><code>&lt; %@page contentType=text\/html%&gt;\n&lt; %@page pageEncoding=UTF-8%&gt;\n&lt; %@taglib uri=http:\/\/java.sun.com\/jsp\/jstl\/core prefix=c%&gt; \n&lt; %@taglib uri=http:\/\/java.sun.com\/jsp\/jstl\/fmt prefix=fmt%&gt; \n\n&lt; !DOCTYPE HTML PUBLIC -\/\/W3C\/\/DTD HTML 4.01 Transitional\/\/EN\n   http:\/\/www.w3.org\/TR\/html4\/loose.dtd&gt;\n\n&lt;html&gt;\n    &lt;body&gt;\n        &lt;h1&gt;&lt;fmt:message key=title.register_account \/&gt;&lt;\/h1&gt;\n    &lt;\/body&gt;\n&lt;\/html&gt;\n\n<\/code><\/pre>\n<p>So far this approach has shown the following benefits.<\/p>\n<ul>\n<li><code>index.jsp<\/code> becomes a controller.<\/li>\n<li>Because JSP are compiled automatically, I avoid manual compilation.<\/li>\n<li>I don&#8217;t have to map individual JSP files, as I do with servlets.<\/li>\n<li>URLs are consistent.<\/li>\n<\/ul>\n<p>This technique is unsuitable for large projects but is good enough for writing quick web application projects.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lately, I have been experimenting with a technique to accelerate web application development in Java. It does without custom servlets and relies on Java Server Pages (JSP). Here is how it is implemented. First, define an interface called Controller. Declare a method called handleRequest that takes as arguments an HttpServletRequest and an HttpServletResponse. The method [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-114","post","type-post","status-publish","format-standard","hentry","category-general"],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3I4g9-1Q","jetpack-related-posts":[],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/posts\/114","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/comments?post=114"}],"version-history":[{"count":17,"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/posts\/114\/revisions"}],"predecessor-version":[{"id":1716,"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/posts\/114\/revisions\/1716"}],"wp:attachment":[{"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/media?parent=114"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/categories?post=114"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/priscimon.net\/coding\/wp-json\/wp\/v2\/tags?post=114"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}