How to create a web application from scratch with Java, Eclipse, Tomcat, Hibernate and PostgreSQL – Part #5

This is the fifth in a series of articles. You can find the previous part here: How to create a web application from scratch with Java, Eclipse, Tomcat, Hibernate and PostgreSQL – Part #4

After having analyzed in the preceding article what are the main errors that might occur in case of incorrect configurations or problems in the code, let’s go back to the features of our application and continue with their implementation.

ADDING AN ATTRIBUTE TO THE REQUEST
First, we had left off the topic to pass a User object (Model) from the servlet (Controller) to the JSP page (View) without the latter calling again the getParameter for the parameters sent through the form. The JSP page should instead receive directly the User object. In this way we read the parameters in a single point, reducing the chance of error and avoiding a mismatch of information due to the double reading if in one of the two points we have made a mistake (as we saw in the previous article in which the jsp page correctly read parameters but the servlet didn’t).
To do this we must use the setAttribute method, defined again in the ServletRequest interface implemented by the HttpServletRequest class representing, as we have seen, the request that reaches the servlet. Taking a look to the documentation we see that the setAttribute method is defined as follows:

void setAttribute(java.lang.String name, java.lang.Object o)

Parameters:

  • name: a string representing the name of the attribute to store
  • o: the object to save as attribute of the request

The documentation also adds the following information:

  • The attributes are related to the single request and they are available as long as the request is
  • The method is usually used in combination with a RequestDispatcher
  • The attribute name follows the same naming convention allowed for the definition of packages
  • If the object passed to the method is null then the attribute will not be inserted in the request

We can modify our servlet by inserting the setAttribute call before to forward the request to the JSP page:

request.setAttribute("user", u);	// we insert the User object in the request...
		
RequestDispatcher view = request.getRequestDispatcher("useradd.jsp");  // ... and we send it to the JSP
view.forward(request, response);

The following picture shows what our “AddUser” servlet looks like:
setAttribute - sending object from Servlet to JSP

If in our servlet we set the attribute in order to make it available to the JSP page, in the latter we must then read the value. To do so, rather intuitively, we must use the getAttribute method of the request, passing it the name of the parameter we want to retrieve. The getAttribute method returns an Object, so we must necessarily make an explicit cast of that object to the User type.
In order to use the User class we need to import it as follows:

<%@ page import="com.dede.app1st.model.User"%>

The code of our “useradd.jsp” JSP page then becomes the following:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"
    import="com.dede.app1st.model.User"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>1st Web App - New User Created</title>
</head>
<body>
	<h1>New User Created</h1>
	
	<p>
	<% User u = (User)request.getAttribute("user"); %>  // we make an explicit cast
	First Name: <% out.print(u.getFirstname()); %> <br/>
	Last Name:  <% out.print(u.getLastname()); %> <br/>
	Country:    <% out.print(u.getCountry()); %>
	</p>
</body>
</html>

Servlet JSP getAttribute

Now that we have seen how to improve the mechanism of communication between the servlet and the JSP page, we can go back to the enrichment of our application. The next step is to add a control to ensure uniqueness of the users and then verify that a user that is trying to register have not already done it previously and so it already appears in the database.

HOW TO AVOID DUPLICATION OF USERS
In order to implement a mechanism that avoid the insertion of duplicate users we must define the criteria according to which we believe that the user that is going to make the registration is already in our database. Typically this kind of check is made on fields like the username or email address, but given the simplicity of the user structure we are using, we suppose that there can not be two users in our system with the same name and surname. After all, beyond the fields we use, what interests us is to look at how to define a unique constraint on some fields of our structure and then of columns in a table of our database.
At the moment our application does not make any kind of control like this; we can try for example to make a new request to create a user by entering the same data that we had previously entered to create the first user
Web Application input form

Once the operation is complete let’s check in the “users” table of the database and, as shown in the figure below, we can see that a new record has been inserted with the same values of the columns “firstname”, “lastname” and “country” of the first record previously inserted.
Web Application database record duplicati

CREATE A UNIQUE CONSTRAINT IN THE DATABASE
To prevent this from occurring and to ensure that the pair of values “firstname” and “lastname” is unique for all rows of the “users” table we have to define a constraint of uniqueness. To do this go into pgAdmin3 console, select the “users” table of our “firstapp” database and right-click on the “Constraints” item, then select “New Object” and then again “New Unique Constraints”. The following image shows this operation:
Web Application database new constraint

At this point it opens a new window with the wizard for the constraint creation, where we start entering the constraint name and possibly a comment that provides a description of his purpose. We can call for example our constraint “UniqueName”, as shown in the picture:
PostgreSQL new unique constraint

At this point we must select which columns we want to include in the definition of the constraint so that they must then have, at least, one different value for each record in the table. To do that we move in the “Columns” tab of the create window and select in this case the columns “firstname” and “lastname”.
PostgreSQL create new unique constraint columns

We are now ready to end the creation of our constraint by pressing “OK”. But in doing so, we get the result shown in the following picture, where an alert informs us that there was an error in the creation of the constraint that we had configured, because in the table already exists a pair of values for columns “firstname” and “lastname” which is repeated. In the error message it is also reported what are these repeated values.
PostgreSQL create new unique constraint columns

This means that, before we can create constraint on our table, we have to remove duplicate values already present. So, we go on the “users” table, select the last record entered, click the right mouse button and select the “Delete” command as shown in the figure below.
PostgreSQL remove duplicate record

Now that we have eliminated the duplicate records, creating the unique constraint is successful and we see it appearing under the “Constraints” section in the “users” table in the pgAdmin3 console.
PostgreSQL unique constraint created

SPECIFY THE UNIQUE CONSTRAINT IN JPA/HIBERNATE
After defining the unique constraint on the database we have to provide the information of its existence to Hibernate and transfer this concept on our Entity class “User” that maps the table on which we have defined the constraint.
The Java Persistence API allows us to specify this information through an attribute of the “@Table” annotation, called “uniqueConstraints”, which is set by a further annotation called “@UniqueConstraint” that requires a mandatory element “columnNames” defined as a String array containing the list of the columns that compose the unique key.
We must therefore change the @Table annotation in the User class as follows:

@Table( name = "USERS",
	uniqueConstraints = {@UniqueConstraint(columnNames = {"firstname","lastname"})}
)

The following picture illustrates that change:
JPA UniqueConstraint annotation
The important thing to remember is that JPA annotations just seen do not define the unique constraint itself , but they only provide the information that this constraint is present. The constraint must always be defined in the database.

At this point we run a test, trying another time to create a user by entering once again the same information as for the record already present in the database.
Web Application input form

Whereas before we could easily insert into the database a record containing information equal to that of an existing user, now that we have defined a unique constraint on the pair of columns “firstname” and “lastname” we get a ConstraintViolationException:

Grave: Servlet.service() for servlet [com.dede.app1st.controller.AddUser] in context with path [/WebTest] threw exception
org.hibernate.exception.ConstraintViolationException: could not execute statement
. . .
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "UniqueName"
  Dettaglio: Key (firstname, lastname)=(Davis, Molinari) already exists.

As we can see the type of error is meaningful and it shows us that we are trying to insert a record that broke the unique constraint called “UniqueName”. Furthermore, we can see the detail of what are the columns that compose the unique key (“firstname” and “lastname”) and what are the values we’re trying to insert for which there is already a row in the database (“Davis” and “Molinari” ).
The following image depicts the result of the insert operation for the existing record:

Unique Constraint violated

In this way our application prevents to enter in the database the same user two time however, in such a case, it throws an exception. In the next article we will see how to handle this exception and to avoid that the error arises. Instead we’ll provide to the user a message about the problem that occurred with another appropriate JSP page.

You may also be interested in this tutorial: Create a modern web application with Spring Boot, MongoDB, Angular 4 and TypeScript and deploy it in cloud as Microsoft Azure Webapp

This entry was posted in $1$s. Bookmark the permalink.

One thought on “How to create a web application from scratch with Java, Eclipse, Tomcat, Hibernate and PostgreSQL – Part #5

  1. Pingback: How to create a web application from scratch with Java, Eclipse, Tomcat, Hibernate and PostgreSQL – Part #4 | Dede Blog

Leave a Reply

Your email address will not be published. Required fields are marked *