Quantcast
Viewing all articles
Browse latest Browse all 10

Implementing the view with Java Server Pages (JSP)

We want to offer a self-registration feature for our web application. Any user should be allowed to register a new account by entering a username and a password. So what we actually need is a very simple user registration form. Our form has input fields for first name, last name, email address, password and another one for the password to make sure the password is free of typos. The email address serves as the unique user identifier in our system. But in this tutorial I am not going to check if the email address is a valid email address (you could use one of the many libraries available for that purpose or write your own regex to validate the email address). Furthermore, right below the registration form, we want to offer a login form allowing a user to login with an existing account.

Before we will discuss about our /welcome.jsp let’s first discuss about some JavaScript, jQuery and JSON stuff. Our REST Services all produce JSON responses. One of our services even consumes JSON data. From that we can tell that we need to be able to create JSON from JavaScript Objects and to create JavaScript Objects from JSON (the latter is very simple because jQuery does it all for us). Unfortunately, jQuery does not really offer support for converting a JavaScript Object to a JSON String. Since we want to use jQuery we could simply use the jquery-json plugin. I have not chosen to use it because of a blog entry from John Resig, the author of jQuery. He said: In the meantime PLEASE start migrating your JSON-using applications over to Crockford’s json2.js. On the other side jquery-json is actually based on json2, so why not using json2 directly? So we will use json2, please see json2 at Github for more information. The library detects if the browser offers native JSON support or not, i.e. JSON.stringify. In case the browser does not offer native JSON support json2 will add ECMAScript 5 compatible support for JSON. ECMAScript 5 was published in December 2009, so json2 is especially relevant for older browser versions published around that date. ECMAScript 5 also adds the “use strict” mode which is a good practice to use – especially while developing your web application (we also make use of “use strict”). For more information about strict mode please check John Resig’s blog mentioned above.

Before you continue please first download the latest json2.js and the latest jQuery.js version (at the time writing this tutorial the lates jQuery was 1.7.2, so my js file is jquery-1.7.2.js):

Oh well, we have talked about some jQuery stuff now, so let’s start to integrate jQuery into our web application. When integrating jQuery into your web applications it is a good idea to use a common Content Delivery Network (CDN). One of the most popular CDNs comes from Google and is called Google Libraries API or simply Google APIs (I usually call it Google APIs). Within your aplications you can simply reference jQuery directly from the Google APIs. And there is a good reason to do so: imagine you just visited some webpage that references jQuery from the Google APIs, then you go to some other page which also references jQuery from the Google APIs. In this case you could profit from a better performance due to caching. The more webpages use the Google APIs the better the overall performance of the web will be (please keep in mind that HTTPS usually is a killer for caching). Integrating jQuery from Google APIs is very simple. When integrating jQuery you (or any other external content) you should you should always think about the protocol. If your site is accessed via HTTPS then you shold also reference the external resources (i.e. js or css files) also via HTTPS. If you would use HTTP in such cases then the browsers usually show some warning. As section 4.2 of RFC 3986 states you could simply use this here:

example for external uri in /WEB-INF/includes/head/jquery.jsp:
1
2
3
4
5
<!-- instead of this (this is old school) -->
<script src="<%=request.isSecure() ? "https":"http" %>://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script>
<!-- you should use this -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script>

Doesn’t the second script tag look much better than the first one? The second script tag simply tells the browser to choose HTTPS or HTTP depending on what ever (HTTP or HTTPS) is used on the current page. See here for a great overview by Dave Ward. Actually, also see Dave Ward’s comment about 3 reasons why you should let Google host jQuery for you. His blogs describe really good why you should simply use “//” and how that works as well as why you should use a CDN and what you should have in your mind when working with HTTPS.

But now back to this tutorial: there is one problem we have: what if the referenced resource is not available? Or in our case: what if jQuery cannot be loaded from the Google APIs, i.e. if Google is blocked for some reason? Before answering this question we will implement a JSP include file called jquery.jsp which can be used by all our other JSPs to include jQuery or jQuery Plugins (we will only discuss jQuery Plugins). Here is the code for /WEB-INF/includes/head/jquery.jsp:

/WEB-INF/includes/head/jquery.jsp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<%@page contentType="text/html" pageEncoding="UTF-8"%>
     
<!-- jq integration from google cdn (content delivery network) -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js" type="text/javascript"></script>
<!-- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js" type="text/javascript"></script> -->
        
<script type="text/javascript">
    //make sure jq is really loaded from google, else load it from our local server
    if (!window.jQuery){
        document.write(unescape("%3Cscript src='<%=request.getContextPath() %>/js/jquery/jquery-1.7.2.js' type='text/javascript'%3E%3C/script%3E"));
    }
</script>
     
<!-- jq-ui integration from google cdn (content delivery network) -->
<!-- you could do it this way, but we don't really need it for our tutorial-->
<!--
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.js" type="text/javascript"></script>
<link href="//ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>
-->

First of all we will reference jQuery from the Google APIs either via HTTP or HTTPS. We have to consider HTTPS to avoid browser warnings, which usually come up when an HTTPS page tries to access some content via HTTP. Furthermore you can choose between jquery.js or jquery.min.js from the Google APIs. The latter is minified while the jquery.js file is better for debugging. And now the magic: if jQuery could not be laoded for some reason then window.jQuery will be undefined. In such cases we will simply fall back to a locally deployed version of jQuery which is placed at /js/jquery/jquery-1.7.2.js (as you can see we use version 1.7.2 while the one from the Google APIs is the latest 1.7.x version). But why are we using document.write(…)? This will add the new script tag to your head at the right place! Please consider that you should not use DOM methonds to create a new element and then adding it to the DOM. This would create a Non-blocking script element, which means that the script is loaded asynchronously instead of synchronously! See Stoyan Stefanov’s comment about Non-blocking JavaScript Downloads in the YUI Blog. Andrea Giammarchi’s blog about discusses document.write() is also really nice. On her blog you will learn where the new script tag is added when using document.write() in the header for loading a remote script.

Now let’s start with the welcome.jsp which is placed at the application’s context root and contains two simple HTML forms. The first thing you can see is an automatic redirection to /secure/index.jsp in case the user is already logged in. Then we include both json2 and jQuery. The action attribute of the registration form is set to /services/auth/register and the method is post. This means when submitting the form the data entered by the user is sent to /services/auth/register via post which is exactly the endpoint of our register REST Service. At this point you can go back to the previous step and have a look at our UserManagementService class to recall what happens in our register REST Service. The second HTML form we have in the /welcome.jsp file is for users that want to login with their already existing user account. This form submits to our login REST Service which we implemented earlier. So the /welcome.jsp file contains two HTML forms (one for login and one for registration) and each of the forms submit to the corresponding REST Service for executing a login or a registration. Last but not least our /welcome.jsp offers a link for navigation to /secure/index.jsp. As you will see later everything under /secure/* is secured content which means that you can only access that content if you are logged in. Both login and logout as well as registration backend logic have been discussed in the previous step. For both forms (register and login) we have registerd submit event listeners. They are executed when clicking on one of the submit buttons and are responsible for making an Ajax call. In case of the registration submit button all form data to be sent is converted into a JSON String. I also handle the server responses in one of the handlers. If the registration or login succeeds ew simply forward to /secure/index.jsp via JavaScript. As you can see in the success handler we check for data.status == “SUCCESS”. This comes from our JsonResponse Envelope (see JsonResponse.java above).

For styling I have used an external css file. I will not discuss it here in detail. Below you find the sources of /welcome.jsp and /css/auth.css (below you will also find the corresponding screenshot):

/welcome.jsp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<%@page contentType="text/html" pageEncoding="UTF-8"
%><%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'
%><c:if test="${pageContext.request.userPrincipal!=null}">
    <c:redirect url="/secure/index.jsp"/>
    <!-- this will redirect if user is already logged in -->
</c:if>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
                       "http://www.w3.org/TR/html4/loose.dtd">
 
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="./css/auth.css" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Welcome Page</title>
    
    <!-- alternative: http://code.google.com/p/jquery-json/ -->
    <!--
    John Resig (author of jQuery) said:
      "In the meantime PLEASE start migrating your JSON-using applications over to Crockford's json2.js"
    -->
    <script src="<%=request.getContextPath() %>/js/json2.js" type="text/javascript"></script>
    
    <%@ include file="/WEB-INF/includes/head/jquery.jsp" %>
    
    <script type="text/javascript">
        $(function(){
            "use strict";
            
            $(document.forms['registerForm']).submit(function(event){
                var data = {
                    fname: this.fname.value,
                    lname: this.lname.value,
                    email: this.email.value,
                    password1: this.password1.value,
                    password2: this.password2.value
                };
                var destinationUrl = this.action;
                
                $.ajax({
                    url: destinationUrl,
                    type: "POST",
                    //data: data,
                    data: JSON.stringify(data),
                    contentType: "application/json",
                    cache: false,
                    dataType: "json",
                    
                    success: function (data, textStatus, jqXHR){
                        //alert("success");
                        if (data.status == "SUCCESS" ){
                           //redirect to secured page
                           window.location.replace("https://"+window.location.host+"<%=request.getContextPath() %>/secure/index.jsp");
                        }else{
                            alert("failed");
                        }
                    },
                    
                    error: function (jqXHR, textStatus, errorThrown){
                        alert("error - HTTP STATUS: "+jqXHR.status);
                        
                    },
                    
                    complete: function(jqXHR, textStatus){
                        //alert("complete");
                        //i.e. hide loading spinner
                    },
                    
                    statusCode: {
                        404: function() {
                          alert("page not found");
                        },
                    }
                    
                
                });
                
                //event.preventDefault();
                return false;
            });
            
            $(document.forms['loginForm']).submit(function(event){
                
                var data = {
                    email: this.email.value,
                    password: this.password.value
                };
                var destinationUrl = this.action;
                    
                $.ajax({
                    url: destinationUrl,
                    type: "POST",
                    data: data,
                    cache: false,
                    dataType: "json",
                        
                    success: function (data, textStatus, jqXHR){
                        //alert("success");
                        if (data.status == "SUCCESS" ){
                            //redirect to secured page
                            window.location.replace("https://"+window.location.host+"<%=request.getContextPath() %>/secure/index.jsp");
                        }else{
                            alert("failed");
                        }
                    },
                        
                    error: function (jqXHR, textStatus, errorThrown){
                        alert("error - HTTP STATUS: "+jqXHR.status);
                    },
                        
                    complete: function(jqXHR, textStatus){
                        //alert("complete");
                    }                   
                });
                
                //event.preventDefault();
                return false;
            });
        });
    </script>
    
  </head>
  <body>
   
    <h1>Welcome to our secured Web Application</h1>
    <a href="<%=request.getContextPath() %>/secure/index.jsp" >go to secured page</a>
    <br/><br/><br/>
     
    <div class="register">
      <form id="registerForm" name="registerForm" action="<%=request.getContextPath() %>/services/auth/register" method="post">
        <fieldset>
          <legend>Registration</legend>
             
          <div>
            <label for="fname">First Name</label>
            <input type="text" id="fname" name="fname"/>
          </div>
          <div>
            <label for="lname">Last Name</label>
            <input type="text" id="lname" name="lname"/>
          </div>
             
          <div>
            <label for="email">Email</label>
            <input type="text" id="email" name="email"/>
          </div>
          <div>
            <label for="password1">Password</label>
            <input type="password" id="password1" name="password1"/>
          </div>
          <div>
            <label for="password2">Password (repeat)</label>
            <input type="password" id="password2" name="password2"/>
          </div>
             
          <div class="buttonRow">
            <input type="submit" value="Register and Login" />
          </div>
           
        </fieldset>
      </form>
    </div>
      
    <br/><br/><br/>
    
    <div class="login">
      <form id="loginForm" name="loginForm" action="<%=request.getContextPath() %>/services/auth/login" method="post">
        <fieldset>
          <legend>Login</legend>
             
          <div>
            <label for="email">Email</label>
            <input type="text" id="email" name="email"/>
          </div>
          <div>
            <label for="password">Password</label>
            <input type="password" id="password" name="password"/>
          </div>
             
          <div class="buttonRow">
            <input type="submit" value="Login" />
          </div>
           
        </fieldset>
      </form>
    </div>
 
  </body>
   
</html>
/css/auth.css:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
.login,
.register{
  font-family: Arial,sans-serif;
  font-size: 13px;
}
 
.login fieldset,
.register fieldset{
  padding-top: 1em;
  padding-bottom: 1em;
  border: 1px solid #0053A1;
  width: 380px;
}
 
.login legend,
.register legend{
  color: #fff;
  background: #0053A1;
  border: 1px solid #0053A1;
  padding: 1px 5px;
}
     
.login div,
.register div{
  margin-bottom: 0.5em;
  text-align: left;
}
     
.login label,
.register label{
  width: 140px;
  float: left;
  text-align: left;
  margin-right: 10px;
  padding: 2px 0px;
  display: block;
}
 
.login input[type=text], .login input[type=password],
.register input[type=text], .register input[type=password]{
  color: #0053A1;
  background: #fee3ad;
  border: 1px solid #0053A1;
  padding: 2px 5px;
  width:200px;
}
 
.login .buttonRow,
.register .buttonRow{
  text-align: left;
}
 
.login input[type=submit],
.register input[type=submit]{
  color: #fff;
  background: #0053A1;
  border: 2px outset #0053A1;
}
.login .authError{
    margin-bottom:20px;
    color:red;
    text-align:center;
For more details about this check spring web hosting website.}

Viewing all articles
Browse latest Browse all 10

Trending Articles