Tag Archives: mvc

Getting started with Spring MVC and Gradle

Today, I would like to share an article that can help to get started with Spring MVC and Gradle.

What is Gradle?

I never use Gradle before, however, it’s easy to know what Gradle is, due to wikipedia.org:

“Gradle is a project automation tool that builds upon the concepts of Apache Ant and Apache Maven and introduces a Groovy-based DSL instead of the more traditional XML form of declaring the project configuration.”

I don’t know about Groovy, however, we can learn a lot about Gradle by visiting http://www.gradle.org/.

Install Gradle on Windows

Download the latest Gradle distributed package at http://www.gradle.org/. Current version of Gradle is 1.9.

I extract Gradle distribution to folder c:\gradle-1.9 and also add gradle root folder to system PATH variable.

To see as if Gradle is working, open command line application and try to call gradle.bat, the you see the result like below, you can now using Gradle.

I choose NetBeans 7.3 to be my IDE, but NetBeans doesn’t support Gradle officially, so we need to install a plugin named Gradle by follow the instruction from the web page http://plugins.netbeans.org/plugin/44510/gradle-support.

After installing Gradle, you need to configure Gradle plugin by open menu Tools->Options. We need to set the Gradle Installation Directory for the plugin.

Then, use NetBeans to create new Gradle project:

After choosing project type, now we have to input project name and the main class:

After clicking finish, then a project will be created with its structure like below:

You can see the build.gradle file and settings.gradle file. The build.gradle file is the most important one. You don’t need to use NetBeans to create the project, you just need create a new folder and create the two files build.gradle and settings.gradle.

The settings.gradle just contains the project name:

rootProject.name = 'gradle-simple-mvc'

The build.gradle stores all configuration needed for our project:

apply plugin: 'java'

sourceCompatibility = '1.7'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'

if (!hasProperty('mainClass')) {
    ext.mainClass = 'com.tumivn.mvcsample.Main'
}

repositories {
    mavenCentral()
}

dependencies {
    // TODO: Add dependencies here ...
    // You can read more about how to add dependency here:
    //   http://www.gradle.org/docs/current/userguide/dependency_management.html#sec:how_to_declare_your_dependencies
    testCompile group: 'junit', name: 'junit', version: '4.10'
}

To enable java in the project, we need to enable java plugin:

apply plugin: 'java'

The main repository we use for loading dependencies (java libraries) is Maven so we need to declare it:

repositories {
    mavenCentral()
}

Netbeans also declare a dependency for the project, which is JUnit, for unit testing:

dependencies {
    // TODO: Add dependencies here ...
    // You can read more about how to add dependency here:
    //   http://www.gradle.org/docs/current/userguide/dependency_management.html#sec:how_to_declare_your_dependencies
    testCompile group: 'junit', name: 'junit', version: '4.10'
}

However, we need to change the the content of the build.grade so it will be a Spring MVC application other than a Java SE application:

apply plugin: 'war'
apply plugin: 'jetty'

repositories {
    mavenCentral()
}

dependencies {
    providedCompile 'javax.servlet:servlet-api:2.5'
    compile 'org.springframework:spring-webmvc:3.2.5.RELEASE'
    testCompile 'junit:junit:[4,)'
    runtime 'javax.servlet:jstl:1.2'
}

/* Change context path (base url). otherwise defaults to name of project */
jettyRunWar.contextPath = ''

We need 'war' plugin to enable web development and when building the application a war file will be created for deployment; 'jetty' plugin for running jetty web server and deploy our website for testing. And the project need more dependencies:

dependencies {
    providedCompile 'javax.servlet:servlet-api:2.5'
    compile 'org.springframework:spring-webmvc:3.2.5.RELEASE'
    testCompile 'junit:junit:[4,)'
    runtime 'javax.servlet:jstl:1.2'
}

We need javax.servlet:servlet-api version 2.5 and spring web MVC framework version 3.2.5 for develop our website.

Then, we need add more folders to create web application structure:

You can see the web.xml file, it's the web configuration file, below is its content:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/dispatcher-servlet.xml</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

in this file we need to declare an org.springframework.web.servlet.DispatcherServletDispatcherServlet instance to processing work flow. Its name is dispatcher and the configuration file will be stored at [application root]/src/webapp/WEB-INF/spring/dispatcher-servlet.xml.

The dispatcher-servlet.xml content:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
            http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.2.xsd">

  <context:component-scan base-package="com.tumivn.mvcsample.controller" />  
  <mvc:annotation-driven />

  <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/view/"/>
    <property name="suffix" value=".jsp"/>
  </bean>

</beans>

We declare to use annotation to configure routing instead of using XML by a declaration:

  <mvc:annotation-driven />

Beside, we have a declaration to allow dispatcher-servlet to scan through com.tumivn.mvcsample.controller package to get controllers appropriate for each request.

Now it's the time to write the first controller named HomeController:

package com.tumivn.mvcsample.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeController {

    @RequestMapping("/")
    public String loadIndexPage(Model model) {
        model.addAttribute("title", "Hello Spring MVC!");
        return "index";
    }
}

The loadIndexPage method is configured to response to the "/" request, and it will send the model with "title" message inside and the view "index" (WEF-INF/view/index.jsp) to front controller to merge view and model and return the result to browser. Below is the implementation of index.jsp

<!DOCTYPE HTML>
<html>
    <head>
        <title>${title}</title>
    </head>
    <body>
        <h1>${title}</h1>
    </body>
</html>

Now, it's the time to build the application. You can easily right click at the project root and choose build menu to build. Or open command line and go to the project root folder and then call "gladle.bat build" command and see build successes.

Now, it's time to run the web application by using the jettyRun task of gradle.

The Jetty server will be run and the website will be available at address http://localhost:8080/gradle-simple-mvc. Open a browser and browse the url and you will see a message "Hello Spring MVC!" on the browse. Congratulation!

To reference, source code is available at GitHub.

This is the first time I touch Java for 5 years. Many things new, and many things I almost forgot. But Java, Gradle and Spring MVC make me excited. I love to learn more about Java and PHP for my personal projects. And still use .NET and ASP.NET MVC for daily jobs.

Happy coding!

Which JavaScript MVC Framework should i use?

Popular JavaScript MVC Frameworks

Which JavaScript MVC library should we use?

It’s hard to make decision because a lot of JavaScript MVC framework out there. For outsourcing business, it depends on what customer want. For personal usage, we can think read comparison articles and choose what we want.

Here’re two great links for your reference:

http://coding.smashingmagazine.com/2012/07/27/journey-through-the-javascript-mvc-jungle/

http://www.infoq.com/research/top-javascript-mvc-frameworks

http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/

02

How to display time following client browser time zone on ASP.NET MVC or PHP

I have a site that have many users from different time zone, and I want the times on my web page will be displayed correctly due to the client browser time zone. How to do that?

First thing first, I need to store the create/update time for articles, comments… with GMT time zone. Then, when a user try to browse a page, I will try to get client time zone, and then convert the times to client time zone to display. For example, I’m at Vietnam (GMT+7), when I try to browse an article on my website, and the article create date is GMT 2013/06/24 10:00am, it should be displayed as 2013/06/24 05:00pm (GMT+7 time).

Secondly, we need to know that, we don’t have any function to get client time zone at server side, but we know how to get the time zone at client side by using JavaScript.

Please try run the below JavaScript on any browse:

var offset = new Date();
alert(offset.getTimezoneOffset()); 
//result = 420 if client time zone is GMT+7, it means 7 hours or 420 minutes

OK, right now we know the time zone offset. But to get it on server side, we need to store the value into cookies. The JavaScript method below is to save a value to cookie:

function setCookie(cookieName, cookieValue, nDays) {
var today = new Date();
var expire = new Date();
if (nDays == null || nDays == 0) nDays = 1;
expire.setTime(today.getTime() + 3600000 * 24 * nDays);
document.cookie = cookieName + "=" + escape(cookieValue)
+ ";expires=" + expire.toGMTString() + "; path=/";
}

var offset = new Date(); 
setCookie("TimeOffset", offset.getTimezoneOffset(), 365);

But hold on a second, please see the last sentence of setCookie method:

document.cookie = cookieName + "=" + escape(cookieValue)
+ ";expires=" + expire.toGMTString() + "; path=/"; 

Why do we have “path=/”, what does it mean? Yes, it’s very important, you must know that cookies is an dictionary that will be send ford and back between client and server, so, the cookies size should be as small as possible. Let see an example below:

1) Using firebug, add a cookie by execute the document.cookie=”sample=420;” at “/” level.

When turn to Firebug Cookies tab, you will see:

01

Yes, the cookie sample is saved as expected, with Path equals to “/”.

02

2) Using Firebug again, and try to add cookie but with a deeper level page like http://jou.vn/Article/Tao-virtual-directory-cho-apache-server-tren-Ubuntu/2187, you will see that there are two cookie with the same name “sample” are stored:

03There’s no need to store a same cookie at many path, so we need to define the Path that we need to store the cookie by using “path” parameter like below:

document.cookie = "sample=420;path=/"

Now, with ASP.NET at server side, we can get the cookie easily like below:

    public int GetClientTimeOffset()
    {
        var timeOffset = 0;
        var timeOffsetCookie = HttpContext.Current.Request.Cookies["TimeOffset"];
        if (timeOffsetCookie != null)
        {
            timeOffset += Convert.ToInt32(timeOffsetCookie.Value);
        }

        return timeOffset;
    }

By using that above function, you can easily change the time value to follow the client time zone before, like:

item.CreatedDate = comment.CreatedDate.AddMinutes(-_cultureService.GetClientTimeOffset());

If you’re a PHP developer, it’s easy to get cookie value by get use $_COOKIE global variable like:

$timeOffset = $_COOKIE["timeOffset"];

But don’t forget to validate the cookie value before doing anything, because everyone can set the cookie by using a tool like FireBug. And sometime, the cookie is not set yet.

That all of my article today, the next article is about how to store multi-level comment system effectively to reduce the cost of querying data from SQL.

Happy coding!

image

Querying ASP.NET Web API with OData querying parameters

ASP.NET Web API has built-in support for some OData query parameters, and I want to write a tutorial that will use Web API, OData parameter to query data (sorting, filtering and paging) instead of implement it by ourselves in classic ASP.NET MVC like before. For more information of ASP.NET Web API and OData parameters please take a look at the article of Mike Wasson.

I assume that you have knowledge of ASP.NET MVC, Web API, JavaScript and jQuery, so this article content is all about showing of how to query data from an ApiController action.

We will create a new ASP.NET MVC 4 project named WebApiQueryingEx, this project is a product management page, it allow you to query the product list, filtering, paging and ordering the search result.

Product class

We need a Product class to store information of product in our store


public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
}

 

ProductRepository

In ProductRepository class, we will have a static variable called _products, it’s initialized when the application start and store a list of 100 products. ProductRepository has a static constructor to fill data into _products, and it has a method call GetAll to get all products, the GetAll method return a IQueryable object.

public class ProductRepository
{
    private static IList<Product> _products;

    static ProductRepository()
    {
        _products = new List<Product>();

        var random = new Random();

        for (var i = 0; i < 100; i++)
        {
            var product = new Product() { 
                Id = i, 
                Name = "Product " + i, 
                Quantity = random.Next(1000) 
            };

            _products.Add(product);
        }
    }

    public IQueryable<Product> GetAll()
    {
        return _products.AsQueryable();
    }
}

ProductsController

We need an API Controller called ProductsController to response HTTP GET request from client side to get products. The very simple ProductsController is implemented as below.

public class ProductsController : ApiController
{
    private readonly ProductRepository _productRepository = new ProductRepository();

    public IQueryable<Product> GetAll()
    {
        return _productRepository.GetAll();
    }
}

HomeController & Index.cshmtl

We have a HomeController to provide home page when user enter to the website, it has only one action called Index.

public class HomeController : Controller
{
    //
    // GET: /Home/ 

    public ActionResult Index()
    {
        return View();
    }

}

The view Index.cshtml (for action Index of HomeController) has three columns, the first column show Search function and search result, the second column is to show a query that get the top five of products that have the biggest quantities, and the third column is for showing products by paging. Then index.cshtml is implemented as below:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Product managements</title>
    <script type="text/javascript" src="../../Scripts/jquery-1.6.2.min.js"></script>
</head>
<body>
    <div>
        <h2>Product Management</h2>
        <div style="float: left; padding: 15px; border: 1px solid; margin: 5px;">
            <h3>Search by Product Name</h3>
            <div>
                <label>Search: </label>
                <input type="text" name="search-box" id="search-box" />
                <input type="button" name="search-button" id="search-button"
                    value="Search" onclick="Search($('#search-box').val())" />
            </div>
            <div id="filter-list">
            </div>
        </div>
        <div style="float: left; padding: 15px; border: 1px solid; margin: 5px;">
            <h3>Top Quantity List</h3>
            <div id="top-quantity-list">
            </div>
        </div>
        <div style="float: left; padding: 15px; border: 1px solid; margin: 5px;">
            <h3>Product Lists</h3>
            <div id="product-list">
            </div>
            <div id="product-paging">
            </div>
        </div>    </div>
</body>
</html>

Searching products by name

We will have a JavaScript method called Search to provide search-by-name function to get products by name criteria. We use $filter parameter to get the products, which contain the criteria in their names.

function Search(criteria) {
    $('#filter-list').html('ID - NAME - QUANTITY');
    $.getJSON("/api/products?$filter=substringof('" + criteria + "', Name) eq true",
            function (data) {
                $.each(data, function (key, val) {
                    var str = val.Id + ' - ' + val.Name + ' - ' + val.Quantity;
                    $('<div/>', { html: str })
                        .appendTo($('#filter-list'));
                });
            });
}

If you have taken a look to Index.cshml code, you will see that we have a call to Search method on search-button button onclick method.

<input type="button" name="search-button" id="search-button"
                value="Search" onclick="Search($('#search-box').val())" />

When you run the /Home/Index, you can type any criteria on the #search-box textbox and click on Search button to get the result, the result will be filled below the Search button.

01

Get top-five of products that have largest quantities

We have to implement a JavaScript method to get top-five of products that have the largest quantities, this method will send a HTTP request to /api/products with two parameters $top and $orderby to sort the result and get only the first-five result after sorting. The URI that our GetTopFive method will request is “/api/products?$top=5&$orderby=Quantity desc”

function GetTopFive() {
    $('#top-quantity-list').html('ID - NAME - QUANTITY');
    $.getJSON("/api/products?$top=5&$orderby=Quantity desc",
            function (data) {
                $.each(data, function (key, val) {
                    var str = val.Id + ' - ' + val.Name + ' - ' + val.Quantity;
                    $('<div/>', { html: str })
                        .appendTo($('#top-quantity-list'));
                });

            });
}

The result:

02

Paging the result

To apply paging when getting all products, we will use two parameters $top and $skip in request URI to get the paging result. The JavaScript method GetProducts is to enable paging product list.

function GetProducts(pageId, pageSize) {

    $('#product-list').html('ID - NAME - QUANTITY');

    var skipCount = (pageId - 1) * pageSize;
    $.getJSON("/api/products?$skip=" + skipCount + "&$top=" + pageSize,
            function (data) {
                $.each(data, function (key, val) {
                    var str = val.Id + ' - ' + val.Name + ' - ' + val.Quantity;
                    $('<div/>', { html: str })
                        .appendTo($('#product-list'));
                });

                var prev = pageId > 1 ? pageId - 1 : pageId;
                var next = data.length > 0 ? pageId + 1 : pageId;
                var str = '<a href="#product-list"  onclick="GetProducts(' + prev
                    + ',10)">Previous</a> &nbsp; <a href="#product-list"  onclick="GetProducts('
                    + next + ',10)">Next</a>';

                $('#product-paging').html(str);
            });
}

We update the JavaScript code to call GetProducts when page is ready:

$(document).ready(function () {
    GetTopFive();
    GetProducts(1, 10);
});

Result is:

01

This is not a fully functional paging solution, but it is enough to demonstrate paging technique using API Controller and OData query parameter.

Conclusion

This article is to introduce you a new way to query data without coding too much on server side by using Web API and OData query parameter. Hope that you will enjoy with Web API!

Happy coding!