Understanding request parameters

Matrix variables and path variables are a great way to bind variables in the URL request path. However, there is one more way to bind variables in the HTTP request, not only as a part of the URL but also in the body of the HTTP web request; these are the so-called HTTP parameters. You might have heard about GET or POST parameters; GET parameters have been used for years as a standard way to bind variables in URLs, and POST is used to bind variables in the body of an HTTP request. You will learn about POST parameters in the next chapter during form submission.

Okay, now let's see how to read GET request parameters in the Spring MVC style. To demonstrate the usage of a request parameter, let's add a product details page to our application.

Time for action - adding a product detail page

So far in our product listing page, we have only shown product information such as the product's name, description, price, and available units in stock. But we haven't shown information such as the manufacturer, category, product ID, and more. Let's add a product detail page to show them:

  1. Open the ProductRepository interface from the com.packt.webstore.domain.repository package in the src/main/java source folder and add one more method declaration on it as follows:
          Product getProductById(String productID); 
    
  2. Open the InMemoryProductRepository implementation class and add an implementation for the previously declared method as follows:
          @Override 
          public Product getProductById(String productID) { 
            String SQL = "SELECT * FROM PRODUCTS WHERE ID = :id"; 
            Map<String, Object> params = new HashMap<String, Object>(); 
            params.put("id", productID); 
     
             return jdbcTemplate.queryForObject(SQL, params, new             ProductMapper()); 
          } 
    
  3. Open the ProductService interface and add one more method declaration to it as follows:
          Product getProductById(String productID); 
    
  4. Open the ProductServiceImpl service implementation class and add the following method implementation for getProductById:
          @Override 
          public Product getProductById(String productID) { 
             return productRepository.getProductById(productID); 
          } 
    
  5. Open our ProductController class and add one more request mapping method as follows:
          @RequestMapping("/product") 
          public String getProductById(@RequestParam("id") String 
          productId, Model model) { 
             model.addAttribute("product",       productService.getProductById(productId)); 
             return "product"; 
          } 
    
  6. And finally add one more JSP View file called product.jsp under the src/main/webapp/WEB-INF/views/ directory, add the following code snippets into it, and save it:
          <%@ taglib prefix="c" 
          uri="http://java.sun.com/jsp/jstl/core"%> 
     
          <html> 
          <head> 
          <meta http-equiv="Content-Type" content="text/html; 
          charset=ISO-8859-1"> 
          <link rel="stylesheet" 
     
           href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/
           bootstrap.min.css"> 
          <title>Products</title> 
          </head> 
          <body> 
             <section> 
                <div class="jumbotron"> 
                   <div class="container"> 
                      <h1>Products</h1> 
                   </div> 
                </div> 
             </section> 
             <section class="container"> 
                <div class="row"> 
                   <div class="col-md-5"> 
                      <h3>${product.name}</h3> 
                      <p>${product.description}</p> 
                      <p> 
                       <strong>Item Code : </strong><span 
                       class="label label warning">${product.productId}
          </span> 
                      </p> 
                      <p> 
                         <strong>manufacturer</strong> :       ${product.manufacturer} 
                      </p> 
                      <p> 
                         <strong>category</strong> : 
                         ${product.category} 
                      </p> 
                      <p> 
                         <strong>Availble units in stock </strong> :       ${product.unitsInStock} 
                      </p> 
                      <h4>${product.unitPrice} USD</h4> 
                      <p> 
                   <a href="#" class="btn btn-warning btn-large"> 
                   <span class="glyphicon-shopping-cart glyphicon">          </span> Order Now 
                         </a> 
                      </p> 
                   </div> 
                </div> 
             </section> 
          </body> 
          </html> 
    
  7. Now run our application and enter the following URL: http://localhost:8080/webstore/market/product?id=P1234. You will be able to see the product detail page as shown in the following screenshot:
    Time for action - adding a product detail page

    Using request parameters to show the product detail page

What just happened?

In steps 1 and 2, we just created a repository method declaration/implementation to get products for the given product ID (getProductById). Similarly in steps 3 and 4, we created a corresponding Service layer method declaration and implementation to access the getProductById method. What we did in step 5 is very similar to what we did in the getProductsByCategory method of ProductController. We just added a product object to the model that is returned by the service object:

model.addAttribute("product", productService.getProductById(productId)); 

But here, the important question is, who is providing the value for the productId parameter? The answer is simple, as you guessed; since we annotated the parameter productId with @RequestParam("id") annotation (org.springframework.web.bind.annotation.RequestParam), Spring MVC will try to read a GET request parameter with the name id from the URL and will assign that to the getProductById method's parameter productId.

The @RequestParam annotation also follows the same convention as other binding annotations; that is, if the name of the GET request parameter and the name of the variable it is annotating are the same, then there is no need to specify the value attribute in the @RequestParam annotation.

And finally in step 6, we added one more View file called product.jsp, because we want a detailed view of the product where we can show all the information about the product. Nothing fancy in this product.jsp file; as usual we are getting the value from the model and showing it within HTML tags using the usual JSTL expression notation ${}:

<h3>${product.name}</h3> 
   <p>${product.description}</p> 
... ... 

Okay, you saw how to retrieve a GET request parameter from an URL, but how do you pass more than one GET request parameter in the URL? The answer is simple: the standard HTTP protocol defines a way for it; we simply need to delimit each parameter value pair with an & symbol; for example, if you want to pass category and price as GET request parameters in a URL, you have to form the URL as follows:

http://localhost:8080/webstore/product?category=laptop&price=700

Similarly, to map this URL in a request mapping method, your request mapping method should have at least two parameters with the @RequestParam annotation annotated:

public String getProducts(@RequestParam String category, @RequestParam String price) { 

Pop quiz - the request parameter

For the following request mapping method signature, which is the appropriate request URL?

@RequestMapping(value = "/products", method = RequestMethod.GET) 
public String productDetails(@RequestParam String rate, Model model) 
  1. http://localhost:8080/webstore/products/rate=400
  2. http://localhost:8080/webstore/products?rate=400
  3. http://localhost:8080/webstore/products?rate/400
  4. http://localhost:8080/webstore/products/rate=400

Time for action - implementing a master detail View

A master detail View is nothing but a display of very important information in a master page; once we select an item in the master View, a detailed page of the selected item will be shown in the detailed View page. Let's build a master detail View for our product listing page, so that, when we click on any product, we can see the detailed View of that product.

We have already implemented the product listing page (http://localhost:8080/webstore/market/products) and product detail page (http://localhost:8080/webstore/market/product?id=P1234), so the only thing we need to do is connect those two Views to make it a master detail View. Let's see how to do that:

  1. Open products.jsp. You can find products.jsp under src/main/webapp/WEB-INF/views/. Add the following spring tag lib reference on top of the file:
          <%@ taglib prefix="spring"       
          uri="http://www.springframework.org/tags" %> 
    
  2. Add the following lines after the Available units in stock paragraph tag in products.jsp:
          <p> 
          <a href=" <spring:url value="/market/product?      
          id=${product.productId}" /> " class="btn btn-primary"> 
          <span class="glyphicon-info-sign glyphicon"/></span> Details 
          </a> 
          </p> 
    
  3. Now open product.jsp. You can find product.jsp under src/main/webapp/WEB-INF/views/. Add the following spring tag lib reference on top of the file:
          <%@ taglib prefix="spring"       
          uri="http://www.springframework.org/tags" %> 
    
  4. And, add the following lines just before the Order Now link in product.jsp:
          <a href="<spring:url value="/market/products" />" class="btn 
          btn-default"> 
             <span class="glyphicon-hand-left glyphicon"></span> back 
          </a> 
    
  5. Now run our application and enter the following URL http://localhost:8080/webstore/market/products. You will be able to see the product list page, and every product will have a Details button as shown in the following screenshot:
    Time for action - implementing a master detail View

    Master View of product listings

  6. Now click on the any product's Details button and you will be able to see the detailed view with the back button link to the product listing page.

What just happened?

What we did is simple; in step 2 we just added a hyperlink using the following tag in products.jsp:

<a href=" <spring:url value="/market/product?id=${product.productId}" /> " htmlEscape="true" />" class="btn btn-primary"> 
   <span class="glyphicon-info-sign glyphicon"/></span> Details 
</a> 

Notice the href attribute of a <a> tag, which has a <spring:url> tag as its value:

<spring:url value="/market/product?id=${product.productId}" /> 

This <spring:url> tag is used to construct a valid Spring URL. We need this <spring:url> to be used in step 2; that's why we added reference to the Spring tag library in step 1. Observe the value attribute of the <spring:url> tag, and you can see that, for the id URL parameter, we assigned the expression ${product.productId}. So during the rendering of this link, Spring MVC will assign the corresponding product ID in that expression.

For example, while rendering the link for the first product, Spring MVC will assign the value P1234 for the product ID. So the final URL value with <spring:url> in it will become /market/product?id=P1234, which is nothing but the request mapping path for the product's details page. So when you click this link, you will land on the details page for that particular product.

Similarly, we need a link back to the product listing page from product detail page; that's why we added another link in the product.jsp tag as follows in step 4:

<a href="<spring:url value="/market/products" />" class="btn btn-default"> 
   <span class="glyphicon-hand-left glyphicon"></span> back 
</a> 

Note the <span> tag is just to style the button with an icon, so you do not need to pay attention to it too much; the only interesting thing for us is the href attribute of the <a> tag, which has the <spring:url> tag with the value attribute /market/products in it.

Have a go hero - adding multiple filters to list products

It is good that you learned various techniques to bind parameters with URLs such as using path variables, matrix variables, and GET parameters. We saw how to get the products of a particular category using path variables, how to get products within a particular brand and category using the matrix variable, and finally how to get a particular product by the product ID using a request parameter.

Now imagine you want to apply multiple criteria to view a desired product; for example, what if you want to view a product that falls under the Tablet category, and within the price range of $200 to $400, and from the manufacturer Google?

To retrieve a product that can satisfy all this criteria, we can form a URL something like this:

http://localhost:8080/webstore/products/Tablet/price;low=200;high=400?brand="Google"

Why don't you write a corresponding controller method to serve this request URL? Here are some hints to accomplish this requirement:

  • Create one more request mapping method called filterProducts in the productController class to map the following URL:

    http://localhost:8080/webstore/products/Tablet/price;low=200;high=400?brand="Google"

    Remember this URL contains matrix variables low and high to represent the price range, a GET parameter called brand to identify the manufacturer, and finally a URI template path variable called Tablet to represent the category.

  • You can use the same View file products.jsp to list the filtered products.

Good luck!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.4.44