Discussions

News: Developing an App with the new Juzu Web Framework and AJAX

  1. In this article I will show how to we can produce simple and efficient gadget like applications with Juzu. I took as example the Who Is Online gadget eXo Platform provides. I will not implement of course the business rules for this gadget or the look and feel, however I will show how we can create an application that is efficient, simple and tested.

    The main change from the original gadget is to leave the Rest programming model to use the Ajax programming model:

    • Rest:  a pure JavaScript application that uses Rest services to retrieve JSON data and build the UI in the browser
    • Ajax: the client ask the server to provide markup and the client updates a portion of the page with the fragment

    Both programming model uses JavaScript, however Ajax applications use usually than Rest applications. So why should we chose Ajax over Rest ? There are several good reasons in this use case

    • Ajax applications create markup on the server where most of the services, in the same memory space.
    • The first time the application is displayed, Ajax applications can render the entire markup in the initial response, Rest applications can’t. It means that page loading is faster because the client does not have to connect to the server.

    Beans

    Juzu applications can use Javabeans, in our application we will make an WhoIsOnline bean with a single method for retrieving the friends of a user:

    public interface WhoIsOnline { Collection<User> getFriends(String userId); }

    (For better code readibility, if you want to try it by yourself, it's here.)

    This bean is just a facade in front of the real services, it does not aim to be the service itself. The motivation is that we can provide several implementations for the bean, in particular we will provide a mock implementation for testing purposes.

    Who is online ?

    Now we can display who is online in our application with a Juzu controller:

    public class Controller { @Inject WhoIsOnline whoIsOnline; @Inject @Path("index.gtmpl") Template index; @View public Response.Render index() { Collection<User> friends = whoIsOnline.getFriends("me"); return index.with().set("users", friends).render(); } }

    (For better code readibility, if you want to try it by yourself, it's here.)

    We need two templates for rendering index.gtmpl and users.gtmpl, the former including the later (we will see the reason later):

    The users online are: <div class="users"> #{include path=users.gtmpl}#{/include} </div>  

    The users.gtmpl templates iterates over the users and display them in a list:

      <ul> <% users.each { user -> %> <li>${user.firstName} - ${user.lastName}</li> <% } %> </ul>

    (For better code readibility, if you want to try it by yourself, it's here.)

     

    Mocking the users

    Finally we need to provide an implementation for the WhoIsOnline interface. We will use mock, i.e a simple implementation of the interface that does not require a backend. The goal is to test the UI and in this case using mock is great because the setup is very minimal:

    @Singleton public class MockWhoIsOnline implements WhoIsOnline { private ArrayList<User> friends = new ArrayList<User>(); public Collection<User> getFriends(String userId) { friends.add(new User("First-" + friends.size(), "Last-" + friends.size())); return friends; } }

    (For better code readibility, if you want to try it by yourself, it's here.)

    This simple implementation add a new friend to the list each time the getFriends method is called.

    Testing the app

    Now we will focus on testing the application with a JUnit test:

    @RunWith(Arquillian.class) public class WhoIsOnlineTestCase { @Deployment public static WebArchive deployment() { WebArchive war = Helper.createBasePortletDeployment(); war.addAsWebInfResource(new File("src/main/webapp/WEB-INF/portlet.xml"), "portlet.xml"); war.addAsWebResource("whoisonline/jquery-1.7.1.min.js", "jquery-1.7.1.min.js"); // Use spring.xml with the MockWhoIsOnline bean war.addAsWebInfResource("whoisonline/spring.xml", "spring.xml"); return war; } @ArquillianResource URL deploymentURL; @Drone WebDriver driver; }

    (For better code readibility, if you want to try it by yourself, it's here.)

    This project uses several framework that will setup an embedded Tomcat with the GateIn Portlet Container:

    • The @RunWith(Arquillian) tells JUnit to run the test with the Arquillian framework
    • The deployment() method packages a war file that contains the application, it is invoked by Arquillian after is started Tomcat
    • The driver is a Selenium WebDriver wrapper, the @Drone annotation tells Arquillian to inject it in our test
    • The deploymentURL will be the base URL of the web application in Tomcat, it will be injected by Arquillian after the application started

    Ajax dude

    So now our application shows an initial page with the user’s friends we will use Ajax to refresh the page periodically and refresh the page.

    Let’s first add a new method to our controller that returns the list of users as an ajax resource:

    @Inject @Path("users.gtmpl") Template users; @Ajax @Resource public Response.Render users() { Collection<User> friends = whoIsOnline.getFriends("me"); return users.with().set("users", friends).render(); }

    (For better code readibility, if you want to try it by yourself, it's here.)

    Now we use the users template directly from the controller and this fragment will be returned to the JavaScript part of our application:

    $(function() { var refresh = function() { $(".users").each(function() { $(this).jzLoad("Controller.users()"); }); }; // Wait 1/2 second (not realistic of course) // And we should use setInterval with 60 seconds setTimeout(refresh, 500); });

    (For better code readibility, if you want to try it by yourself, it's here.)

    The JavaScript code is quite trivial but there are two important points here

    We use the jzLoad function instead of the jQuery load function : the jzLoad is a jQuery plugin provided by Juzu that allows to specify the reference to a controller instead of an URL. Under the hood Juzu will wrap the HTML with a block that contains the URLs.

    The other point is that we don’t need any single script tag in the HTML. Instead we rely on the users CSS class to add behaviour, there are several key benefits to this

    • The code is in a self contained JavaScript file whoisonline.js and there are not script tag in our application. The whoisonline.js can be cached by the browser
    • The same JavaScript code works regardless of the number of the portlet we put on the page
    • In eXo Platform 4 we can serve this code as a JavaScript module and benefit from the advanced modularity provided by GateIn 3.5

    Last but not least we provide the code for testing the Ajax load:

    @Test @RunAsClient public void testIndex() throws Exception { driver.get(deploymentURL + "/embed/WhoIsOnline"); WebElement p = new WebDriverWait(driver, 10).until( new ExpectedCondition<WebElement>() { public WebElement apply(WebDriver input) { List<WebElement> users = input.findElements(By.cssSelector("div.users ul li")); if (users.size() > 1) { return input.findElement(By.cssSelector("div.users")); } else { return null; } } }); List<WebElement> users = p.findElements(By.tagName("li")); Assert.assertEquals(2, users.size()); }

    (For better code readibility, if you want to try it by yourself, it's here.)

    We use Selenium WebDriver until method that will block until more than one li tag is available. This will happen after the first Ajax refresh, if it does not happen it means there is a bug and after 10 seconds the until method will fail and make the unit test fail.

    Additional Resources:

     

    Threaded Messages (4)

  2. Oh No !!![ Go to top ]

    Yet, another framework.

  3. just to say...[ Go to top ]

    Thanks to new Web Frameworks developed by talentuous people, you can build web apps like you do today (taking full power of jquery, less, angular, etc) ;-)
    Maybe this one isn't mean for you but it comes with new ideas that will certainly ease development for Java developers. By leveraging java annotations at a new level, JuzuWeb makes Async Ajax, Less integration, routing and more a very easy task in your development process.
    I think it's worth taking a look at it (if you have time)... and of course commenting on its features rather than it's the new kid in the block. I'm curious of all feedbacks since I personally love developing with JuzuWeb.

  4. just to say...[ Go to top ]

    How does this compare to (μ)Micro?

    See https://github.com/florinpatrascu/micro

  5. JEE[ Go to top ]

    JuzuWeb was created to ease development for web applications in Java.

    Today, you have some frameworks like Spring or JSF where you can develop in JEE environment. But for me, it comes with too much layers and complexity. Juzu takes a different approach, more like Play! Framework does but still in JavaEE.

    As a bonus, it comes with support for Java portlets which can be handy when you have to develop in a portal solution following this standard.

    http://juzuweb.org/reference/index.html

    For what I understand, Micro is more in the Play! approach (standalone applications). Even if it's possible to do so with Juzu, it's just one side of the equation.

    To know more about its coolness, I recommend you to stop by http://blog.exoplatform.com/2013/01/24/juzu-day-3-the-coolness