Creating a forum

In this section, we'll refactor our existing application in order to enable it to act as a forum. And, chances are high that it won't be necessary to learn anything new; we'll just re-use the skills gathered so far; but we'll also use the parsing commodities that Play! 2 offers us.

Reorganizing and logging in

The very first thing we have to do is to enable a user to log in; this ability was already created in the Data controller. However, for that, we'll update our Application controller a bit, to create a new index action that will check whether a user is logged in or not.

Reorganizing and logging in

So, index is now the new entry point of the application and can be routed from / in the routes file. And, it's solely meant to check if a user has logged in or not. This check is based on the session content, as we simply check whether a user's e-mail is present in the session.

Note

We never see what a session can be in Play! 2, but we saw that Play! 2 is completely stateless. So, a session in Play! 2 is only an encrypted map of the value stored in the cookie. Thus it cannot be that big, and definitely cannot contain full data.

If the user is present, we redirect the request to the chatroom by calling redirect with the expected action. This will prevent the browser from posting the request again if the user reloads the page. This method is called POST-redirect-GET .

Otherwise, we respond with an Unauthorized HTTP response (401) that contains the HTML login page.

The two actions (shown in the next screenshot) are so simple that we won't cover them further, except for a single line: session().clear(). It is simply revoking the cookie's content, which will require the subsequent request to create a new one, which then doesn't contain the previously stored e-mail.

Reorganizing and logging in

And finally, enter, which shows how a request's body can easily be handled using the relevant method: asFormUrlEncoded. It should look like that shown in the following screenshot:

Reorganizing and logging in

Indeed, one would normally have to use a form to retrieve this information for us, which would do it for us (behind the scenes); but in this case we have only a single parameter to retrieve, so a form would be overkill.

So far, so good; we are now able to create a user, log in with it, and use a login page. To target having cleaner code, it would be worth splitting the Data controller code into several pieces (matter of a good separation of subject). Hence, the Users controller is created, in which will be placed the user-related actions taken out of Data.

Now, we'll move back to something we saw earlier but didn't cover—the routes.Chats.allChats() action call.

Chatting

In the previous section, we were introduced to the Chats controller and its allChats action. If the names are self-descriptive, the underlying code isn't that much.

First of all, we're now dealing with Chat instances that must be persisted somewhere in a database, along with their underlying items.

But we'll also prepare for the next section, which relates to multipart data (for instance, it's helpful for file upload). That's why we'll add a brand new type, Image, which is also linked to Chat.

Having said that, it would be worth checking our new chat implementation:

Chatting

Thanks to the previous chapter, there's nothing all that new here, except the Image type itself. Before we cover the Item and Image types, we'll first go to the Chats controller to see what's going on.

Chatting

Finally, we can see our allChats action; it's simply rendering all existing instances within a template. Even the rest of the controller is simple; everything is done in templates, which are left as exercises (we're so good at them now!).

However, there's still the loadChat action that contains something related to this chapter:

Long chatId = Long.parseLong(queryString.get("chatid")[0]);

This action handles requests asking to show a particular Chat instance, which is a resource and thus should be served using a GET request. This implies that the parameter value is stored in the query string (or in the URL itself) rather than in the request body.

Regarding query string access, it's more interesting to analyze the following line:

Map<String,String[]> queryString = request().queryString();

In fact, all actions contextually refer to a request object, which is accessible using the request() method. This request object declares a queryString() method that returns a map of string and an array of strings. What comes next is trivial; we just get chatid out of this map (ok... in a very unsafe way).

Until now, we have been able to log in and access the chatroom, where we can create or show chat instances. But we're still unable to reply to a chat. That's what will be tackled now.

For that, we need to create an action that will, based on a chat ID, post a new message linked to the logged in user, and then attach this message as an item of the underlying Chat instance.

For this, we must update the Item class with persistence information. Afterwards, we'll be able to update the Chats controller in order to create instances.

Chatting

Ok, it's like a beefed-up POJO; let's jump into the action that will create Item instances.

The workflow to post a message for a user starts by enabling him/her to participate in a chat. This is done by loading it (using the loadChat action) where the user will be able to post a new message (an overview of the UI will be presented at the end of this chapter for illustration only).

The following screenshot shows how it can be done:

Chatting

Observe how the user was recovered using the session.

Still, nothing cumbersome to review here, we've just re-used a lot of stuff we've already covered. The action receives a POST request in which information about the message is given, and then we can bind the request to itemForm and finally save to the database the item contained in the resulting form.

At most, we should notice that we're still free to encode the body as we want, and also that the chat ID is not a part of the form but a part of the action signature—that's because it is a part of the URL (routing).

We've almost finished our forum; the only thing needed is to enable users to post images.

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

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