mscharhag, Programming and Stuff;

A blog about programming and software development topics, mostly focused on Java technologies including Java EE, Spring and Grails.

Posts tagged with Java EE

  • Monday, 28 May, 2018

    Java EE MVC: Handling form validation

    In this post we will have a look on form validation in Java EE MVC.

    Java EE MVC integrates with the Java Bean Validation API (JSR 303) which makes adding validation constraints pretty easy.

    Validation using the JAX-RS way

    Assume we have a small html form that can be used to send contact messages. To represent the form data we create a small ContactMessage bean containing the form fields and validation constraints:

    public class ContactMessage {
    
        @FormParam("message")
        @NotBlank
        @Size(max = 1000)
        private String message;
    
        // getters / setters
    }
    

    In our MVC controller we use the @BeanParam annotation to convert the form data to a ContactMessage object:

    @Controller
    @Path("/")
    public class ContactController {
    
        @POST
        public String formSubmit(@Valid @BeanParam ContactMessage message) {
            ...
        }
    }
    

    (For more details about the @BeanParam annotation, have a look at the blog post Working with bean parameters)

    By adding the @Valid annotation to the ContactMessage parameter we enable validation. If a form is submitted and the validation of the ContactMessage object fails, a ConstraintViolationException will be thrown. The controller method will not be called in this case. Instead, the exception can be handled using a generic JAX-RS ExceptionMapper like shown in another post: Global Exception handling in Java EE MVC.

    This approach is typically fine for standard JAX-RS REST endpoints. Here we often want to return a generic HTTP 400 (Bad request) status code if invalid data has been passed to the server.

    In an MVC environment we can use this behaviour to render a standard error page to the user, whenever invalid data has been passed. However, this is often not flexible enough. Often we want to return a more specific page that shows an error message to the user.

    Validation using @MvcBinding and BindingResult

    Java EE MVC provides a @MvcBinding annotation that enables an alternative exception handling mechanism. @MvcBinding can be placed on fields and method parameters together with JAX-RS binding annotations (like @FormParam):

    public class ContactMessage {
    
        @MvcBinding
        @FormParam("message")
        @NotBlank
        @Size(max = 1000)
        private String message;
    
        // getters / setters
    }
    


    This tells Java EE MVC to call the controller method instead of the generic exception handler if binding of the annotated field fails. To access binding information, we can inject a BindingResult object into our controller class:

    @Controller
    @Path("/")
    public class ContactController {
    
        @Inject
        private Models models;
    
        @Inject
        private BindingResult bindingResult;
    
        @POST
        public String formSubmit(@Valid @BeanParam ContactMessage message) {
            if (bindingResult.isFailed()) {
                models.put("bindingResult", bindingResult);
                return "/WEB-INF/jsp/contact.jsp";
            }
            return "/WEB-INF/jsp/success.jsp";
        }
    }
    

    As the name suggests, we can use the injected BindingResult object to access binding information within a controller method. In this example we simply check if there was a binding problem by calling isFailed(). By adding the bindingResult to the model, we can access it later in the view to show an error message to the user.

    A simple JSP view that displays all validation errors below the submit button looks like this:

    <form action="${mvc.contextPath}/contact" method="post">
        <label>Message:</label>
        <textarea name="message"></textarea>
        <br/>
    
        <input type="submit"/>
    
        <c:if test="${bindingResult.isFailed()}">
            <p>Form validation failed. Reasons:</p>
            <ul>
                <c:forEach items="${bindingResult.allValidationErrors}" var="validationError">
                    <li>
                        <c:out value="${validationError.paramName}: ${validationError.message}"/>
                    </li>
                </c:forEach>
            </ul>
        </c:if>
    </form>
    

    Conclusion

    Form validation is pretty easy with Java EE MVC. Validation constraints can be added to beans using JSR 303 Bean validation annotations. @MvcBinding allows us to handle validation errors within controller methods instead of using generic ExceptionMappers. BindingResult gives us access to validation information.

    As always you can find the example code on GitHub.

  • Wednesday, 27 April, 2016

    Java EE 8 MVC: Global exception handling

    In the previous previous posts we learned about various ways to access request information (e.g. query or path parameters) in Java EE MVC. This post shows how to apply global exception handling to an MVC application.

    Assume we have a controller method that might throw an IllegalArgumentException:

    @Controller
    @Path("illegal-argument")
    public class ExceptionController {
    
      @GET
      public String doWork() {
        // code that might throw an IllegalArgumentException
      }
    
    }
    

    We could now add a try/catch block to doWork() and wrap the piece of code that might throw the exception. However, this approach becomes tedious if it needs to be applied to multiple methods.

    In such a case we can register a global exception mapper. To do this, we habe to create a class that implements the generic ExceptionMapper interface.

    A simple ExceptionMapper for IllegalArgumentExceptions looks like this:

    @Provider
    public class IllegalArgumentExceptionMapper implements ExceptionMapper<IllegalArgumentException> {
    
      @Inject
      private Models models;
    
      @Override
      public Response toResponse(IllegalArgumentException exception) {
        models.put("message", exception.getMessage());
    
        return Response.status(Response.Status.BAD_REQUEST)
            .entity("/WEB-INF/jsp/error.jsp")
            .build();
      }
    }
    

    Now, whenever an IllegalArgumentException is thrown from controller methods, IllegalArgumentExceptionMapper will be used to convert the exception to an appropriate response. Here a simple error view (error.jsp) is rendered.

    If you want a generic ExceptionMapper that handles all types of exceptions, you simply have to implement ExceptionMapper<Exception>. If you have multiple ExceptionMapper implementations that are suitable to handle a thrown exception, the most specific ExceptionMapper is used.

    Quick Summary

    Adding global exception handling to an Java EE MVC application is quite simple. We only have to create a class that implements the ExceptionMapper interface with the exception type that should be handled.

    The full example code can be found on GitHub.

  • Tuesday, 15 March, 2016

    Java EE 8 MVC: Working with bean parameters

    In the last posts we saw how to access query, path and form parameters in MVC Controllers. This post shows how multiple parameters can be mapped to an object using the @BeanParam annotation.

    Let's reuse the simple HTML form from the post about form parameters:

    <form action="submit" method="post">
      <label>ID:</label>
      <input type="text" name="id" />
    
      <label>Name:</label>
      <input type="text" name="name" />
    
      <label>Role:</label>
      <select name="role">
    	<option value="admin">Admin</option>
    	<option value="reporter">Reporter</option>
    	<option value="accountant">Accountant</option>
      </select>
    
      <input type="submit"/>
    </form>

    This defines a simple form containing two text input fields and a select menu with three options.

    In the previous post about form parameters, we learned that we can access these parameters by annotating controller parameters with @FormParam.

    However, this approach is cumbersome if the form has more than a few parameters. In these situations we typically want to map form parameters to a separate object. @BeanParams helps us with doing exactly this.

    With @BeanParam we can write:

    @POST
    @Path("submit")
    @Controller
    public String submit(@BeanParam User user) {
      // use user ..
    }

    The User class looks like this:

    public class User {
    
      @FormParam("id")
      private long id;
    
      @FormParam("name")
      private String name;
    
      @FormParam("role")
      private Role role;
     
      // getters and setters
    }


    When the controller method is called a new instance of User will automatically be created. The fields of the created object will be filled with the passed form parameters.

    @BeanParam and other parameter annotations

    Classes used with @BeanParam are not limited to form parameters. All parameter annotations shown in previous blog posts (@QueryParam, @PathParam, etc.) can be used inside bean parameters.

    For example:

    @GET
    @Path("/date/{year}/{month}")
    public String get(@BeanParam RequestData data) {
      ...
    }
    
    public class RequestData {
    
      @PathParam("year")
      private int year;
    
      @PathParam("month")
      private int month;
    
      @QueryParam("name")
      private String name;
    
      // getters and setters
    }
    

    If we now send a HTTP GET request to

    /date/2016/02?name=john

    the values 2016, 2 and john will be injected to the fields year, month and name of RequestData.

    Quick Summary

    With @BeanParam you can inject request parameters into beans. This is especially useful if you have more than a few parameters. Inside bean parameters all other parameter annotations can be used.

    You can find the example source code on GitHub.

  • Monday, 22 February, 2016

    Java EE 8 MVC: Working with form parameters

    In the previous two posts we saw how to work with query and path parameters in the upcoming Java EE MVC framework. This post focuses on form parameters.

    When you submit a web form using a post request, the form values are send as part of the request body. The media type (or content type) defines the format that is used to store the values inside the request body. Web forms usually use the media type application/x-www-form-urlencoded. Parameters that are send using this media type can be accessed using the @FormParam annotation.

    Using form parameters

    Assume we have the following simple HTML form, containing two text input fields and a select menu:

    <form action="submit" method="post">
      <label>ID:</label>
      <input type="text" name="id" />
      
      <label>Name:</label>
      <input type="text" name="name" />
      
      <label>Role:</label>
      <select name="role">
        <option value="admin">Admin</option>
        <option value="reporter">Reporter</option>
        <option value="accountant">Accountant</option>
      </select>
      
      <input type="submit" />
    </form>
    

    To process the form values we can use the following controller method:

    public enum Role {
      admin, reporter, accountant
    }
    
    @Controller
    @Path("form-params")
    public class FormParamsController {
    
      @POST
      @Path("submit")
      public String submitParams(
          @FormParam("id") long id,
          @FormParam("name") String name,
          @FormParam("role") Role role) {
    
        ...
      }
    }
    

    With @FormParam form parameters can automatically be mapped to method arguments. Form parameters use the same type conversion rules as query or path parameters (described here). This makes it easy to convert form parameters to primitives, enums or objects.

    Using @FormParam on fields and methods

    Like other parameter annotations @FormParam can be used to annotate fields and methods.

    For example:

    @Controller
    @Path("form-params-fields")
    public class FormParamsFieldController {
    
      @FormParam("id")
      private long id;
    
      @FormParam("role")
      private Role role;
    
      private String name;
    
      @FormParam("name")
      public void setNameField(String name) {
        this.name = name;
      }
    
      @POST
      public String submitParams() {
         // use id, role, name
      }
    }
    

    In this example the submitted form parameters are mapped to fields (id, role) and a setter (setNameField()). Inside submitParams() we can then simply access the fields to obtain the form parameters.

    Quick Summary

    Parameters submitted via HTML forms can be obtained with @FormParam. Like @QueryParam and @PathParam it is possible to annotate fields, methods and method parameters with @FormParam.

    You can find the source code for all examples on GitHub.

  • Sunday, 31 January, 2016

    Java EE 8 MVC: Working with Path Parameters

    In the previous post we saw how to work with query parameters in Java EE MVC. This post continues with a very similar topic: path parameters.

    Path parameters are a dynamic part of the request path and can be specified with the @Path annotation.

    For example:

    @Controller
    @Path("path-params")
    public class PathParamsController {
    
      @GET
      @Path("/date/{year}/{month}")
      public String pathParamDate(@PathParam("year") int year, @PathParam("month") int month) {
        ...
      }
    }
    

    Paths parameter are surrounded with curly brackets inside the @Path annotation. In this example two path parameters are defined: year and month.

    With @PathParam path parameters can be mapped to method parameters.

    We can call this method by sending a request to

    /path-params/date/2016/01
    

    In this case 2016 and 1 will be passed as year and month arguments.

    Type conversion

    Path parameters use the same type conversion rules as query parameters (explained in the previous blog post).

    For example, we can convert a path parameter to an enum value like this:

    public enum Role {
      admin, reporter, accountant
    }
    
    @Controller
    @Path("path-params")
    public class PathParamsController {
    
      @GET
      @Path("/roles/{role}")
      public String pathParamUsers(@PathParam("role") Role role) {
        ...
      }
    }
    

    If we now send a request to

    /path-params/roles/admin
    

    the string admin gets converted to the corresponding enum constant.

    Using @PathParam on fields and methods

    Like @QueryParam the usage of @PathParam is not limited to method parameters. It is also possible to annotate fields or setters with @PathParam.

    For example:

    @Controller
    @Path("path-params")
    public class PathParamsController {
    
      @PathParam("category")
      private String category;
    
      @GET
      @Path("/categories/{category}")
      public String findByCategory() {
        // work with category
      }
    }

    Using Path Parameters with Patterns

    It is possible to define a more specific pattern for a path variable. Therefore, a regular expression can be added after the name of the path variable.

    For example:

    @Controller
    @Path("path-params")
    public class PathParamsController {
    
      @GET
      @Path("/users/{id : \\d+}")
      public String findUserById(@PathParam("id") long id) {
        ...
      }
    
      @GET
      @Path("/users/{name : [a-zA-Z]+}")
      public String findUserByName(@PathParam("name") String name) {
        ...
      }  
    }
    

    Here we define two controller methods that listen on /users/{variable}:

    • findUserById() is only called if a numeric id is part of the request path
    • findUserByName() is used if the path parameter matches the regular expression [a-zA-Z]+.

    So if we send a request to

    /path-params/users/123
    

    findUserById() will be called and 123 is passed as id.

    Sending a request to

    /path-params/users/john
    

    calls findUserByName() and passes john as name.

    Quick Summary

    @PathParam can be used to extract path parameters defined with @Path. Like @QueryParam, @PathParam can be used on method arguments, instance fields and methods.

    When defining path parameters with @Path, a regular expression can be used to define a specific path pattern.

    You can find the source code for all shown examples on GitHub.

  • Thursday, 14 January, 2016

    Java EE 8 MVC: Working with query parameters

    In the previous post about the new Java EE MVC Framework we had a detailed look on Controllers. In this and the following posts we will see how to access various types of request data in MVC Controllers.

    Java EE MVC makes heavy use of JAX-RS and most of the things we will see in this and the next posts are JAX-RS features. So, if you are familiar with JAX-RS you probably will not learn much new in this post.

    Query parameters

    This post focuses on query parameters. If you read my Java EE MVC Getting started post you might already know the @QueryParam annotation. The most common use case of  @QueryParam is to map a query parameter to a controller method parameter.

    For example:

    @Controller
    @Path("query-params")
    public class QueryParamsController {
    
      @GET
      public String queryParams(@QueryParam("name") String name) {
        ...
      }
    }
    

    If we now send a HTTP GET request to

    /query-params?name=john
    

    the string "john" will be passed as name parameter to the method queryParams().

    Type conversion

    With @QueryParam query parameters can automatically be converted to various types.

    For example:

    public enum Role {
      admin, reporter, accountant
    }
    
    @Controller
    @Path("query-params")
    public class QueryParamsController {
    
      @GET
      public String queryParams(
          @QueryParam("id") long id,
          @QueryParam("name") String name,
          @QueryParam("role") Role role) {
    
        ...
      }
    }
    

    We can now send a request like this:

    /query-params?id=42&name=john&role=admin
    

    A query parameter can automatically converted to a type, if the target type matches one of the following rules:

    • It is a primitive type
    • The type has a constructor that accepts a single String argument
    • The type has a static factory method named valueOf() or fromString() with a single String argument
    • The type is List<T>, Set<T>; or SortedSet<T> where T matches one of the previous rules

    In the previous example, the query parameter id is automatically converted to long. If the id parameter is missing or a conversion to long is not possible, an exception will be thrown. It is also possible to use Long instead of long. In this case, we get null passed to the controller method if the id parameter is missing.

    Enums have a valueOf() method by default. So, the query parameter role can automatically be converted to the corresponding enum value.

    Using @QueryParam on fields and methods

    @QueryParam is not limited to method parameters. It is also possible to map query parameters to fields or methods, like the following example shows:

    @Controller
    @Path("query-params-fields")
    public class QueryParamsFieldController {
    
      @QueryParam("id")
      private Long id;
    
      @QueryParam("role")
      private Role role;
    
      private String name;
    
      @QueryParam("name")
      public void setName(String name) {
        this.name = name;
      }
      
      @GET
      public String queryParams() {
        // use id, role and name
      }
    }
    

    If we now send a HTTP GET request to

    /query-params-fields?name=john&id=42&role=reporter
    

    the parameters are set to the fields id, role and name (via setName()) before queryParams() is called.

    Do not forget that a new instance of the class is created for every request, so it is safe to have fields that contain request information.

    Quick Summary

    The @QueryParam annotation can be used to obtain query parameters. @QueryParam can be used on fields, methods and method parameters. Query parameters can be automatically converted to various types, as long as the target type is a primitive type, contains a String constructor or contains valueOf() or fromString() factory methods.

    You can find the source code for all the shown examples on GitHub.

    In the next post we will see how to work with path parameters.