Developing Juzu portlets – Step 2: viewing and posting secrets

02-Juzu-tutorial-series

Previous step:
Learn how to develop great Juzu portlets for eXo Platform!

In the previous blog post, you learned how to start a simple Juzu project and deploy it in eXo Platform.

In this blog post, we will start to play with Juzu and add some functionality to our application.

Introduction

It’s time to tell you a little bit more about the JuZcret application.

First of all we have secret. A secret is a simple message but it can also be enhanced by an image (to illustrate the secret better).

Our application will manage a list of secrets and display them. Of course any user can also share their secrets using an add secret button.

In later steps, we will allow connected users to like and comment on secrets, but these features are not included in Step 2.

Create our model

This does not require any Juzu stuff. We just need to create a simple Secret bean containing a default constructor with getters and setters.

In the org.juzu.tutorial package, add a new package named models. In this new package, create a Secret class as below:

01-model

Secret

Create our service

We need to create an application bean to manage all the secrets: the SecretService!

The SecretService bean will contain all the logic for our application, like getting the list of secrets and adding a secret.

In the org.juzu.tutorial package, add a new package named services. In this new package, create the interface SecretService and its implementation SecretServiceMemImpl as below:

02-service

The SecretService interface

The SecretService implementation

Note: In step 2, we will implement a simple in-memory data-saving implementation for simplicity. Real persistence is only for real aspirant Juzu developers not for rookies 😉 and will be covered later in step 5.

Display secrets

Now that our SecretService application bean is ready, we would like to use it.

But as before, we first need to declare it. And declaring a custom bean in Juzu is very simple.

Binding the application bean

Remember step 1, when I told you about the configuration file for our application named package-info.java.

This Java file is the home for the package level annotation. This is where we will declare our new application bean. Replace the file package-info.java with:

In a Juzu application, we can have several kinds of bean: controllers, templates, plugins and application services (don’t worry, each of these will be covered in a different step).

All these different types of bean are managed by the container, which means that it is the job of the IOC container to manage the service lifecycle (instantiation, inject dependencies, …) and to inject them where you need them.

For instance, you can directly inject and use a template in a controller by adding the @Inject annotation when you declare it:

However, if you want to use a custom bean, like our SecretService, you first need to declare it in the package-info.java using the @Binding annotation.

And that’s it. Now we can use the SecretService bean anywhere in our application, simply by using the @Inject annotation.

Scoped binding

It’s time for a lesson! Let’s talk a little bit about scoped binding in Juzu.

As you can see, we have declared our service as a singleton:

By declaring the service bean as a singleton in package-info.java, I have overridden the scope annotation the bean could declare.

The annotation scope is optional in package-info.java. If the scope is not specified, it is determined from the bean, which should be annotated with a scope.

For instance, in our case, the following declaration in package-info.java:

will give us the exact same result as this declaration:

It’s recommended to add a scope in package-info.java, since it gives more fine-grained control and on opening the file you have a quick overview of the composition of the project.

Abstract bean binding

Let’s have another talk, this time about abstract bean binding in Juzu.

In our example, we need to set the implementation member of the @Binding annotation because SecretService is an interface.

If an application bean doesn’t have an interface, then you don’t need to set the implementation member. For instance, in our case, we may directly use this implementation:

Ok, that’s enough explanation. Let’s go back to the code.

Develop the controller

We already developed the new application bean, SecretService, and we declared it in package-info.java. Now it’s time to use it with a new controller named JuZcretApplication, which will allow us to display a list of secrets.

In the org.juzu.tutorial package, create a new java class JuZcretApplication:

The JuZcretApplication controller bean must be the default controller for our application. Right now we have two controller beans in our project:

  • Controller.java
  • JuZcretApplication.java

There is no problem with this. In Juzu, you can have as many controllers as you want. But (and there’s always a but…), you need to tell Juzu which one is the default controller.

Guess where we will define this? Yes, package-info.java!

Open it and just update the @Application annotation by setting the defaultController member:

To display a list of secrets, our JuZcretApplication controller needs:

  • The SecretService application bean
  • A new template able to display a list of secrets

Create a new empty template, secretWall.gtmpl, in the org.juzu.tutorial.templates package. The secretWall template will be responsible for displaying the list of secrets.

Also create another empty template, addSecret.gtmpl, in the org.juzu.tutorial.templates package:

03-templates

The addSecret template will be responsible for displaying the form used to add a new secret.

We need to inject into JuZcretApplication, our application bean and our template beans:

Note: If you get a “cannot resolve symbol” exception after injecting a newly created template, like this:

04-addSecret

then you should recompile your project:

This will generate the Java class associated with this template and consequently fix the “cannot resolve symbol” exception.

Now we need to create a new view controller. A view controller is a method with the @View annotation and is responsible for providing the markup. @View will use an injected template to create markup. The @View method delegates the rendering to the template.

In our case, we will create a new view controller responsible for displaying the list of secrets.

Type safe parameters

You can declare parameters in a template that are directly available to subclasses of the juzu.template.Template class.

For instance, open secretWall.gtmpl and add:

Now add the view into JuZcretApplication.java like this:

You see that we can directly set the parameter secretsList declared in the secretWall template via a generated method named with the parameter name. For the secretsList parameter #{param name=secretsList/}, we have a secretsList() method that can be used.

Consequently, if you modify the secretWall.gtmpl template and change the name of the parameter secretsList, the compilation of JuZcretApplication.java will fail.

Declaring a parameter in the template and using a generated method in the controller are not mandatory. You can simply use a HashMap to store parameters passed by the controller to the template:

But using a HashMap means that if a parameter name changes in the template, the controller will continue to compile without error because of the generic parameter map, and you will only see the error at runtime. To avoid seeing this situation, it’s better to declare parameters in the template and use the generated methods named with the parameter name.

Default controller method

One more thing. In Juzu, index is a special name that catches any unmatched request. In other words, the method index() annotated with @View provides the default markup for our application.

Integrating with Platform 4.1

Guys, after this explanation we need to take a break here because I have something to confess.

Today the official Juzu version supported by Platform 4.1 is 0.6.2. I don’t want to limit you to 0.6.2. I want to let you discover all of the Juzu features available in version 1.0.0-cr1. To run a Juzu 1.0.0-cr1 portlet properly in Platform 4.1, we need to override the implementation that comes from the eXo commons project. If not, we’ll get an unexpected error due to the conflict in the class version. This problem will be fixed as soon we upgrade Platform with the newest Juzu version.

This is quick and pretty simple. And because we are nice, notice that we created a specific Juzu helloWorld project for you that already contains all the stuff needed to create a Juzu portlet for Platform 4.1.

So for your next personal project, I advise you to clone this Juzu Platform 4.1 startup project.

But in this tutorial, it’s important to understand what happens so you can become a real Juzu developer ;). That’s why you need to follow this instruction:

In Platform, the services are managed by eXo container, thanks to provider factory support. A provider factory provides pluggability for integrating beans that are not managed natively by the IOC container but need to be integrated inside the container.

For JuZcret to run properly in Platform now, we need to declare a KernelProviderFactory.

First, we need to create a new file named juzu.inject.ProviderFactory in src/main/resources/META-INF/services/.

In this file, we just add a line with the implementation class name:

Notice that it’s important to keep the name exactly like that above, as this is a workaround to override the implementation that comes from the eXo commons project.

Second, we create the kernel provider factory class. In the org.exoplatform.commons.juzu package, add a KernelProviderFactory class:

The provider calls the PortalContainer – an object from the eXo kernel library – and delegates finding the managed bean to it. Juzu will use the returned result to bind to its container. So we need to add the dependency to eXo kernel lib in the POM of our project:

That’s it. Now our Juzu 1.0.0-cr1 portlet can work on Platform 4.1.

Remember, for your next project, a Juzu Platform 4.1 startup project is available.

Display secrets

Note: We will now configure our project to use JRebel. This will allow hot redeployment of our portlet without restarting the server.

Recompile the project:

Copy and paste the WAR file (which replaces the old one) in the web app folder of the Platform server as explained in step 1, start the server and open the JuZcret page created in step 1.

It displays a simple message:

05-message

What we really want it to do is to get the list of secrets and display it. Not display a single hard-coded sentence.

Note: Remember that we have just configured the portlet to use JRebel. So from now on, we don’t need to restart the server after a modification. We can just rebuild it using mvn clean compile.

In JuZcretApplication.java, modify the index method to pass a list of secrets to the secretWall template instead of a string:

In SecretServiceMemImpl.java, we will initialize the list with some fake secrets so that we have something to display for our test:

Finally, we need to update the secretWall.gtmpl template to manage the list of secrets passed by the controller and display all secrets:

Juzu templating

The native Juzu template engine extends the Groovy templating system so we can include snippets of Groovy code or resolve Groovy expressions.

In our case, we use Groovy code with the scriptlet syntax <% … %> to perform a simple loop for each secret. Then each secret is added within a <li> tag using Groovy expressions wrapped with the ${…} syntax.

See the list of secrets

Next we rebuild our project, refresh the browser, and here is the result:

06-secret-list

You’ll see in the server log something like this:

JRebel reloads the classes, which saves us from having to restart the Tomcat server. But keep in mind that it can only reload a class; it can’t renew an object instance. That means that attributes of created objects stay the same after the class has been reloaded.

Add a secret

We are close to the end! After displaying the secrets, we want to add a new secret.

We already have a service ready with an addSecret method:

What is missing is a form to create a new secret and the logic to manage it. This is what we need to do:

  • Update the gtmpl template for adding a secret.
  • Update the gtmpl template to display an add secret form.
  • Create a new view controller to provide markup for creating a secret using the gtmpl template.
  • Add some logic to switch between the different views and manage the add secret feature.

Template

We need to add a link in the secretWall.gtmpl to switch to the add secret form:

For now we will keep the href empty. We will come back to it later.

Then we need to update the addSecret.gtmpl template so we can display an add secret form:

We keep the values of both href and the action parameters empty. We will come back to these later.

View

We need to create a new view controller to provide markup for adding a new secret in JuZcretApplication.java.

At the beginning of this step, we have already injected the new template, addSecret:

Go back to secretWall.gtmpl to update the href of the link and let Juzu manage it:

Controller URLs are natively supported in the template. So if you change the path for your view, you don’t need to update your template. Juzu will take care of it.

Action

In Juzu, application logic processing is implemented via an action controller, which is a method annotated with @Action.

In JuZcretApplication.java, let’s create our first action controller. It will be responsible for creating a new secret:

Now go back to addSecret.gtmpl and update the submit action of the form:

Now rebuild the project, refresh the browser, and click on the Share my secret link to add a new secret:

07-add-secret-form

Note: After JRebel reloads our project, our portlet may display an error message instead of the expected screen. If this happens, you need to restart the server.

Redirection

An action never produces markup. Instead an action phase is followed by a view phase that will return a markup response. Juzu handles this interaction with an http redirection to the next view phase via the redirect after post pattern.

What’s JuZcretApplication_? It’s a class generated by Juzu via an annotation of JuZcretApplication.

It’s the companion class of JuZcretApplication generated by Juzu during the compilation of the project. In Juzu, all controller classes generate a companion class. The companion class has the same name as the original class appended with the _ character.

So, after adding a new secret you are automatically redirected to the secret wall page:

08-share-secret

Now we don’t need Controller.java and index.gtmpl any more. You can remove both of them. Your project should look like this:

09-project

We now have some interesting features allowing us to interact with our Juzu portlet, but it still has an ugly design…

In the next blog post, Step 3 – Building a sexy secret wall, we will improve the UI of JuZcret to attract many secret users… (Edit: “Step 3: Building a sexy secret wall” is live!)

The final source of step 2 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: , , , , , ,