Showing posts with label JQuery. Show all posts
Showing posts with label JQuery. Show all posts

Tuesday, May 1, 2012

Bootstrap Multilevel Dropdown Menu

Simple example of twitter Bootstrap Multilevel Dropdown Menu here is the working example jsfiddle and below is the complete source of html.



<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">

        <title>Bootstrap Multilevel Dropdown Menu</title>
        <script type='text/javascript' 
        src='http://code.jquery.com/jquery-1.7.1.js'></script>
        <link rel="stylesheet" type="text/css"
              href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">

        <script>

            /* bootstrap-dropdown.js v2.0.2

             * http://twitter.github.com/bootstrap/javascript.html#dropdowns
             * ============================================================
             * Copyright 2012 Twitter, Inc.
             *
             * Licensed under the Apache License, Version 2.0 (the "License");
             * you may not use this file except in compliance with the License.
             * You may obtain a copy of the License at
             *
             * http://www.apache.org/licenses/LICENSE-2.0
             *
             * Unless required by applicable law or agreed to in writing, software
             * distributed under the License is distributed on an "AS IS" BASIS,
             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
             * See the License for the specific language governing permissions and
             * limitations under the License.
           */
     !function( $ ){
       "use strict"
      /* DROPDOWN CLASS DEFINITION
             * ========================= */
            var toggle = '[data-toggle="dropdown"]'
            , Dropdown = function ( element ) {
                var $el = $(element).on('click.dropdown.data-api', this.toggle)
                $('html').on('click.dropdown.data-api', function () {
                    $el.parent().removeClass('open')
                })
            }
            Dropdown.prototype = {
                constructor: Dropdown
                , toggle: function ( e ) {
                    var $this = $(this)
                    , selector = $this.attr('data-target')
                    , $parent
                    , isActive

                    if (!selector) {
                        selector = $this.attr('href')
                        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
                    }

                    $parent = $(selector)
                    $parent.length || ($parent = $this.parent())
                    isActive = $parent.hasClass('open')
                    clearMenus()
                        !isActive && $parent.toggleClass('open')
                    return false
                }
            }

            function clearMenus() {
                $(toggle).parent().removeClass('open')
            }
            /* DROPDOWN PLUGIN DEFINITION
             * ========================== */
            $.fn.dropdown = function ( option ) {
                return this.each(function () {
                    var $this = $(this)
                    , data = $this.data('dropdown')
                    if (!data) $this.data('dropdown', (data = new Dropdown(this)))
                    if (typeof option == 'string') data[option].call($this)
                })
            }
            $.fn.dropdown.Constructor = Dropdown
            /* APPLY TO STANDARD DROPDOWN ELEMENTS
             * =================================== */
            $(function () {
                $('html').on('click.dropdown.data-api', clearMenus)
                $('body').on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle)
            })
        }( window.jQuery );
        </script>
        
        <script type='text/javascript'>//<![CDATA[
        $(window).load(function(){
            jQuery('.submenu').hover(function () {
                jQuery(this).children('ul').removeClass('submenu-hide').addClass('submenu-show');
            }, function () {
                jQuery(this).children('ul').removeClass('.submenu-show').addClass('submenu-hide');
            }).find("a:first").append(" &raquo; ");
        });//]]> 
        </script>
        
        <style>
            .submenu-show
            {
                border-radius: 3px;
                display: block;
                left: 100%;
                margin-top: -25px !important;
                moz-border-radius: 3px;
                position: absolute;
                webkit-border-radius: 3px;
            }
            .submenu-hide
            {
                display: none !important;
                float: right;
                position: relative;
                top: auto;
            }
            .navbar .submenu-show:before
            {
                border-bottom: 7px solid transparent;
                border-left: none;
                border-right: 7px solid rgba(0, 0, 0, 0.2);
                border-top: 7px solid transparent;
                left: -7px;
                top: 10px;
            }

            .navbar .submenu-show:after
            {
                border-bottom: 6px solid transparent;
                border-left: none;
                border-right: 6px solid #fff;
                border-top: 6px solid transparent;
                left: 10px;
                left: -6px;
                top: 11px;
            }
        </style>
    </head>
    <body>
        <div class="navbar navbar-fixed-top">
            <div class="navbar-inner">
                <div class="container-fluid">
                    <a data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar">
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </a>
                    <a href="#" class="brand">Project name</a>
                    <div class="nav-collapse">
                        <ul class="nav">
                            <li class="active"><a href="#">Home</a></li>
                            <li><a href="#">Link</a></li>
                            <li><a href="#">Link</a></li>
                            <li><a href="#">Link</a></li>
                            <li class="dropdown">
                                <a data-toggle="dropdown" class="dropdown-toggle" href="#">Go To <b class="caret"></b></a>
                                <ul class="dropdown-menu">
                                    <li class="dropdown submenu">
                                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">Level 1</a>
                                        <ul class="dropdown-menu submenu-show submenu-hide">
                                            <li class="dropdown submenu">
                                                <a href="#" class="dropdown-toggle" data-toggle="dropdown">Level 1.1</a>
                                                <ul class="dropdown-menu submenu-show submenu-hide">
                                                    <li><a href="#">Level 1.1.1</a></li>
                                                    <li><a href="#">Level 1.1.2</a></li>
                                                    <li><a href="#">Level 1.1.3</a></li>
                                                    <li><a href="#">Level 1.1.4</a></li>
                                                </ul>
                                            </li>
                                            <li class="dropdown submenu">
                                                <a href="#" class="dropdown-toggle" data-toggle="dropdown">Level 1.2</a>
                                                <ul class="dropdown-menu submenu-show submenu-hide">
                                                    <li><a href="#">Level 1.2.1</a></li>
                                                    <li><a href="#">Level 1.2.2</a></li>
                                                </ul>
                                            </li>
                                            <li><a href="#">Level 1.3</a></li>
                                            <li><a href="#">Level 1.4</a></li>
                                            <li><a href="#">Level 1.5</a></li>
                                        </ul>
                                    </li>
                                    <li><a href="#">Other</a></li>
                                </ul>
                            </li>
                        </ul>
                    </div><!-- /.nav-collapse -->
                </div>
            </div>
        </div>
    </body>

</html>


JSF Primefaces Mobile RSS Reader

This is a simple example of Primefaces Mobile RSS Reader similar to How to Build an RSS Reader with jQuery Mobile. For this example I have used Maven 3.0,  Primefaces 3.2, Primefaces Mobile 0.9.2 versions also I have used primefaces FeedReader component and this component has a dependency on  Rome API.

The source code is available for download @ Github and TODO is upload the example in GAE

At very high level the main page has 3 views and I am highlighting the important notable items on the page.

1. View main will Display the List of available Feeds
2. View feedsView Displays the first 10 feed content from the selected feed from main view
3. View newFeed is for adding new feed it will display a FORM to add new feed and after adding it will display the updated list.

<f:view xmlns="http://www.w3.org/1999/xhtml"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:p="http://primefaces.org/ui"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:pm="http://primefaces.org/mobile"
        contentType="text/html" renderKitId="PRIMEFACES_MOBILE">
    <pm:page title="PF RSS Reader" mini="true">
        <!-- Page content goes here -->
        <f:facet name="meta">
            <meta name="apple-mobile-web-app-capabel" content="yes" />
        </f:facet>
        <!-- Main Page to List all Feeds -->
        <pm:view id="main">
            <pm:header title="Rss Feeds" swatch="b" fixed="true">
                <f:facet name="right"><h:outputLink value="#newFeed?reverse=true">Add Feed</h:outputLink></f:facet>
            </pm:header>
            <pm:content>
                <h:form id="listFeedNames">
                    <p:dataList value="#{mobileTestController.rssFeedsList}" var="feed" type="inset">
                        <f:attribute name="filter" value="true" />
                        <p:column>
                            <p:commandLink value="#{feed.title}" update=":viewFeed" action="#{mobileTestController.viewSelectedFeed(feed)}"/>
                        </p:column>
                    </p:dataList>
                </h:form>
            </pm:content>
            <pm:footer fixed="true" style="text-align: center; font-size: 10px">
                <h:outputText value="Fixed Footer" style="text-align: center"/>
            </pm:footer>
        </pm:view>
        <!-- List Feed Results -->
        <pm:view id="feedsView">
            <pm:header title="View Feed" swatch="b" fixed="true">
                <f:facet name="left"><p:button value="Home" icon="home" href="#main?reverse=true"/></f:facet>
                <f:facet name="right"><h:outputLink value="#newFeed?reverse=true">Add Feed</h:outputLink></f:facet>
            </pm:header>
            <pm:content>
                <h:form id="viewFeed">
                    <p:feedReader value="#{mobileTestController.selectedFeed}" var="feed" size="10">
                        <h:outputText value="#{feed.title}" style="font-weight: bold"/>
                        <br />
                        <h:outputText value="#{feed.description.value}" escape="false"/>
                        <p:separator />
                    </p:feedReader>
                </h:form>
            </pm:content>
        </pm:view>
        <!-- Add New Feed Form -->
        <pm:view id="newFeed">
            <pm:header title="Add New Feed" swatch="b" fixed="true">
                <f:facet name="left"><p:button value="Home" icon="home" href="#main?reverse=true"/></f:facet>
            </pm:header>
            <pm:content>
                <h:form>
                    <p:inputText id="feed_name" label="Title:" value="#{mobileTestController.rssFeed.title}"/>
                    <p:inputText id="feed_rss" label="Rss URL:" value="#{mobileTestController.rssFeed.rssUrl}"/>
                    <p:commandButton value="Save" action="#{mobileTestController.addNewFeed}" update="@form,:listFeedNames" icon="check" />
                </h:form>
            </pm:content>
        </pm:view>
    </pm:page>
</f:view>



Wednesday, November 30, 2011

JSF Primefaces mobile Integration

Today I created my first mobile web application using Primefaces mobile and also integration with existing primefaces JSF application and it took me less than 15 minutes to setup and run the application in Weblogic 10.3.5. I have used the same managed bean for both desktop web and mobile web browsers and it  works great thanks to primefaces team powerd by JQuery mobile for awesome JSF components and detailed user guide.

There were few lessons learned during integration.

  1. Read JQuery mobile documentation it helps you during page creation. 
  2. If you are new to primefaces make sure you understand primefaces AJAX implementation.
  3. Read primefaces user guide (core & mobile) and and review the examples closely in the guide.
  4. Apply special focus while reading about <p:commandLink>. Feels silly?
  5. Follow mobile page design principals.
Update (04/11):

  • Setup the Render Kit Id as PRIMEFACES_MOBILE for parent <f:view> then you do not need to pass the request parameter with the URL  "?javax.faces.RenderKitId=PRIMEFACES_MOBILE" or you do not need to setup the default-render-kit-id in faces-config.xml
  • To make use of JQuery mini forms you can set mini="true" to the page element . Note needs primefaces mobile version 0.9.2
  • Add filter to dataList by adding the attribute filter
  • Fixed Header & Footer
  • Example code to create RSS reader Github 

Ex:


<f:view xmlns="http://www.w3.org/1999/xhtml"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:p="http://primefaces.org/ui"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:pm="http://primefaces.org/mobile"
        contentType="text/html" renderKitId="PRIMEFACES_MOBILE">
    <pm:page title="Mobile Home" mini="true">
        <!-- Page content goes here -->
        <pm:view id="main">
            <pm:header title="Fixed Header" swatch="b" fixed="true"/>
            <pm:content>
                <p:dataList>
                    <f:attribute name="filter" value="true" />
                    <h:outputText value="Barcelona" />
                    <h:outputText value="Istanbul" />
                    <h:outputText value="New York" />
                    <h:outputText value="Paris" />
                </p:dataList>
            </pm:content>

          <pm:footer fixed="true" style="text-align: center; font-size: 10px">
                <h:outputText value="Fixed Footer"/>
            </pm:footer>

        </pm:view>
    </pm:page>
</f:view>



Thursday, July 7, 2011

JAX-RS REST FileUpload and FileDownload example

In the process of comparing REST vs SOAP one of the test case for evaluation was document management service. i.e., upload and download files via services. I have previously consumed SOAP based service but it was having some serious limitations and performance issues since we have to read the complete file before writing it to output stream and has unnecessary data hops. Our goal is to deploy a simple lightweight services, with high performance dealing with documents using Jersey JAX-RS implementation.

Test case: Simple directory listing of files in a grid with an ability to upload, download and delete file as RESTful services.

Output looks some thing like this:



POM file

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>wlrestgrid</groupId>
 <artifactId>wlrestgrid</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>war</packaging>
 <name />
 <description />
 
 <dependencies>
  <dependency>
   <groupId>javax.xml.bind</groupId>
   <artifactId>jaxb-api</artifactId>
   <version>2.1</version>
  </dependency>
  <dependency>
   <groupId>com.sun.jersey</groupId>
   <artifactId>jersey-server</artifactId>
   <version>1.8</version>
  </dependency>
  <dependency>
   <groupId>asm</groupId>
   <artifactId>asm</artifactId>
   <version>3.1</version>
  </dependency>
  <dependency>
   <groupId>com.sun.jersey</groupId>
   <artifactId>jersey-json</artifactId>
   <version>1.8</version>
  </dependency>
  <dependency>
    <groupId>com.sun.jersey.contribs</groupId>
    <artifactId>jersey-multipart</artifactId>
    <version>1.8</version>
  </dependency>
  <dependency>
   <groupId>org.codehaus.jettison</groupId>
   <artifactId>jettison</artifactId>
   <version>1.3</version>
  </dependency>
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>servlet-api</artifactId>
   <version>2.5</version>
   <scope>provided</scope>
  </dependency>
  <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.0.1</version>
  </dependency>
  <dependency>
   <groupId>commons-fileupload</groupId>
   <artifactId>commons-fileupload</artifactId>
   <version>1.2.2</version>
  </dependency>
 </dependencies>
 <repositories>
        <repository>
            <id>maven2-repository.dev.java.net</id>
            <name>Java.net Repository for Maven</name>
            <url>http://download.java.net/maven/2/</url>
            <layout>default</layout>
        </repository>
    </repositories>
 <build>
  <sourceDirectory>${basedir}/src</sourceDirectory>
  <outputDirectory>${basedir}/WebRoot/WEB-INF/classes</outputDirectory>
  <resources>
   <resource>
    <directory>${basedir}/src</directory>
    <excludes>
     <exclude>**/*.java</exclude>
    </excludes>
   </resource>
  </resources>
  <plugins>
  </plugins>
 </build>
</project>


web.xml file has configurations for Jersey see line 13 it is the package where the services are defined.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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_2_5.xsd">
 <display-name></display-name>
 <servlet>
  <display-name>JAX-RS REST Servlet</display-name>
  <servlet-name>JAX-RS REST Servlet</servlet-name>
  <servlet-class>com.sun.jersey.server.impl.container.servlet.ServletAdaptor</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.dvmr.poc.rest</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.config.feature.Redirect</param-name>
            <param-value>true</param-value>
        </init-param>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>JAX-RS REST Servlet</servlet-name>
  <url-pattern>/services/*</url-pattern>
 </servlet-mapping>
 <welcome-file-list>
  <welcome-file>index.jsp</welcome-file>
 </welcome-file-list>
</web-app>


DocumentService.java has all the RESTful services defined to list, upload, download and delete file from a directory all the paths are highlighted.

package com.dvmr.poc.rest;

import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;

import com.dvmr.poc.bean.FileBean;
import com.dvmr.poc.exception.NotFoundException;
import com.dvmr.poc.service.BlobService;
import com.dvmr.poc.service.impl.BlobServiceImpl;
import com.dvmr.poc.util.MultipartUtil;

/**
 * This rest based document service
 * @author vreddy.fp
 *
 */

@Path("/document")
public class DocumentService {

 /**
  * Replace with Inject annotation in JEE6 or with Spring 3.0
  */
 private final BlobService blobService = new BlobServiceImpl();

 public DocumentService() {
  super();
 }
 
 public BlobService getBlobService() {
  return blobService;
 }


 @POST
 @Path("upload")
 @Consumes(MediaType.MULTIPART_FORM_DATA)
 @Produces(MediaType.TEXT_PLAIN)
 public Response uploadFile(@Context HttpServletRequest request,
   @Context HttpServletResponse res) throws Exception {
  String response = "Unable to attach files";
  FileBean bean = MultipartUtil.parseMultipart(request, getBlobService());
  if (null != bean) {
   response = "{\"name\":\"" + bean.getFilename() + "\",\"type\":\""
   + bean.getContentType() + "\",\"size\":\"" + bean.getSize()
   + "\"}";
  }
  return Response.ok(response).build();
 }

 /**
  * In Memory solution
  * 
  * @param blobKey
  * @return
  * @throws Exception
  */
 @GET
 @Path("download")
 @Produces(MediaType.APPLICATION_OCTET_STREAM)
 public Response downloadFile(
   @DefaultValue("empty") @QueryParam(value = "blobKey") String blobKey)
   throws Exception {
  if(blobKey.equals("empty"))
   throw new NotFoundException("blobKey cannot be empty!");
  
  byte[] docStream = getBlobService().getBlob(blobKey);
  return Response
    .ok(docStream, MediaType.APPLICATION_OCTET_STREAM)
    .header("content-disposition", "attachment; filename = " + blobKey).build();
 }
 
 /**
  * list all valid files in a directory
  * @return
  * @throws JSONException
  */
 @GET
 @Path("list")
 @Produces( { MediaType.APPLICATION_JSON})
 public JSONArray listFiles() throws JSONException{
  JSONArray arr = new JSONArray();
  List<FileBean> list = getBlobService().getBlobs();
  for(Iterator<FileBean> i = list.iterator(); i.hasNext();){
   arr.put(i.next().toJson());
  }
  return arr;
 }
 
 /**
  * remove file from directory
  * @param blobKey
  * @return
  */
 @GET
 @Path("delete")
 @Produces(MediaType.TEXT_PLAIN)
 public Response deleteFile(@DefaultValue("empty") @QueryParam(value = "blobKey") String blobKey){
  
  if(blobKey.equals("empty"))
   throw new NotFoundException("blobKey cannot be empty!");
  
  getBlobService().deleteBlob(blobKey);
  return Response.status(Status.OK).build();
 }
 
}


FileBean.java is a simple POJO that holds file details.

package com.dvmr.poc.bean;

import java.util.Map;

import javax.xml.bind.annotation.XmlRootElement;

import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;

/**
 * 
 * @author vreddy.fp
 *
 */
@XmlRootElement
public class FileBean {
 String filename;
 long size;
 String url;
 String contentType;
 Map<String, String> formFieldsMap;

 public FileBean(String filename, long size, String url, String contentType) {
  this.filename = filename;
  this.size = size;
  this.url = url;
  this.contentType = contentType;
 }

 public FileBean() {
 }

 

 public String getFilename() {
  return filename;
 }

 public void setFilename(String filename) {
  this.filename = filename;
 }

 public long getSize() {
  return size;
 }

 public void setSize(long size) {
  this.size = size;
 }

 public String getUrl() {
  return url;
 }

 public void setUrl(String url) {
  this.url = url;
 }

 public String getContentType() {
  return contentType;
 }

 public void setContentType(String contentType) {
  this.contentType = contentType;
 }

 public Map<String, String> getFormFieldsMap() {
  return formFieldsMap;
 }

 public void setFormFieldsMap(Map<String, String> formFieldsMap) {
  this.formFieldsMap = formFieldsMap;
 }
 
 public JSONObject toJson() throws JSONException {
  JSONObject obj = new JSONObject();
  obj.put("name", filename);
  obj.put("size", new Long(size));
  obj.put("url", url);
  obj.put("contentType", contentType);
  return obj;
 }
 
}


MultipartUtil.java has the method to parse the request using commons streaming API for faster uploads and better performance for reading files.

package com.dvmr.poc.util;

import java.io.InputStream;
import java.util.HashMap;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
import org.apache.commons.io.IOUtils;

import com.dvmr.poc.bean.FileBean;
import com.dvmr.poc.service.BlobService;

/**
 * 
 * @author vreddy.fp
 *
 */
public class MultipartUtil {

 /**
  * 
  * @param request
  * @return
  */
 public static FileBean parseMultipart(HttpServletRequest request, BlobService blobService){
  FileBean bean = null;
  if (ServletFileUpload.isMultipartContent(request)) { 
   bean = new FileBean();
            ServletFileUpload uploadHandler = new ServletFileUpload();
            InputStream stream = null;
            bean.setFormFieldsMap(new HashMap<String, String>());
            try {
                FileItemIterator itr = uploadHandler.getItemIterator(request);
                while(itr.hasNext()) {
                 FileItemStream item = itr.next();
                 String name = item.getFieldName(); // form field name
                    stream = item.openStream();
                    if(item.isFormField()) {
                     String value = Streams.asString(stream);
                     bean.getFormFieldsMap().put(name, value);
                    } else {
                       bean.setFilename(item.getName());
                         bean.setContentType(item.getContentType());
                         bean.setSize(blobService.uploadBlob(stream, item.getName()));
                    }
                }
            }catch(FileUploadException ex) {
             ex.printStackTrace();
            } catch(Exception ex) {
             ex.printStackTrace();
            }finally{
             IOUtils.closeQuietly(stream);
            }
        } 
  return bean;
 }
}

BlobService.java is the interface.

package com.dvmr.poc.service;

import java.io.InputStream;
import java.util.List;

import com.dvmr.poc.bean.FileBean;

public interface BlobService {
 /**
  * upload files to a directory
  * @param inputStream
  * @param filename
  * @return
  */
 public long uploadBlob(InputStream inputStream, String filename);
 /**
  * returns the file as a byte[]
  * @param blobKey
  * @return
  */
 public byte[] getBlob(String blobKey);
 
 /**
  * Deletes file form the directory
  * @param blobKey
  */
 public void deleteBlob(String blobKey);
 
 /**
  * get all files from the directory
  * @return
  */
 public List<FileBean> getBlobs();
}


BlobServiceImpl.java is the implementation for BlobService

package com.dvmr.poc.service.impl;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.CountingInputStream;

import com.dvmr.poc.bean.FileBean;
import com.dvmr.poc.service.BlobService;
import com.dvmr.poc.util.PropertyFileLoader;

/**
 * 
 * @author vreddy.fp
 *
 */
public class BlobServiceImpl implements BlobService {

 private PropertyFileLoader propertyFileLoader = PropertyFileLoader.getInstance("config");

 public long uploadBlob(InputStream inputStream, String filename) {
  Writer output = null;
  CountingInputStream countingInputStream = null;
  long filesize = 0;
  try {
   // if uploading form IE it get complete path
   filename = FilenameUtils.getName(filename);
   output = new FileWriter(new File(getDirctoryLoation()+ filename));
   countingInputStream = new CountingInputStream(inputStream);
   IOUtils.copy(countingInputStream, output);
   filesize = countingInputStream.getByteCount();
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   IOUtils.closeQuietly(countingInputStream);
   IOUtils.closeQuietly(output);
  }
  return filesize;
 }

 /**
  * 
  */
 public byte[] getBlob(String blobKey) {
  File file = new File(getDirctoryLoation()+ blobKey);
  byte[] docStream = null;
  try {
   docStream = FileUtils.readFileToByteArray(file);
  } catch (IOException e) {
   e.printStackTrace();
  }
  return docStream;
 }

 public void deleteBlob(String blobKey) {
  FileUtils.deleteQuietly(new File(getDirctoryLoation()+ blobKey));
 }

 /**
  * 
  */
 public List<FileBean> getBlobs() {
 
  List<FileBean> list = new ArrayList<FileBean>();
  Iterator<File> files = FileUtils.iterateFiles(
    new File(getDirctoryLoation()),
    getValidFileExtentions(),
    false);

  while (files.hasNext()) {
   File file = files.next();
   FileBean fileBean = new FileBean(
     file.getName(), 
     file.length(),
     file.getAbsolutePath(), 
     FilenameUtils.getExtension(file.getName()));
   list.add(fileBean);
  }
  return list;
 }

 public String getDirctoryLoation() {
  return propertyFileLoader.getValue("directory.location");
 }

 public String[] getValidFileExtentions() {
  return propertyFileLoader.getValue("valid.file.extentions").split("\\|");
 }

}

PropertyFileLoader.java is Util class to loads config.properties file. This file as the Directory location to where the files are written and displayed.

package com.dvmr.poc.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import org.apache.commons.io.IOUtils;

/**
 * 
 * @author vreddy.fp
 *
 */
public class PropertyFileLoader {

 private static PropertyFileLoader instance = null;
 private static final String PROPERTIES_FILE = ".properties";
 Properties properties = null;

 
 public PropertyFileLoader() {
  super();
 }
 
 public static PropertyFileLoader getInstance(String name) {
       if(instance == null) {
          instance = new PropertyFileLoader(name);
       }
       return instance;
    }

 public PropertyFileLoader(String name) {
  loadProperties(name);
 }

 public void loadProperties(String name) {
  properties = new Properties();
  InputStream in = this.getClass().getResourceAsStream("/com/dvmr/poc/resources/" + name + PROPERTIES_FILE);
  try {
   properties.load(in);
  } catch (IOException e) {
   e.printStackTrace();
  }finally{
   IOUtils.closeQuietly(in);
  }

 }
 
 public String getValue(String key){
  return properties.getProperty(key);
 }
}


config.properties file is defined in com.dvmr.poc.resources package.

directory.location=C\:\\temp\\logs\
valid.file.extentions=gif|jpg|JPG|png|txt|jpeg

fileutil.jsp file uses JQuery for JSOP, SlickGrid for to list the files in grid and jquery.form.js plugin to upload files using ajax. Copy necessary plugin files including css and image files to your web application.

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%
 String path = request.getContextPath();
 String basePath = request.getScheme() + "://"
   + request.getServerName() + ":" + request.getServerPort()
   + path + "/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
 <head>
  <base href="<%=basePath%>">

  <title>My JSP 'fileutil.jsp' starting page</title>

  <meta http-equiv="pragma" content="no-cache">
  <meta http-equiv="cache-control" content="no-cache">
  <meta http-equiv="expires" content="0">
  <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
  <meta http-equiv="description" content="This is my page">
  <link rel="stylesheet" href="css/slickgrid/slick.grid.css" type="text/css" media="screen" charset="utf-8" />
        <link rel="stylesheet" href="css/smoothness/jquery-ui-1.8.5.custom.css" type="text/css" media="screen" charset="utf-8" />
  <link rel="stylesheet" href="css/slickgrid/examples.css" type="text/css" media="screen" charset="utf-8" />
 </head>

 <body>
  <h3>Directory Browser that displays only (gif, jpg, JPG, png, txt, jpeg)</h3>
  <table width="100%">
  <tr>
   <td valign="top" width="50%">
    <div id="myGrid" style="width:600px;height:500px;"></div>
   </td>
  </tr>
  </table>
  <hr>
  <h3>Upload file (Uses Iframe)</h3>
  <form id="myform" action="services/document/upload" method="POST" enctype="multipart/form-data">
   <div id="fileSection">
    File:
    <input type="file" name="fileup0" />
   </div>
   <input type="submit" value="Upload file" />
  </form>


 </body>
 
     <script language="JavaScript" src="lib/jquery-1.4.3.min.js"></script> 
  <script language="JavaScript" src="lib/jquery-ui-1.8.5.custom.min.js"></script> 
  <script language="JavaScript" src="lib/jquery.event.drag-2.0.min.js"></script> 
  <script language="JavaScript" src="lib/jquery.form.js"></script>
        
        <script language="JavaScript" src="javascripts/slickgrid/slick.core.js"></script> 
  <script language="JavaScript" src="javascripts/slickgrid/slick.editors.js"></script> 
  <script language="JavaScript" src="javascripts/slickgrid/slick.grid.js"></script> 
 <script>
 $(function() {
  loadGrid();
  ajaxFileUpload();
  downloadFile();
  deleteFile();
 });
 
 
 function downloadFile(){
  $(".download-file").click(function(event) {
   event.preventDefault();
   if ($("#downloadFrame").length == 0) {
    $('<iframe id="downloadFrame" style="display:none;" src="about:none"></iframe>').appendTo('body');
   }
   $("#downloadFrame").attr("src", $(this).attr("href"));
  });
 }
 
 function deleteFile(){
  $(".delete-file").live("click", function(event){
    event.preventDefault();
    $.getJSON($(this).attr("href"), function(vals) {
      loadGrid();
  });
  });
 }
 
 function ajaxFileUpload(){
  function cb_success (rt, st, xhr, wf) {
     loadGrid();
     $('#myform').resetForm();
  }
  var options = {
         success: cb_success,
         dataType: 'html',
         contentType: 'text/plain',
         method: 'POST'
     };
     $('#myform').ajaxForm(options);
 }
 
 function loadGrid(){
   var grid;
  var data = [];
  var downloadFileFormatter = function(row, cell, value, columnDef, dataContext) {
      return "<a class='download-file' href='services/document/download?blobKey=" + dataContext["name"] + "'>Download</a>" +
      "&nbsp;<a class='delete-file' href='services/document/delete?blobKey=" + dataContext["name"] + "'>Delete</a>";
  };
  var columns = [
   {id:"download", name:"Actions", formatter:downloadFileFormatter, width:110},
   {id:"name", name:"Name", field:"name", width:120, cssClass:"cell-title"},
   {id:"size", name:"Size", field:"size"},
   {id:"url", name:"Path", field:"url", width:200},
   {id:"contentType", name:"Type", field:"contentType", width:50}
  ];
 
  var options = {
   enableAddRow: false,
   enableCellNavigation: true
  };
  
   $.getJSON("services/document/list?timire="+Math.min(100, Math.round(Math.random() * 110)) ,  function(vals){
                $.each(vals, function() { 
                    data.push(this); 
                }); 
                grid = new Slick.Grid($("#myGrid"), data, columns, options); 
            }); 
 }
</script>
</html>

Source code is available @ GitHub finally :-)

PF