Uploading file: HTML5, BackboneJS and RESTFul services

In my previous post, I have introduced the sample application Account Manager. In this new post I want to describe implementation details of a functionality aimed at uploading the account’s picture.

uploading

The starting point is the html page (in my architecture it is not a complete html page but a section of the entire page due to Underscore JS templating feature).

The first step is to declare an input tag of type = file, that defines a file-select field and a “Browse” button for file upload:

<input id="fileInput" type="file" name="fileInput">

To give Bootstrap style to input element (the actual release of Bootstrap doesn’t support this element yet) , I have used a custom style. More details here.

The result is the input is sorrounded by span element with specific styles:

<span class="file-input btn btn-block btn-primary btn-file">
  <input id="fileInput" type="file" name="fileInput">
</span>

The next step is to send the file to the RESTFul service for uploading. In the html page, I haven’t used the <form> tag and a button to submit the form/request (the input element is not inside a form element). For this purpose, I use a new feature of HTML5, that is FormData object. The data submit is done via JQuery.

The FormData object is one of the enhancements to XMLHttpRequest.  With the FormData object, you can create and send a set of key/value pairs and, optionally, files using XMLHttpRequest. When using this technique, the data is sent in the same format as if you’d submitted it via the form’s submit() method with the encoding type of multipart/form-data.

Let’s have a look at the code.

In my Backbone .js file for account’s details page, I have created a function saveFile:

saveFile: function() {
  var picture = $('input[name="fileInput"]')[0].files[0]; 
  var data = new FormData();
  data.append('file', picture);
  $.ajax({
    url: 'rest/accounts/upload/'+this.model.get('picture'),
    data: data,
    cache: false,
    contentType: false,
    processData: false,
    type: 'POST',
    success: function(data){
      $('#loadingModal').modal('hide');
    },
    error: function(data){
      alert('no upload');
      $('#loadingModal').modal('hide');
    }
  });
},

The first thing is to retrieve the file uploaded and attached to the input element:

var picture = $('input[name="fileInput"]')[0].files[0];

Since you can upload more than one file, (I have implemented a check on number of file because you can upload only one picture a time for an account) I know the picture is at position zero of files array.

Next, I create a new FormData object and append the picture file as key/value data:

var data = new FormData();
data.append('file', picture);

Finally, I call the RESTFul POST method service, to save the picture on the server, via Ajax passing the FormData object:

$.ajax({
    url: 'rest/accounts/upload/'+this.model.get('picture'),
    data: data,
    ...
    type: 'POST',
    ...
});

Before calling the saveFile function, I do something on creating an unique filename for the picture that will be persisted on the server. So after browising and selecting the image file I create the filename using a timestamp

var filename = 'pictureId' + $.now() + '.' + this.getFileExt();

and getting the file extension with my function getFileExt:

getFileExt: function() {
 var files = $('input[name="fileInput"]')[0].files;
 var ext = null;
 if(files[0] != null){
  var filename = 
      files[0].name.replace(/\\/g, '/').replace(/.*\//, '');
  ext = filename.replace(/^.*\./, '').toLowerCase();
 } 
 return ext;
 },

and then I set the picture attribute value for the Backbone model, so it will be persisted in the field PICTURE of MySQL table ACCOUNT:

this.model.set("picture", filename);

so when the upload Rest service is called I can get the parameter filename with

url: 'rest/accounts/upload/'+this.model.get('picture'),

At this point, the picture file is going to be managed by RESTFul service:

@POST
@Path("/upload/{filename}") 
@Consumes("multipart/form-data")
public Response uploadFile( @PathParam("filename") 
                            String filename,
                            MultipartFormDataInput input) {
 String file = ""; 
 Map<String, List<InputPart>> uploadForm = 
                              input.getFormDataMap();
 List<InputPart> inputParts = uploadForm.get("file"); 
 for (InputPart inputPart : inputParts) {
   try {
      InputStream inputStream = 
                  inputPart.getBody(InputStream.class,null);
      byte [] bytes = IOUtils.toByteArray(inputStream);
      file = Consts.BASE_PATH_FILE + File.separator + filename; 
      writeFile(bytes,file);
   } catch (IOException e) {
      e.printStackTrace();
   }
 } 
 return Response.
        status(200).
        entity("Uploaded file name : " + file)
        .build(); 
}

The service accepts MIME media types multipart/form-data (value required when you are using forms that have a file upload control) and has one parameter that is the file name. The method gets the form data map and retrieve the file with the same key “file” used in data.append(‘file’, picture).

The remainder is to get an input stream and an array of bytes and to write the file in a path on the server. In my case, the path is the data directory on JBoss AS, retrieved with system getProperty:

Consts.BASE_PATH_FILE = 
       System.getProperty("jboss.server.data.dir");

The writeFile method is:

private void writeFile(byte[] content, String filename) 
throws IOException { 
  File file = new File(filename);
  if (!file.exists()) {
    file.createNewFile();
  }
  FileOutputStream fop = new FileOutputStream(file);
  fop.write(content);
  fop.flush();
  fop.close(); 
}

So far, I have uploaded the picture on the server, let’s see how to retrieve the picture when you visit the account detail page.

It is very simple, we use a RESTFul service calling it from scr attribute of  html img tag with the parameter picture of the backbone model, saved before file persistence:

<img src="<%= 'rest/accounts/picture/' + picture %>"/>

The REST service is:

@GET
@Path("/picture/{picturename}")
@Produces("image/png")
public Response getFile(@PathParam("picturename") 
                        String pictureName){
  String fileName = Consts.BASE_PATH_FILE + 
                    File.separator + pictureName;
  File file = new File(fileName);
  ResponseBuilder response = Response.ok((Object) file);
  response.header("Content-Disposition", 
                  "attachment; filename=image_from_server.png");
  return response.build();
}
Advertisements

A Sample Web Application with Twitter Bootstrap, Backbone JS, RESTFul and J2EE/JPA backend.

In this post, I want to share with you my passion for cutting-edge web technologies and I want to demonstrate how to build modern full-stack web applications with lightweight frontend layer (entirely built up with Javascript and HTML techs), RestFul web services and J2EE/JPA backend.

Inspired by Christophe Coenraets‘ blog that I usually follow and read, I have decided to make my own app realizing the Java Backend that it is not still implemented in Christophe’s sample app Employee Directory.

To do this I have created an application called Account Manager. Do you know how many username and passwords you need to remember for each internet service and social network account ? Well,  the aim of this sample app is to organize your internet account data ( name, username, password, etc. ) in a good-looking web app, far away from desktop and old-style applications.

This is a sample app so I have overlooked security and cryptography topics ( like hashing of password, etc.)  on purpose.

You can run an hosted version of the application on my OpenShift server @

http://accountsmanager-ccarella.rhcloud.com

and you can find the source code on my GitHub repository @

https://github.com/carminecarella/Accounts_Manager

Some screenshots of Account Manager. The application consists of an home page,

accmansc1

a page Accounts with the list of accounts with a subset of information displayed and pagination too,

accmansc2

for each account, a detail page where you can modify account’s data, upload a picture and delete the account itself.

accmansc4

Technology Stack

The technology stack used in this app is showed below:

setoftechs

Some considerations:

  • A front-end layer essentially built up with Javascript  is inclined to a lack of structure in the code and it doesn’t take long before it becomes a mess. For this reason, MVC Javascript frameworks (like Backbone JS or Angular JS ) give us help to structure your code (making it more readable)  and to make your app more flexible.
  • The powerful abstraction that RestFul services provide, let you to completely separate the back-end layer from front-end one. Moreover, Backbone JS lets to connect it all to your existing API over a RESTful JSON interface in a simple way.
  • As ORM framework I have chosen to use JPA with Hibernate implementation. In my code you will see that I use generic JPA API to write queries in order to not tie the database layer to a specific implementation. In this way, you can switch easily from Hibernate to Oracle TopLink for istance.

Architecture

In the picture below is showed the full-stack architecture of Account Manager.

arc

Code Highlights

Frontend layer

The front-end layer is built up with Twitter Bootstrap, Backbone JS and Underscore JS. Bootstrap is a front-end framework and I have used it for building a clear and intuitive GUI. Underscore JS helps to use templating for splitting the code on several html pages. Backbone JS is used for managing GUI’s events, navigation between html pages and to communicate with RestFul services and Java backend.

Backend layer

The RestFul classes use the interface a session bean to go down in the stack, and the implementation of these interfaces (the session bean itself) are the unique access point for communicating with the database layer.

In this project is widely used the Dependency Injection pattern. So you will find code like @EJB, for istance, to  let the container performs injection when the component is created.

The interfaces used by RESTFul classes are annotated with @Local annotation.  The meaning of that is to expose the business methods to local clients which are running in same application server. It sounds a good choice for my purpose as the client side and server one are in the same project which runs on the same JBoss AS server.

Next steps

I will came back soon with more posts about implementation details of some functionalities of Account Manager.

Consumers trust earned media more than other forms of advertising.

Recommendations from personal acquaintances or opinions posted by consumers online are the most trusted forms of advertising.

According to Nielsen’s Global Trust in Advertising report (April 2012), which surveyed more than 28,000 Internet respondents in 56 countries, 92 percent of consumers around the world say they trust recommendations from friends and family, above all other forms of advertising, an increase of 18 percent since 2007.Online consumer reviews are the second most trusted source of brand information, with 70 percent of global consumers surveyed online indicating they trust consumer opinions posted online, an increase of 15 percent in four years.The explosion of social networks and Consumer Generated Media over the last few years means consumers’ reliance on word of mouth in the decision-making process, either from people they know or online consumers they don’t, has increased significantly.
Consumers are moving towards user reviews to find honest feedback/opinions on products/services. Moreover, people don’t trust anonymous ratings any more. We trust people we know.
The Consumer Generated Media revolution has forced advertisers to use a more realistic form of messaging that is grounded in the experience of consumers rather than the lofty ideals of the advertisers.In this new age of consumer control, the survey also showed that nearly six-in-10 global online consumers (58%) trust messages found on company websites.

On the Web, four-in-10 respondents rely on ads served alongside search engine results, 36 percent trust online video advertisements, and one-third believe themessages in online banner ads, an increase of 27 percent since 2007.
Sponsored ads on social networks are credible among 36 percent of global respondents.

Display ads (video or banner) on mobile devices such as tablets and smartphones are trusted by one-third of global respondents, which is slightly higher than the reported consumer trust level of text ads on mobile phones (29%). While the reported consumer trust level in mobile phone advertising is still low, it increased 61 percent since 2007 and 21 percent since 2009.
Half of consumers around the world say they trust television (47%), magazine (47%) and newspaper ads (46%), confidence declined by 24 percent, 20 percent and 25 percent, respectively, between 2009 and 2011.
In the figure below, result’s survey for 2012.
Global Trust in Advertising in 2012

Global Trust in Advertising in 2012

In the figure below, result’s survey for 2009.

Global Trust in Advertising in 2009

Global Trust in Advertising in 2009

References: