Skip to content

Binding Parameters to your Handler Method

Michael Delamere edited this page Jul 24, 2017 · 51 revisions

In the previous section we had a look at how we can map our handler to a request. Now we want to be able to pass parameters to the handler method. Almost any part of the request can be passed in to it. These include path parameters, query parameters, headers, cookies and session values. If these are not enough for you, you can also just add the raw request parameter map or the HttpServletRequest object itself to your method signature. geeMVC will automatically make them available for you.

The following parameters come out of the box, although it is easily possible to define your own parameter annotations:

Parameter Annotations
Parameter Annotation Description
@PathParam Makes a path parameter available to the handler method.
@Param Makes a query string parameter available to the handler method.
@Cookie Makes a cookie value available to the handler method.
@Session Makes a session attribute available to the handler method.
@Header Makes a header value available to the handler method.
@Context Makes a context object available to the handler method.
@PathParam Annotation

Sometimes paths themselves can contain useful information, like the id of an object that we want to retrieve. In the following example we have included the id 12345 in our path, which could be our productId. With the @PathParam we can now retrieve this id and make our service call to the backend to fetch the requested object.

import static com.geemvc.Results.*;

@Controller
@Request("/products")
public class ProductController {

    // Maps to /products/view/12345.
    // If the parameter name "Long id" is the same as "{id}" 
    // there is no need to specify a name in @PathParam.
    @Request("/view/{id}")
    public Result view(@PathParam Long id) {
        // Fetch the product from some service or repository.
        Product product = products.havingId(id);

        // Forward to the view page and make the product 
        // object available to the JSP or template.
        return view("product/view").bind("product", product);
    }

    // Maps to /products/another-view/12345.
    // If the parameter name "Long anotherId" does not match "{id}"
    // you must specify the name in your @PathParm annotation.
    @Request("/another-view/{id}")
    public Result anotherView(@PathParam("id") Long anotherId) {
        // Fetch the product from some service or repository.
        Product product = products.havingId(anotherId);

        return view("product/view").bind("product", product);
    }
}

Back to the top

@PathParam with Regular Expressions

When a static parameter mapping is not sufficient you can add more flexibility with regular expressions. Check the following example to see how. The parameter here is made up of two parts. The left part is the name of the parameter and on the right we have the actual regular expression.

import static com.geemvc.Results.*;

@Controller
@Request("/products")
public class ProductController {

    // Maps to /products/view/some-sef-url-12345.
    // The following regular expression extracts the id from the end of the URI,
    // which then gets passed to the method with the @PathParam annotation.
    @Request("/view/{id:^.+\\-[\\d]+$}")
    public Result view(@PathParam Long id) {
        // Fetch the product from some service or repository.
        Product product = products.havingId(id);

        // Forward to the view page and make the product 
        // object available to the JSP or template.
        return view("product/view").bind("product", product);
    }
}

Back to the top

@Param Annotation for Retrieving Query String Parameters

Quite often you will be dealing with query string parameters, e.g. /my-uri/?my-param=someValue&another-param=anotherValue. geeMVC also makes it very easy to retrieve these. Simply use @Param instead of @PathParam and specify the name of the parameter that you want.

import static com.geemvc.Results.*;

@Controller
@Request("/products")
public class ProductController {

    // Maps to /products/list?page=3&limit=25.
    // Retrieve both query string parameters by using the @Param annotation. 
    @Request("/list")
    public Result view(@Param Integer page, @Param Integer limit) {
        // Fetch the list of products from some service or repository.
        List<Product> products = products.all(page, limit);

        // Forward to the list page and make the product 
        // objects available to the JSP or template.
        return view("product/list").bind("products", products);
    }
}

Back to the top

@Cookie Annotation

Retrieving cookie values is just as trivial. All you need is the @Cookie annotation. Setting cookies is also very straightforward, but requires some extra code. First you will need to add the HttpServletResponse object to your method-signature, which geeMVC will then automatically inject for you. You can then use the HttpServletResponse object for setting your cookie.

import static com.geemvc.Results.*;

@Controller
@Request("/products")
public class ProductController {
    protected static final int DEFAULT_LIMIT = 25;
    protected static final String DEFAULT_SORT_BY = "price asc";

    // Maps to /products/update-limit-and-sort.
    // Updates the cookie values when the user changes either limit or sort value.
    @Request("update-limit-and-sort")
    public Result updateLimitAndSortBy(@Param Integer limit, @Param String sort, HttpServletResponse response) {
        // Update the "limit" cookie value.
        if (limit != null)
            response.addCookie(new javax.servlet.http.Cookie("limit", String.valueOf(limit)));

        // Update the "sort" cookie value.
        if (sort != null)
            response.addCookie(new javax.servlet.http.Cookie("sort", sort));

        // Fetch the list of products from some service or repository.
        List<Product> products = products.all(limit, sort);

        // Forward to the list page and make the product
        // objects available to the JSP or template.
        return view("product/list").bind("products", products);
    }

    // Maps to /products/list.
    // Uses the cookie limit and sort values if they exist,
    // otherwise falls back to default values.
    @Request("list")
    public Result list(@Cookie("limit") Integer limit, @Cookie("sort") String sortBy) {
        // Fetch the list of products from some service or repository.
        List<Product> products = products.all(limit == null ? DEFAULT_LIMIT : limit, sortBy == null ? DEFAULT_SORT_BY : sortBy);

        // Forward to the list page and make the product
        // objects available to the JSP or template.
        return view("product/list").bind("products", products);
    }
}

Back to the top

@Session Annotation

If you need to retrieve objects out of the current HTTP session, just do the same as above, but this time use the @Session annotation. In order to add objects to the session, you need to add the HttpSession object to your method signature and geeMVC will automatically inject it for you. Then set your values as shown in the example below:

import static com.geemvc.Results.*;

@Controller
@Request("/customers")
public class CustomerController {
    // Maps to /customers/view-account.
    // Checks if the customer object exists in session.
    @Request("view-account")
    public Object viewAccount(@Session("logged-in-customer") Customer customer) {
        // If customer is not logged in, redirect him to login-screen.
        if (customer == null) {
            return "redirect: /customers/login-form";
        } else {
            // Forward to the account page and make the customer
            // objects available to the JSP or template.
            return view("customer/account").bind("customer", customer); // /WEB-INF/jsp/pages/customer/account.jsp
        }
    }

    // Maps to /customers/process-login.
    // Errors and HttpSession objects are automatically injected by geeMVC.
    @Request("process-login")
    public Object processLogin(@Param("username") String username, @Param("password") String password, Errors errors, HttpSession session) {
        Customer customer = someCustomerService.login(username, password);

        if (customer != null) {
            session.setAttribute("customer", customer);

            // Redirect to the account page if login was successful.
            return redirect("/customers/view-account");
        } else {
            // Add message to errors object.
            errors.add("Login incorrect! Please try again.");

            // Forward back to the login-form.
            return "view: customers/login-form";
        }
    }

Back to the top

@Header Annotation

The @Header annotation allows you to pass header values to your handler method. See below for a simple example:

@Controller
public class HelloWorld {

    @Request("/hello/world")
    public void sayHello(@Header("Accept") String accept, @Header("Host") String host, @Header("Referer") String referer) {
        System.out.println("Hello world! You are visiting " + host + " and accepting the "
                + "content type " + accept + ". You have come from " + referer + "!");
    }

Back to the top

@Context Annotation

The @Context annotation allows you to pass context values, such as HttpServletRequest, HttpServletResponse etc., to your handler method. The following objects will be injected automatically when you use @Context, although geeMVC will also inject them without the annotation.

Context Object Description
javax.servlet.ServletRequest The current servlet request object.
javax.servlet.ServletResponse The current servlet response object.
javax.servlet.ServletContext The servlet context object.
javax.servlet.http.HttpSession The current HTTP session object.
javax.servlet.http.Cookie[] The cookie array of the current request.
java.util.Locale The locale of the current request.
java.util.Map<String, String[]> The raw parameter map from the current request.
com.geemvc.Bindings Object which contains typed parameter values converted by geeMVC.
com.geemvc.validation.Errors Object containing validation errors.
com.geemvc.i18n.notice.Notices Object containing notices for display in the view.
@Controller
public class HelloWorld {

    // The following parameters would also be injected without @Context.
    @Request("/hello/world")
    public String sayHello(@Param int temperature, @Context Bindings bindings, @Context Errors errors,
            @Context Notices notices, @Context HttpServletResponse response) {

        if (bindings.hasErrors()) {
            // Add another error if there is one.
            if (temperature > 39)
                errors.add("form.temperature", "Sorry, too hot!");

            // Forward back to JSP or template.
            return "view: some/form/page";
        } else {
            // Add notice and redirect to success page.
            notices.add("Well done, there are no errors!");

            return "view: some/success/page";
        }
    }
}

Back to the top


Learn how to bind bean objects in the next section.

Clone this wiki locally