Developing Juzu portlets – Step 4: adding Likes and Comments for Secret

04-Juzu-tutorial-series

Previous steps:
Learn how to develop great Juzu portlets for eXo Platform!
Step 2: viewing and posting secrets
Step 3: Building a sexy secret wall

In the previous blog post, we implemented the UI of our JuZcret application. We are now able to look at Secret on the secret wall and share a new secret via the “add secret” form. But what would a social feature be without any user interaction? Nothing…

That’s why, during this step, we’ll add two very original social features to our JuZcret application: the “comment” feature and the “like” feature. Crazy! 😉

By implementing these new features we will learn, among other things, how to use Ajax with Juzu, interact with Portlet Container, and add an EDIT mode to our Portlet.

We are assuming that you have already implemented step 3. If not, you can still download the source code resulting from step 3 on Github in order to start this step.

Let’s start by improving the application models a little bit.

Models

Here we don’t need to use Juzu, we will just improve our current model. Let’s add the top of the tree, Model. This class contains common attributes for Secret and Comment:

01-Model

In the org.juzu.tutorial.models package, create a Model class as shown below:

Then add a Comment class:

We also need to improve Secret:

  • Make Secret extend the Model class to inherit the parent attributes.
  • A Secret object will contain several Comment relationships, and several Like relationships (consisting of a simple list of users):

That’s all we have to do! Our model is ready for the comment and like features. Now we need to improve the Secret service by providing an API to make it possible to add comments and like secrets.

Improve Secret Service

Our Secret service needs two more methods to manage the new functionalities: one to add a comment to Secret (the add Comment method) and another to like a secret (the add Like method).

Note: As in step 2, our data is still saved in memory for now.

First, declare these two methods in the Secret service interface:

Then implement these 2 methods in the SecretServiceMemImpl and update the addSecret function:

Now we are done with the service layer!

This two methods are pretty simple and self-explanatory, so we don’t have to spend much time on them.

Note: In case you are in some doubt, I remind you that each step is available on a dedicated branch. To download the result of step 4 on Github, click here.

Now it’s time to go back to Juzu and improve the presentation layer.

Present like and comment

The comment and like actions will be managed using Ajax via the @Ajax Juzu annotation from the Juzu Ajax plugin. The Ajax plugin, like the Binding plugin, is already included in Juzu’s core, so there is no need to add new dependencies in our pom.

It’s important to know that the Juzu-Ajax plugin depends on jQuery. So it’s mandatory to declare jQuery, and we must do so in the previous step if we want to use this plugin.

Then you are ready to use @Ajax in our controller. So let’s add two new controller methods in JuZcretApplication.java:

The @Ajax annotation comes from the Juzu-Ajax plugin; it provides us with a convenient Ajax calling method: jzLoad, jzAjax. We’ll use this later in secret.js.

@Resource is a new type of Controller. Resource controllers operate pretty much the way a view controller does, except that they must produce the entire response sent to the client. That is a perfect method for implementing an Ajax request.

@Mapped allows us to map the request parameters to Bean types. Juzu automatically does the conversion between the primary types and the request parameters, but for a Bean, we need to declare the parameters with @Mapped. Consequently, the parameters of the “add secret” form will be automatically mapped to the attributes of the @Mapped Bean.

Juzu also automatically injects some contextual objects that you can use:

  • SecurityContext (provides security info, such as the current logged in user)
  • HttpContext
  • RequestContext
  • ApplicationContext
  • UserContext
  • ClientContext

You just need to declare the contextual objects in the method sign, as we do above for SecurityContext, and Juzu will inject them automatically at runtime.

You may have noticed that we sent a Json data response to our client by declaring the MimeType as text/json. Now we need to handle this response on the client side.

Template

We need to add two new buttons to like a secret and comment a secret in the secretWall.gtmpl. Then, for the Comment feature, we also need to display a popover to show the list of current comments and add a new comment.

Replace the current content of <ul class=”secret-wall-list clearfix”> as follows:

After that we need to improve our juzcret.less file to manage the new added class. Update the existing less file with these:

Note: […] means sections already added in step 3. If you feel a little bit lost, look for the juzcret.less file directly on the github project.

Now we have two buttons for the comment and like features and a popover to display the list of comments.

Now that we have finished the UI part, we need to add some js handlers to manage these two features using Ajax.

Javascript Handler

Update the secret.js file by adding the snippet in charge of the like feature:

This snippet registers an event on our Like button. The interesting line to notice here is

The jzAjax and jzLoad functions are jQuery plugins provided by the Juzu Ajax plugin. They replace the standard Ajax and Load jQuery functions. They accept the same arguments but the URL is replaced by the controller method.

All we need to do is provide the controller method, like JuZcretApplication.addLike(), and Juzu takes care to find the expected URL, and performs the Ajax request (using jQuery).

Similarly, we also have another three JS listeners for the comment feature. Add them just after the snippet which we just added above:

One major difference in this second handler is that we handle error response. Why? To prevent a user from submitting an empty comment.

This is why our Juzu controller should be aware of invalid data that a user submitted. Let’s move to the data validation and error handling provided by Juzu.

Adding validation

Juzu provides controller handler parameter validation via the Bean Validation framework. To use it, we need to add the juzu-validation plugin in our pom.xml:

And now, all we need to do is add an annotation to the model attributes. Update the Comment class as shown below:

Thanks to the @Pattern and @NotNull annotations, the validation framework will validate the parameter and throw a validation error if needed.

We need to also declare our intention to perform this validation in the controller. In our case, we want to validate any new comment coming from a user. This process is managed by the addComment Resource in JuZcretApplication, where we need to add the @Valid annotation to the Comment parameter:

Now if a user tries to enter an invalid comment, the validation framework will throw an error. Our job is not totally finished…We also need to properly cache this error.

Juzu provides two solutions for handling errors:

  • Use the request lifecycle.
  • Use the error handler.

In our case, we will use the request lifecycle that allows us to handle the error in the controller.

What we need is to analyze the Response and check to see if the type is a Validation Error. If it is, we simply get the error message and update the response to send it properly to the client.

To do this we need our controller, JuZcretApplication, to implement the interface RequestLifeCycle and override the endRequest method:

On the client side, we have already implemented our JS handler to display the error message:

Our JuZcret app now provides a pretty good feature for the end user:

02-comment

Note: If you implement this step just after following the previous steps, you just have to compile your project, paste the new created war in eXo Platform, and start the server. Then access your JuZcret page and take a look at the result. If the result is not correct, configure your project to use JRebel, compile the code, and deploy it in eXo Platform as explained in step 1.

What is missing, so far, is an administrator to manage our application. An administrator must have the availability to configure the portlet. For instance, he or she may want to disable the comment feature.

To do this, what could be better than adding a portlet edit mode?

Portlet Edit Mode

Juzu portlet is JSR286 compliant portlet. To provide an edit mode, we need to tell the portlet container that our portlet support should show an edit mode. That’s why we need to modify our portlet.xml as shown below:

Now the JuZcret portlet has two modes: edit and view mode. We need to create a new template for the edit mode. In the templates package, add a new file, editMode.gtmpl, to display a checkbox to enable the user to comment on secrets, or not:

Our JuZcret application configuration will rely on the portlet preference mechanism.

Juzu’s framework provide a juzu-portlet plugin which helps to bind the portlet preference to our IOC container and allows the user to inject and use PortletPreferences in our controller to store the configuration data of our portlet.

To use this plugin, we need to add juzu-plugins-portlet and portlet-api dependency in the pom.xml:

Now we can inject in our JuZcretApplication controller PortletPreferences using the @Inject annotation. We use it in a new action controller method, named enableComment, which manages the submission of the edit form:

After saving the portlet preference, notice that we redirect the portlet to View mode by responding with a Juzu property, the JuzuPortlet.PORTLET_MODE property type with the value PortletMode.VIEW.

Now JuZcret can be configured to disable the comment feature. This means that we have to adapt our secretWall.gtmpl template to display or not display the form for submitting comment by using the enableComment parameter:

From a security perspective, hiding the social toolbar on the bottom is not enough to prevent a user from commenting, but for the sake of simplicity, we have decided that this solution is acceptable for this tutorial. So when you have disabled comments, it is no longer possible to like or comment on a secret. Social features are deactivated.

The last step is to inject the new editMode.gtmpl template to the controller and modify the index View controller to adapt the display in accordance with the current Portlet mode:

To find out the current Portlet mode, we use the RequestContext object, automatically injected by Juzu, that allows us to check the property JuzuPortlet.PORTLET_MODE.

Recompile your application with

Then stop the eXo Platform, copy/paste the new created war in the webapp folder, and restart the eXo Platform.

Go to the JuZcret page and click on Edit → Page → Edit Layout. Then mouse over the “Juzu Secret Application” and click on the “Edit Portlet” icon.

Here you can disable comments:

03-disable-comments

After unchecking “enable comment,” save and close the edit mode. You cannot add a new comment via the secret wall:

04-disabled-comments

We are at the end of step 4 with a nice social application, but our JuZcret application is still missing something important before it will be ready for production: data is not persistent yet. To fix this, come back to this blog next week to read step 5.

The final source of step 4 is available for downloading on Github.

Previous and next steps:
Learn how to develop great Juzu portlets for eXo Platform!
Step 2: viewing and posting secrets
Step 3: Building a sexy secret wall
Step 4: adding Likes and Comments for Secret
Step 5: Saving Secrets in the JCR
Step 6: Let the whole world create new secrets
Step 7: Finishing the job properly with unit test

Join the eXo tribe by registering for the community and get updates, tutorials, support, and access to the Platform and add-on downloads!

Make the most out of eXo Platform 4

Register to the next webinar and get a complete overview of what you can do with eXo Platform 4. Reserve your seat now!

Be part of the discussion, share your comments

comments

Keep in touch with the author

Tags: , , , , , , ,