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

[复制链接]
查看11 | 回复6 | 2011-5-7 01:45:08 | 显示全部楼层 |阅读模式
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 browserAjax: 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 caseAjax 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.

回复

使用道具 举报

千问 | 2011-5-7 01:45:08 | 显示全部楼层
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[U] 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.
回复

使用道具 举报

千问 | 2011-5-7 01:45:08 | 显示全部楼层
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[U] 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:#{include path=users.gtmpl}#{/include}
The users.gtmpl templates iterates over the users and display them in a list:
%>
  • ${user.firstName} - ${user.lastName}
    (For better code readibility, if you want to try it by yourself, it's here.)
  • 回复

    使用道具 举报

    千问 | 2011-5-7 01:45:08 | 显示全部楼层
    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[U] friends = new ArrayList[U](); public Collection[U] 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.
    回复

    使用道具 举报

    千问 | 2011-5-7 01:45:08 | 显示全部楼层
    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
    回复

    使用道具 举报

    千问 | 2011-5-7 01:45:08 | 显示全部楼层
    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[U] 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() { public WebElement apply(WebDriver input) { List users = input.findElements(By.cssSelector("div.users ul li")); if (users.size() > 1) { return input.findElement(By.cssSelector("div.users")); } else { return null; } } }); List 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:
    If you want to try it by yourself and use the code provided, please refer to this blog post.
    To learn more about the Juzu Web Framwork, Three Days with Juzu: Write a Killer App, is the good starting point. It gives an overview of Juzu capabilities and then dive deeper in the specifics to use this new web framework efficiently.

    回复

    使用道具 举报

    千问 | 2011-5-7 01:45:08 | 显示全部楼层
    GOOD!
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    主题

    0

    回帖

    4882万

    积分

    论坛元老

    Rank: 8Rank: 8

    积分
    48824836
    热门排行