Ingesting data

In the coming sections, we'll focus on how we can send data to the servers that is complex and is constrained in its shape and type. The first step being how to deal with a request for content.

Extracting the data

Earlier we saw how to create a structure from the dictionary, which was created by us. However, in a web environment, such a dictionary will be coming from the client, for instance, the browser.

In this section, we'll see that Play! 2 comes with everything that we might need to map our external view back and forth to our server-side structure (until now User).

To illustrate the simplest case, we'll create an HTML form that will mimic the dictionary:

Extracting the data

This form was created directly from the previous template by changing its signature from a simple User to an Option[User]. This enables us to re-use the same template for two different cases:

  • To show the view when the optional user is present
  • To present the form otherwise

Note

An Option is a Scala structure that defines an absent or present data in a type-safe way. A given value will be of the type Some, whereas an absent one will be of the type None.

Reviewing the form, we can note a new URL (/data/post) that will handle our new request for a new action (post), which we'll cover in a moment. The following screenshot shows its route definition:

Extracting the data

So we have said that we want all URLs of the specified form to be routed to the post action in the Data controller.

Let's see what this new action does:

Extracting the data

First of all, we see that we have used a new method on the form, bindFromRequest, which is meant to retrieve the data needed by the form somewhere in the request.

Why somewhere? Actually, this method is able to look up data of several types and in several places. Depending on the content type, the HTTP method, and the encoding, this binding will look for data in:

  • The query string: This is our case, because we have sent a GET request.
  • The body: For POST/PUT methods. There are several options here because the content could be a map of URL parameters, a multipart, or JSON encoded.

In fact, the binding method will look everywhere to gather all the data and then it will retain the ones declared in the form definition to find which it's expecting.

After having found everything, it returns a Form instance filled with these values on which we may call get in order to retrieve the related domain object. But, we could also call the data method that would give us back the dictionary of values.

Having reached this point, we can now provide our brand new user to the data template rendered within an ok (status 200) response.

Note

See how we used Play!'s specific class, Scala, which contains a lot of methods to interact from Java to Scala. Here we used it to create Scala.Option by giving it the options user (results in Some(user)) or null (correctly cast to have None of the underlying type User).

Trying this in the browser, we'll get the following result:

Extracting the data

That was really cool! From browser to domain object without any manual actions needed. I know what you are thinking, the use case is so simple that it doesn't reflect reality. So let's now test it a bit more by adding something new—validation of a complex structure.

Enhancing your data

In the real world, data is more complex and is required to satisfy some constraints for applications to accept it. In this section, we'll see how to deal with complexity and the next section will cover the constraints.

As Play! 2 is made for realistic applications, it already contains everything we might need to handle complexity.

For now, a user is nothing more than a name; but a real user (as more data is attached), has an age, a gender, an address, some friends, and so on. In brief, he/she can be represented as follows:

Enhancing your data

This should look like stuff we have already seen (possibly thousands of times). A significant change worth noting, however, is the public accessors on the class fields. This is due to the fact that Play! will generate them for us at compile time, so that they will be available for any other reflection-based tool.

The interesting things are that we have added one external indirection (address) and two internal ones (friends and spouse). What would be really great is if we could bind everything from a single request! Ok, let's do some cool things now.

The really good thing at this stage, in Java, is that we don't have to touch anything in the server-side form definition, thankfully, due to the binder. Having said that, we can infer that the needed work will be on the client side only.

Earlier when creating our HTML form, we did it by hand mimicking the User structure and hardcoded the action's URL. That's not what we'd expect from a framework like Play! 2, and it's true because the framework brings a lot of helpers to generate client-side code based on server-side information. So, rather than adapting the existing HTML form to match the new User structure, we'll refactor it using Play! 2's features.

Enhancing your data

There are a lot of new concepts in this form. Conveniently, the interesting lines have been indexed using a comment and their review is as follows:

  1. Rather than using a user (even in an option to avoid NPE) directly, we're now using the server-side form itself.
  2. In the previous version, we were checking that the option wasn't None. Over here we can do the same on the value of the form—its value is actually None until some data is used to fill it in, bound with valid data in an action.
  3. In the case where the form is holding a value, we've access to the get method of it in order to get the user back.
  4. Also, this form is where we see the first usage of the helper package provided by Play! 2. This one is defining plenty of utility functions (templates in fact) that are able to generate HTML code. In this case, we used the form template that generates an HTML form tag. Passing it a route, it will be able to set the correct action and method attributes according to what is defined in the routes file.
  5. Our second usage of this package is the usage of a template that generates an HTML input tag of type text. To generate it, it requires a form's field, which is retrieved by using the given form instance, using it as a function with the field name (userForm("name")).

    Note

    The routes file is compiled in objects under the routes object. Actually, all controllers will be available in this object, but reversed so that we're able to recover the mapping routes for a given pair controller-action. So in the template that we just discussed, it provides the form helper with the URL and the HTTP method defined for the post action.

    The @* *@ notation is simply comments in the Scala template's syntax.

So far, so good; we have changed the signature of the template that required us to change our action a bit. But, we'll also take the opportunity to change the HTTP method of the post action to something more relevant for a modification of the server-side state: POST .

Note

Not only GET and POST HTTP methods are allowed, but also all HTTP-standardized methods such as PUT, DELETE, OPTIONS, and so on.

Enhancing your data

We can be satisfied now by how simple our actions are. The show method (renamed from test) is just asking the template to be rendered using the userForm instance, and the post one does the same but asks for a new instance of the form bound to the request. That's all! We can now start editing and showing our user as the output of our form. Let's try this:

Enhancing your data

So, we retrieved what we had done earlier, but User is now far more complex than a simple name. This means it is now time to update our form with all of the relevant information about the new fields.

Enhancing your data

Wow! A lot in a few minutes, isn't it?

In this new version of the template, we have defined almost a whole user; what hasn't been done yet are the links to other users. How did we achieve that? This was done thanks to the default helpers available in Play! 2.

Some save points have been set in the template, which means that it's time to review them one by one:

  1. The first thing we did is create the HTML input field for the user's age, which is an integer (Ok, could be of a short type). For this kind of data, HTML5 has defined a new type of input, the number one. There is no inputNumber template defined in Play! 2 (at the time of writing), however, it is very trivial to create our own using the generic input template.

    More than just using the template, we've had to create the HTML block by ourselves, with the help of the given data. At this stage, you might be wondering about the worth of this, but we'll cover that when validation occurs.

  2. Then we wanted to let the user define their gender. For that, a Boolean is used. So, we used the checkbox template to generate a checkbox.
  3. The easy part has been done. Now, there is the link to the address information, which is, itself, structured. We wrapped this part of the form in a dedicated fieldset tag.
  4. In this fieldset tag, we defined the input text for fullStreet and county. It was trivial, but what is very cool is how we retrieved a form field using its path to the information from the user. Indeed, we can navigate the object's graph in the forms simply by using the dot notation. The only thing to ensure in this case is that every intermediate object is at least initialized to dummies (otherwise an NPE will be thrown).

    As the labels are ugly by default (they equal the name of the field), we used an argument of the input to set a custom label to something more readable.

    Note

    The label is declared in the parameters list using a symbol that starts with an underscore character. So a symbol is, briefly, a name (without value), and its syntax is similar to val but starts with a quote.

  5. For the last bit of data, country, we wanted to present a list to the user. HTML has a specific form element for this case: select. This element has a name and contains a list of options defined by a value and a display.

Of course, Play! 2 enables us to define such HTML blocks really easily (which is a pain otherwise), all by passing a list of Tuple2 values where the first component is the value that will be sent with the form and the second component is the display one.

So now, what happens if we enter some data in the resulting form?

Enhancing your data

The first try was a real success, but what about the second one (on the right). A guy with no name, no age, and no home—the first piece of data is strange, the second one is frightening me, and the last one makes me sad. Let's try to take things one step further by adding validation.

Validating our data

What we're able to do now is create complex forms (both on the client and server sides) to represent our data, however, most of the time, they have to satisfy some constraints—business ones, for instance.

Java has a Java Specification Request (JSR) defined for exactly this situation, JSR 303, wherein how constraints can be added to Java models—using annotations—is specified.

So, Play! 2 takes advantages of this JSR and enables us to use it to validate our data, but it also defines custom validators that are missing in the specification.

What we'll find very convenient is that the validation information is available on the browser side as well, thanks to the form HTML helpers we saw earlier.

Considering our User and Address models, the following screenshot shows how we could ask Play! 2 to validate them:

Validating our data

Actually, we'll find everything we might need in the package play.api.validation, especially the static methods available in the Constraints class that defines the most common annotations. But, sometimes we might need ones from the JSR; for instance, in the User model we imported Valid from the javax.validation package. Also we can see that while defining the constraints, a new field, email, has appeared.

Browsing the code, we'll find almost all of the validation instructions that have been set to be trivial. Let's review them one by one:

  1. We start with the required name field, which states that the field won't be valid if a null value is given.
  2. Then moving to the new field, email, we can see that it is also required but that it is also constrained to be an Email annotation, which is simply asking for a validation against the classic e-mail pattern.
  3. For numbers, we very often need to assume that the value will always be contained within a predefined range. This constraint is rather simple to define using the Min and Max validation rules.
  4. The next annotation that we now meet is the Valid one. This one is related to Required but is for embedded structures. That is, if an external object has to be set and is also constrained by validation rules, we can ask the system to check its validity as part of the upper-level object validation process (it's a kind of a cascade on validation request).
  5. Moving to Address, we use the Pattern validation, which supersedes the Email validation rule, letting us define our own pattern. That's exactly what has been done for the street, which is supposed to be fully qualified by containing the street and the number.
  6. Nevertheless, it is not the only interesting thing there; we can see for the first time the message property in an annotation. This message is what will be returned if this particular validation fails.
  7. Now we can jump to the last one, validating the country information. We should remember that our form was showing an HTML select element with options having their values set to two chars (IDs). So these IDs will now be validated by the MaxLength constraint.

This last rule might not be enough though, because someone could send a custom HTTP request with a fake country ID. To validate that the value is one of the predefined options, we can define our own logic in a dedicated method—validate:

Validating our data

As shown in the previous screenshot, the validate method is checking our custom rule and will return null if it succeeds; an error message otherwise.

It seems that we've protected a lot of things on the server side now, but how are they presented (if they are) on the other side—in the HTML form?

Validating our data

Gosh! Without changing anything on the client side, the validation instructions have appeared on each field. Recalling what we wondered earlier, "What was the value of such helpers?" So, here we are; and it's not the end.

Note

You're right; the address' constraints aren't shown in the dedicated fieldset, nevertheless, this has been fixed in the 2.1 version of Play!.

On the right side (previous screenshot) is presented a slightly skinned version of our HTML form in order to highlight where to look.

Ok, but how is it supposed to work when incorrect data is sent to the server?

Validating our data

Impressive, isn't it? Without changing a single line of code in our templates, every error just shows up. The only thing that has been done is to add a CSS rule to display the error messages in red.

Oh yeah! The red div element is also a little addition. This addition takes the number of errors that are available in the form object directly, which is shown as follows:

Validating our data

Moreover, it's intuitive!

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

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