Let Your Backbone Slide – Extending RESTful web services

,

Backbone.js provides a very flexible framework for building JavaScript applications that interact with web services. Models and Collections serve to represent easily represent data entities, with operations to create, read, update, and delete. This set of operations – summarized as ‘CRUD’ – is very common to see in web applications.

How, though, do you interact with web services that provide more than just CRUD functionality? RESTful web services can certainly offer more than just CRUD operations, and application requirements may dictate such operations, so the Backbone.js Models and Collections will have to be modified or extended accordingly.

In this article, I’ll go over an example of how to use Backbone.js to communicate with some simple web services that provide CRUD functionality, or ‘endpoints’ along with some non-CRUD endpoints. Additionally, I’ll share some ideas on how to keep these endpoints organized in the Backbone.js Models and Collections, which helps keep the code and application self-documenting.

A blog post is a great example of an entity that could have CRUD endpoints, as well as additional ‘verbs’; you create new blog posts, read from the server to provide them to a reader or editor, update them with edits, corrections, or progress, and perhaps delete them. All blog posts should start as drafts, so there’s a need to publish (and unpublish) them, which is where we start to deviate from the standard web services and need some additional functionality from Backbone.js.

Let’s go ahead and define our blog post:

var BlogPost = Backbone.Model.extend({...});

Voila! Now, our CRUD operations are provided by Backbone.js:

Create (HTTP POST)

var blogPost = new BlogPost();
blogPost.set("title", "My First Post");
blogPost.save();

Read (HTTP GET)

blogPost.fetch();

Update (HTTP PUT)

blogPost.set("content", "Lorem ipsum something something");
blogPost.save();

Delete (HTTP DELETE)

blogPost.destroy();

As an aside, most Backbone.js operations assume that a Model is part of a Collection, which is how it provides the URL of the corresponding RESTful web service. For the sake of brevity, I’ve omitted the Collection operations. If you’d like more detail, the Backbone.js documentation is absolutely outstanding, and even includes annotated source code for a deeper dive.

Now, let’s define the web service that will satisfy these requests. We’ll use ‘services’ as our root path parameter and ‘blogposts’ to represent our Collection of blog posts.

Create (HTTP POST)

/services/blogposts

Read (HTTP GET)

/services/blogposts/{id}

Update (HTTP PUT)

/services/blogposts/{id}

Delete (HTTP DELETE)

/services/blogposts/{id}

Referencing the Collection again, a GET request to /services/blogposts would return all of the blog posts. This Collection would give us access to the individual blog post Models and provide the URL for the model to interact with the web services.

As you can see, the requests have an almost identical URL, with the Create operation being the exception. With the blog post’s unique ID provided in the URL, the indication is that we’re operating on a unique entity now, a single Model – our blog post. It’s logical that any operation performed on a single blog post must have an ID in the URL, followed by the action to be performed.

Let’s use ‘publish’ and ‘unpublish’ as our verbs that describe the additional operations that we’re going to perform on our blog post.

Since we’re modifying (Updating) the model, the request should be defined as:

Update (HTTP PUT)

/services/blogposts/{id}/publish

Now, the issue becomes clear; Backbone.js doesn’t know about our custom endpoints. A Model’s ‘url’ property is provided by its Collection, but can be overridden to allow for the functionality we must provide. Let’s define a function that will allow us to access our publish and unpublish web services:

publish: function() {
 this.url = this.collection.url + "/" + this.id + '/publish';
 this.save();
}

In the above function, we reference the collection’s URL – ‘services/blogposts’ along with the model’s id. Our custom endpoint, ‘/publish’, is then appended to the URL.

This isn’t the cleanest way to achieve this functionality – we’re keeping text literals in functional code, and this pattern would have to be replicated for each custom endpoint. In a large application, that may be dozens or hundreds of times. Also, since we’ve overridden the model’s url field, any future requests would go to our custom endpoint.

Now is when the flexibility of Backbone.js really shines – we can customize the ‘url()’ function to work with our custom endpoints, which we’ll declare in a member object:

endpoints: {
 PUBLISH: '/publish',
 UNPUBLISH: '/unpublish'
}

We’ll now modify the url() function of the model to append an endpoint (if set), and add a getter and setter for the current endpoint variable, and reset the endpoint when the sync is finished:

var BlogPost = Backbone.Model.extend({
url: function() {
 var base =
 _.result(this, 'urlRoot') ||
 _.result(this.collection, 'url') ||
 urlError();
 if (this.isNew()) return base;
 // Add the current endpoint to the url provided
  return base.replace(/([^\/])$/, '$1/') + encodeURIComponent(this.id) + this.getCurrentEndpoint();
},
setCurrentEndpoint: function(endpoint) {
 this.currentEndpoint = endpoint;
},
getCurrentEndpoint: function() {>
 if (this.currentEndpoint) {
  return this.currentEndpoint;
 }
 return "";
},
sync: function(method, model, options) {
 // sync stuff here
 ...
 this.setCurrentEndpoint("");
}
...
});

Now our Model has a much simpler time accessing a custom endpoint:

publish: function() {
 this.currentEndpoint = this.endpoints.PUBLISH;
 this.save();
}

This pattern makes our Models and Collections much easier to contain, and since we’ve integrated our custom endpoint functionality in Backbone.js’ base Model (rather than our own), it’s available to every Model and Collection we create.

A comprehensive organization of web services can offer great ‘readability’ of an application; the API should tell a story. It may not always be efficient or effective to give every action required a CRUD endpoint; following a sensible progression in URL endpoints or path parameters will give those using the API a better idea of what to expect in return. Similarly, when the Backbone.js Models and Collections are implemented to match, their interactions with the web services are clear, both to a new developer and one that hasn’t seen the code in 6 months.

There are many ways to organize RESTful web services depending on the needs of the client, the server, and the application. It may not always be convenient or useful to create unique CRUD web services for every operation required for an application, so some ‘overloading’ of the models/entities to provide access to non-CRUD endpoints may be an elegant solution. With the flexibility provided by Backbone.js, it is entirely possible to modify the Models and Collections to interact with a set of RESTful web services, regardless of the architecture.

Liferay Vs. SharePoint: Who is using these technologies?

, ,

Portals continue to evolve as platforms gain new features that increasingly blur the boundaries between portals and areas such as content management. Customer experience, customer engagement, digital experience and marketing integration have been a large focus of portal platforms for the past couple of years as more and more enterprises have embarked on portal implementations. Today we will examine Liferay Vs. Sharepoint

Earlier this year, Gartner released its latest Magic Quadrant for horizontal portals. Microsoft SharePoint and Liferay were both named in the top 5 for leaders in horizontal portals.   But, who exactly is using Liferay and SharePoint and who are some of their top global customers? Below is a brief summary on the customers and industries using the Liferay and SharePoint platforms.

Liferay – who is using it?

Liferay is the leading Open Source portal server.  Many enterprises are using Liferay to build robust business solutions that deliver long-term value and results.  The company has seen a recent rapid growth in the past few years.  Liferay is an all-in-one enterprise portal with broad product capabilities that provide a user-friendly interface where you can centralize, share and collaborate.

Liferay has proven its real world performance globally with many clients across many diverse industries and business functions. It has been used in just about every industry around the world including automotive, education, government, healthcare, financial services, IT and Hi-Tech, media and entertainment and more.  It is primarily used for corporate websites, intranets and extranets but is highly scalable and easy to launch with many out of the box features.  Major organizations around the world choose Liferay for a wide variety of business functions beyond the traditional portal:

  • Intranet portals
  • Extranet portals
  • Content and Document Management
  • Web publishing and shared workspaces
  • Enterprise collaboration
  • Social networking
  • Enterprise portals and identify management

Liferay is growing year over year, and has over 150,000 community members, 5 million downloads, over 500 apps in Liferay Marketplace, and 650 employees.

Some of Liferay’s key customers include:

 

Liferay Clients

Learn more about their case studies and the enterprises using Liferay across industries and around the world.

SharePoint – who is using it?

SharePoint’s usage is widespread because of its complex collaboration structure. The platform allows you to develop your business collaboration solutions fast and effectively.  Similar to Liferay, SharePoint’s customers are spread globally across just about every industry including retail, education, transportation and more.

According to Microsoft, SharePoint is adding approximately 20,000 SharePoint users every day.  That is approximately 7.3 million new SharePoint users every year. Similar to Liferay, the majority of customers use SharePoint as an internal tool; intranet/extranets and enterprise content and document management.

Here are the 5 most common uses of SharePoint:

  • Intranet portals
  • Extranet portals
  • Enterprise content and document management
  • Public facing websites
  • Forms & workflow

Some of Sharepoint’s key customers include:

Sharepoint Clients

Check out some of SharePoint’s case studies here.

Which portal you choose depends entirely on your industry, and what tasks and objectives you are looking to accomplish.  In a previous article, we took a look at some Alternatives to SharePoint.

Question:  What portal technology are you using for your business?  Are you satisfied with it? If not, what frustrates you about your portal technology?  Share your experiences below. 

Top 5 Application Servers for Liferay Deployments

,

We often get asked by new Liferay customers, “What application server should we deploy Liferay on?”. Our answer always starts with, ”What are you using today?”.   If your organization already runs applications using a Java stack then there’s a good chance you can leverage that experience when building out your Liferay environment.

That said, here are our top five application servers for Liferay deployments:

1. Tomcat 7.0

Tomcat is an open source web server and a supported Liferay application server developed by the Apache foundation. Tomcat powers numerous large-scale, mission-critical web applications across a diverse range of industries and organizations. There’s a good chance it is running applications you are using on the Internet daily. The Tomcat application is lightweight, reliable and does its job well.

Veriday has been running Liferay on Tomcat for over five years. It has become our go-to server for new deployments.

2. JBoss 7.1 AS

JBoss is an open source application server developed by RedHat. It complies strictly with the Java EE 6.0 Web Specification and OSGi Core 4.2. If a full J2EE stack has appeal or your organization is already using JBoss internally, then it is a very good choice. This is also a support Liferay application server.

3. Websphere 8.5

4. Weblogic 12c

IBM’s Websphere and Oracle’s Weblogic are the big guns in the Java application server world. They do their job very well but they don’t come cheap. If you’re using them, then you likely have good reasons and likely aren’t looking for change. Liferay fully supports both Websphere and Weblogic environments.

5. Glassfish v3.1

Glassfish is an open source application server originally developed by Sun and now sponsored by Oracle. It’s a solid choice if you’re already using Glassfish, however, its future is gloomy.  Glassfish application server wouldn’t be Veriday’s top choice for new Liferay deployments.

A note about bundles.

Liferay is available bundled with Tomcat, JBoss and Glassfish. These bundles simplify the process of installing, configuring and running Liferay. Keep this in mind when selecting a target application server for your Liferay installation.

Application servers supported by Liferay but not making our top list include Resin, Tcat, tcServer, JOnAS as well as older versions of our top 5 picks. Your businesses experience, existing infrastructure and support needs might lead you to one of these options.

Of course, we’re always available for support in your decision making process and designing your Liferay target Architecture. From conceptual planning to implementation to technical support, we have your back when it comes to making your next online project a milestone success.

Leveraging Liferay’s Scripting Console

,

Recently, we were faced with a challenge. We were trying to add a new page to Liferay with a specific name friendly URL but when we went to add the page we saw an error indicating the URL was already in use.

Screen Shot 2014-11-12 at 9.36.41 AM

This particular site has hundreds of pages and the friendly URL didn’t appear to match any existing pages. We spent a few minutes clicking through trying to locate the conflicting page without any luck. We followed the link lead to a PDF on the site but the page name used to configure it still wasn’t obvious. We needed a better approach to solve this.

Enter Liferay’s scripting console.

Screen Shot 2014-11-12 at 9.39.04 AMIn version 6.0, Liferay added a scripting console to the Server Administration section of the control panel. This is a powerful tool that we frequently use during development, debugging and prototyping.  This was the perfect place to run a quick query to figure this out.

We wrote a simple groovy script. Given a friendly URL this script will return the associated page name.

import com.liferay.portal.service.LayoutLocalServiceUtil

friendlyURL = ‘/third-quarter-report’

groupId = 10182

boolean privateLayout = false;

layout1 =

LayoutLocalServiceUtil.getFriendlyURLLayout(groupId, privateLayout, friendlyURL)

out.println(layout1.getFriendlyURL() + ‘ : ‘ + layout1.getName());

Screen Shot 2014-11-12 at 9.58.33 AM

We ran the script, identified the conflicting page and worked with the marketing team to resolve the conflict.

Liferay’s scripting console has uses beyond simple queries. We also use it for:

  • Bulk user maintenance
  • Automating setup and configuration steps such as creating pages, users and roles
  • During development to quickly test Liferay APIs and verify results
  • As a rapid prototyping tool during development
  • Scripting repetitive operations and maintenance tasks
  • More complex queries to identify and resolve issues

The scripting console is a powerful feature within Liferay and shouldn’t be overlooked. For more information refer to:

Was this information useful? Share your comments below. 

Backbone.js Patterns: User notification system

,

At Veriday, we have been using Backbone.js to build rich web applications for a few years now. During this period we developed different patterns to make us more efficient building apps using Backbone.js as well as to enforce certain user experience standards across our applications. In this post, we will talk about our “BaseModel” and how we use it to enforce the same user experience when it comes to messages to the end user.

A traditional Backbone.js model will usually extend Backbone.Model:

Person = Backbone.Model.extend({
        initialize: function(){
            alert("Welcome to this world");
        }
    });

The above is fine for learning and experimenting with Backbone.js, however, as your team and codebase grows you need to have a different pattern for all your application’s models.

var User = BaseModel.extend({
     defaults: {
     },
     initialize: function() {
         BaseModel.prototype.initialize.apply(this, arguments);
     }
});

In our applications, we have a model called BaseModel.js which serves exactly this purpose. When we declare a new model we extend our BaseModel. The above example shows how a “User” model is declared in Veriday’s JavaScript applications. Our BaseModel.js would extend the default Backbone.Model.

First, why should you care about this?

Before we elaborate on this, compare today’s web applications with the ones in the early 2000s. There is definitely richer experiences today across a variety of web applications. It wasn’t like that before, and the mere fact that you could do something online like pay your bills was revolutionary enough. Since the launch of Gmail on April 1st 2004, we started to see richer experiences on the web, we started seeing JavaScript toolkits and full blown frameworks to help us develop these rich experiences. This eventually led to the current JavaScript MVC style frameworks we see today from Backbone.js,  Angular.js, Ember.js, Knockout.js and many more. As JavaScript becomes more of a “first-class” citizen on the web you will start to have the need for implementing common design patterns that have, until recently, been the case only on the back-end. The front-end was an thought that got slapped on later and glued together through a myriad of tricks. So, here’s two reasons why you should care:

  1. Eventually the default Backbone.Model will no longer satisfy your needs and you will need to change it. Modifying the Backbone.js source code is not the right answer for that.
  2. Eventually you might have to introduce new behaviour to all your models. Copying and pasting this new behaviour across all your models is not the right answer for that.

How can we implement subclassing in JS?

Javascript’s inheritance model is prototypical and not class based (like Java). We can still achieve something similar through the pattern we will describe here, and some coding conventions that the team understands and most importantly follow. Even though our BaseModel.js could technically be instantiated, we never do that. The convention is that these Base*.js Models (and we have several of them) should never be instantiated, they just get extended by other instantiable models.

var User = BaseModel.extend({
     defaults: {
     },
     initialize: function() {
         BaseModel.prototype.initialize.apply(this, arguments);
     }
});

We accomplish this  through the JavaScript prototype. In the case for the “User” above, the Backbone.js initialize method for the model is responsible for calling the parent’s initialize method. This gives us the appearance of subclassing and inheritance in JavaScript. All of our models’ that initialize methods contain the:

BaseModel.prototype.initialize.apply(this,arguments)

This is so we can inherit behaviour from the BaseModel.

var BaseModel = Backbone.Model.extend({
	defaults: {
	},
	initialize: function() {
	}
});

Another real world advantage of this approach is when we introduced Backbone-Relational into our models.  We only had to modify our BaseModel and extend the RelationalModel instead like this:

var BaseModel = Backbone.RelationalModel.extend({
	defaults: {
	},
	initialize: function() {

	}
});

How to implement a global notification system in Backbone.js

By global, we mean that each developer should never have to worry about implementing this for their component.  Each component should behave the same way in terms of notifications for success and error messages and finally if/when we ever change how our notification system operates we can control that in one place across the application. This place is the BaseModel.js.

Notification

Above is an example of a success message in Digital Agent. Let’s take a look at how this works. In our BaseModel, we attach several listeners to the different Backbone. Events we would like to listen to and take an action on. Today these are:

this.on("error", this.defaultErrorHandler, this);
this.on("invalid", this.defaultValidationErrorHandler, this);
this.on("sync", this.defaultSuccessHandler, this);
this.on("saving", this.defaultPendingHandler, this);
this.on("deleting", this.defaultPendingHandler, this);

If you are familiar with Backbone.js you might be wondering about the saving and deleting events since these are not Backbone.js events. However, because we have our BaseModel in place, we are able to change some of this behaviour. For example, take a look at this snippet from our BaseModel.sync method.

sync: function(method, model, options){

				...
				var xhr = Backbone.sync(method, model, options);
				xhr.method = method;

				...

				if(method == "create" || method == "update"){
					model.trigger('saving', model, xhr, options);
				}

				else if(method == "delete") {
					model.trigger('deleting', model, xhr, options)
				}

				...

				return xhr;
			},

Basically, we overwrite the sync method with our own.  We still call the original Backbone.sync method but now we can do some other things before or after that. In this case, we trigger new events for when Backbone.js is in the process of saving or deleting something. This is more from a user experience perspective so that you can show different messages when models are being saved or deleted. Without this, you will not be able to differentiate between “sync” events which correspond to the model being synced with the server.

this.message = new Message();
...
this.messageView = new MessageView({
     model: this.message
});
...
this.message.on("change:uniqueId", this.messageView.render, this.messageView);

Also, in our BaseModel we make use of our Message view and model. These are responsible for handling messages that are returned by the server, or client side validation, or other error messages. Since we are in BaseModel.js, this.messageView is also available in all sub models for when we have a need to show the user a message.

Let’s look at the defaultSuccessHandler we wired up to the “sync” event above. We check what the method for the AJAX request was, and based on the method we show an appropriate message. Here, you also see that we use a “defaultMessages” object. This object contains some default text, however again, because it is in the BaseModel, another model is able to provide its own messages. Ex. in the BaseModel a successful save would show “Saved”, however, as you can see in the notification image above our Page model, it can provide its own message with more context around the action i.e. a page was saved.

defaultSuccessHandler: function(model, resp, options){
	...		
	//don't show a success message if we were just fetching from the server
	if(options.xhr.method == 'read'){
		return;
	}
	else if(options.xhr.method == 'create' || options.xhr.method == 'update') {
		this.message.set({
			type: 'success',
			text: this.defaultMessages.success
		});
	}
	else if(options.xhr.method == 'delete') {
		this.message.set({
			type: 'success',
			text: this.defaultMessages.deleteSuccess
		});
	}	
},

This works nicely with Backbone js validation as well since by default validation errors will trigger an “invalid” event which we will also listen to. Now we can show validation as well as errors returned from the back-end in the same way throughout the application.

This was a sneak peek into one of our favourite Backbone.js patterns at Veriday. To wrap this post up:

  1. Always extend your own base model instead of the Backbone.Model. Thank us when your code base crosses  30,000 lines of Javascript and you need to make a big change to all your models.
  2. If you need to overwrite Backbone.js behaviour, always do that in your BaseModel, BaseCollection, or BaseView.

Found this blog post useful? Leave us a note below!

Rich Liferay Applications using Backbone.js and Jersey (Part 2)

,

In part 1 of this series, we described how Veriday builds rich Liferay portlets using Backbone.js. If you missed the first part or are unsure how to integrate Backbone.js into your Liferay then it will be helpful to read Part 1 first.The approach we describe in part 2 allows your team to be highly efficient and iterative by nature while building Liferay portlets (or any web-based software in general). On Digital Agent, we break our teams into groups of 2-3 developers. Usually the ratio of front-end to back-end is 1:1, but in some cases it could also go to 2:1, depending on complexity.

How does this approach improve our team’s agility and efficiency?

This approach will allow both front-end developers and back-end developers to proceed with their work in parallel with zero time wasted waiting on each other to finish their portion.  This allows the other developer to begin working on their section.

JSON as an interface

This requirement is important because it allows the whole team to proceed with their work and tackle each challenge in the most productive way, rather than stitching some scaffolding for the purposes of the development team being able to build.

The first step is for the team to agree on the JSON contract between the front-end team and the back-end team. Here we answer questions such as: 1) what data is needed for this interface and 2) what should the data look like? We always start with what the end product of the front-end experience should be and then work on how to get that data returned in the format that the JSON contract specified.

The Backbone Model & Collection

Below is a code snippet from one of a Backbone model for a “Store”.

define([.. ],
function(..){
     var Store = BaseModel.extend({
         urlRoot: "/stores/",
         getOwner: function(){
               return this.get("owner");
         },
      ....

From the above model we can see that the end point for this model is “/stores”. The corresponding stores collection is:

define(['models/Store'],
    function(Store){
        var Stores = Backbone.Collection.extend({
            model: Store,
            urlRoot: "/stores/",
            initialize: function() { ...

The Jersey End Point

The corresponding collection for stores also has the same endpoint “stores”.

@Path("/stores")
    public class StoreWebservice {
        @Resource(name = "storeService")
        private StoreService storeService;
        @GET
        @Produces(MediaType.APPLICATION_JSON)
        @PreAuthorize("hasRole('Store Owner')")
        public List<StoreDto> get(@Context SecurityContext context) {
            List<StoreDto> result = getStoreService().getAllStores();
            return result;
        }
...

The Jersey web service above defines the corresponding “/stores” endpoint that our Backbone.js model and collections points at. You can also see that the StoreWebservice has access to a “storeService”. This is where different business services can be injected into our JSON API. These other services can also be Liferay services, if needed. A typical pattern we use is to not directly call Liferay services from our web services. We typically wrap Liferay services within our own utility service to ensure Liferay service calls are contained instead of being present all over your application. We also follow this pattern in the front-end where we wrap Liferay Javascript methods with our own JavaScript utility object that contains these calls.

The list of “StoreDTO” that is returned is basically the POJO representation of the Backbone.js model Store.js we showed above.  The JSON object behind Store.js and what StoreDTO.java represents is your “JSON as an interface” contract that our front-end and back-end developers agree on before proceeding.

So, how does this increase team productivity?

At this point, our application is nicely broken up into layers in which people can work in without having to wait for others to complete their section. After agreeing on the JSON interface, a typical sprint will progress where the developers working on the back-end can proceed with implementing the new services and data access methods that will extract the required data. The front-end developers will proceed with creating the Backbone.js models, collections (ex. Store.js and Stores.js), Jersey Webservice (ex. Stojrewebservice) and the Java DTOs (ex. Store.java). The front-end developers will even stub out the different methods of the Jersey Webservice, even just hardcode a valid response.

 @GET
 @Produces(MediaType.APPLICATION_JSON)
 @PreAuthorize("hasRole('Store Owner')")
 public List<StoreDto> get(@Context SecurityContext context) {
     List<StoreDto> result = new ArrayList<StoreDto>();
     StoreDto store1 = new StoreDto();
     store1.setName("My Store");
     store1.setAddress("5450 Explorer Drive, Mississauga");
     store1.setHours("8am-5pm every day except weekends");
     StoreDto store2 = new StoreDto();
     store2.setName("New Store");
     store2.setAddress("100 Main Street West, Hamilton");
     store2.setHours("24/7");

     result.add(store1);
     result.add(store2);

     return result;
 }

At this point, our team can proceed with building out their own areas of the application with little dependency on each other’s components, early in on the sprint.  We push the integration towards the end of the 2 week sprint where we now have iterated a few times over the front-end and back-end and have ironed out any unforeseen challenges. At this point, what is left is for our developers is to wire up the methods that the front-end team defined, in their Jersey classes, to the actual business services that were implemented.

The approach is not perfect but it definetely helps productivity from day 1. The approach allows us to have developers who are passionate about the front-end focus on the front-end, and those who love working on the back-end focus on the back-end. Even our full stack developers can take full advantage of this approach.

Being able to build applications in this style is also a testament to Liferay’s flexibility. Don’t be afraid to bring your own experience to your Liferay stack!

Liferay Portal, a Leader in the Gartner Magic Quadrant

,

As one of Liferay’s proud Canadian partners in portal technology, we were thrilled to see Liferay, provider of the world’s leading enterprise-class, open source portal, announced that it had been positioned by Gartner, Inc. in the Leaders Quadrant of the Magic Quadrant for Horizontal Portals.

Gartner, a leading information technology research and advisory company, placed Liferay in the Leaders Quadrant based on completeness of vision and ability to execute on that vision.

Gartner Magic Quadrant

For more about Liferay, visit www.liferay.com.

About Liferay

Liferay, Inc. is a leading provider of enterprise open source portal and collaboration software products, servicing Fortune 500 companies worldwide. Clients include Allianz, BASF, Cisco Systems, Lufthansa Flight Training, Rolex SA, Siemens AG, The French Ministry of Defense, and the United Nations. Liferay offers Enterprise Edition subscriptions, which provide access to emergency fixes, software updates, 24/7 support SLAs, and subscription-only features. Liferay also offers professional services and training to ensure successful deployments for its customers. Liferay, Liferay Portal, and the Liferay logo are trademarks or registered trademarks of Liferay, Inc., in the United States and other countries.

How to Manage Dozens of Themes?

,

In the world of web applications, there is a clear divide between the front-end (client) and the back-end (server); In the last several years, frameworks have emerged for both areas that offer substantial time savings in development and design. Libraries like jQuery, Backbone.js, and Underscore.js make life in the front-end much easier, and technologies like Spring, Hibernate, and Jersey reduce tedious rework and ease integration in the back-end.

It’s only logical that tools would evolve also for creating stylesheets, which can grow to gargantuan sizes in an enterprise portal environment. Enter LESS (and other CSS pre-processors), which provides JavaScript-like functionality to CSS – the ability to define variables, create functions, and nest rules, which results in being able to write better code, faster. In a Liferay portal with dozens of themes, the time savings achieved by using a pre-processor can grow to be substantial.

Variables

The attention to the styling of a website can often be eclipsed by the attention to the functional specs; how a website *works* is more important than how a website *looks*. If the styles are ignored for too long, however, especially in a Liferay portal environment with lots of themes, performing edits or upgrades can become hard to manage.

LESS allows for the declaration of variables, which greatly simplifies the reuse of colors, dimensions, and properties. Want to change the entire color palette of the site? Change 2 or 3 variables. Want to add a layout for large, widescreen monitors? Add a single variable and re-use logic for containers and columns. Want to change the size of every piece of text on the site? Define a base font-size and scale all other elements from that.

Variables also allow for consistency between themes – common elements like fonts, banners, and logos can be changed across dozens of themes by altering a single variable.

Functions

The use of functions (or mixins) in CSS pre-processors is well-documented; it’s easy to find libraries that will provide multiple vendor prefixes (-moz-, -webkit-, -o-, -ms-) or adjust multiple properties with a single parameter (border-radius, text-shadow). What about a function that will allow you to use different versions of images based on the style of the theme? By passing in parameters like size and color, it’s possible to create themes that are ‘aware’ of their layout and color palette and can provide corresponding images.

Here’s an example of a logo that can adjust its color and width, with a default of 280px:

.logo (@color, @size: 280px){
background:url('../images/logos/example-@{color}-logo-@{size}.png') center center no-repeat;
}

To use this in a LESS file, this function simply needs to appear along with any other CSS properties:

#my-logo {
position:absolute;
top:25px;
left:50px;
.logo("black", 200)
}

This would output a logo with background image source:

‘../images/logos/example-black-logo-200.png’

Again, the use of LESS allows for more efficient, more flexible code that reduces rework, enabling common elements between themes that can easily be changed to match the overall aesthetic of the theme.

Nesting

The benefits of a CSS pre-processor that allows nesting are two-fold. First, it saves time and keystrokes by not having to re-type selectors. For example:

#my-section {
border:none;
background-color:#000;
  a {
  color:#FFF;
  }
}

Is rewritten by LESS into:

#my-section {
border:none;
background-color:#000;
}
#my-section a {
color:#FFF;
}

Second, nesting ensures that all of the style definitions have the proper top-level selector. This is especially important in a portal environment, where there is no guarantee that a given class is not in use. From the example above, if ‘#my-section’ contained all of the edits, there is no chance that another, more specific selector (from either the Liferay portal or the browser styles) will take precedence. Avoiding these conflicting CSS rules is a huge time saver and prevents the front-end team from having to play ‘CSS Detective’ more than necessary.

In conclusion, the addition of a CSS pre-processor to any development environment can be a great quality-of-life improvement by increasing the productivity and consistency of the front-end development team while simultaneously decreasing maintenance overhead. When applied to Liferay portal, a pre-processor can assist in ease of re-use between themes and avoiding collisions and overwrites from existing styles.

Rich Internet Applications Using Backbone.js and Liferay

,

It’s 2014 and your portal needs to get RICH! It’s no longer enough to have a portal that just works and presents information to your end users from multiple different sources. Today, it’s just as important to have a rich and easy to use interface.

The tooling available for the front-end today is the best it’s ever been, so good that the front-end today can finally become a first class citizen on the web. Traditionally, the backe-end influenced how your application’s front-end gets built, what frameworks get used, how the builds and deployments are performed, and so on. In this article I’m going to show you how Veriday super-charged our Liferay portal development practices by using Backbone.js and other front-end tooling.

A little bit of history

Our engineering team at Veriday has been using Liferay for over 7 years now. We have seen Liferay grow from an up and coming player in the enterprise portal space into a best-in-class technology going head to head and winning against incumbents such as Websphere Portal, Oracle Web Logic and Microsoft Sharepoint. 

Hello Backbone.js

Backbone.js is an extremely lightweight Javascript framework with a RESTful JSON interface based on the model-view-presenter design pattern. Today our engineering team has been exclusively using this framework for over 2 years now because it 1) allows us to iterate faster on the front-end and 2) is fairly flexible and integrates well with our web services based architecture.

So far we have used Backbone.js in two different ways. We utilize it when we’re building our products such as MapCMS. We also use it when building Liferay portlets. The pattern we use to integrate it with Liferay portlet diverges from Liferay’s portlet development documentation, but being able to diverge from the patterns described in the Liferay documentation allows us to also bring our own experience and lessons learned to the table.

The hybrid JSF/JSP + Backbone.js approach

We refer to the way we decided to integrate Backbone.js into our portlets the “hybrid” approach. The main reason is we still wanted the portal and portlet infrastructure, but at the same time we wanted the flexibility and richness we gain from single page applications. In this approach we build and deploy our portlet projects in the usual standard way, but the portlet just ends up being a shell for the Backbone application. In this method we also gain the advantage of being able to bootstrap the Backbone application without incurring the delay of performing an initial Ajax request to initialize the portlet. This is a very handy way to provide some contextual information to Backbone, for ex. is there a logged in user or who is the logged in user, or what is the current user’s locale preferences?

How do we load Backbone

So you can’t just use Backbone without drinking the rest of the cool-aid. Before we bring Backbone into the picture, we need to present some other libraries that make things more efficient and easier. The first library we need is Require.js for Javascript module loading and dependency management. Require provides the module ‘import’ mechanism from other programming languages like Java or C for example.

define(
    //The name of this module
    "types/Manager",

    //The array of dependencies
    ["types/Employee"],

    //The function to execute when all dependencies have loaded. The
    //arguments to this function are the array of dependencies mentioned
    //above.
    function (Employee) {
        function Manager () {
            this.reports = [];
        }

        //This will now work
        Manager.prototype = new Employee();

        //return the Manager constructor function so it can be used by
        //other modules.
        return Manager;
    }
);

The Require.js example above shows how it is used to define a module which you can then load using require within your portlets:

require(["some/script.js"], function() {
    //This function is called after some/script.js has loaded.
});

So using the above pattern we can define JavaScript modules, and then load them in asynchronously using Require.js within each portlet’s JSF view or JSP.

What about HTML? Where does that go?

The second part of this puzzle before we get to all the Backbone goodness, is what do we do with our application’s markup? how do we load it? The first thing we decided here is there will absolutely never be any HTML within any JavaScript or event Java code. It’s very important for you to make this decision up front as it will help you avoid a whole lot of headaches as you maintain and enhance your portlets over time.

Now we introduce another library called Underscore.js – this library provides dozens of utility functions that we will need. One of these is the _.template() function.

define([
    "text!templates/map-store-result.html",
], function(StoreResultTemplate){
...
renderStoreResult: function(store){

                var templateHtml = _.template(StoreResultTemplate, {
                        store: store
                    }
                );
                this.$el.find("#location-result").html(templateHtml);

            },
...

In the example above we use Require to load a plain simple html file called map-store-result.html, and we use Underscore’s template method to parse the template and populate it with values – ex. a “store”.

<h3>{{store.getStoreName()}}</h3>
<div class="span6">
    Dealer: {{store.getOperatorName()}} <br />
    Phone: {{store.getStorePhone()}} <br />
    Fax: {{store.getStoreFax()}} <br />
    Auto Service: {{store.getStoreAutoService()}}
</div>
<div class="span6">
    {{store.getStoreAddress()}}
</div>

The above HTML snippet is our template code referencing different attributes of a “store”.

Let’s take a look at some Backbone.js already

We now have all the pieces of the puzzle and can get Backbone loaded into a Liferay portlet, we know how to load our modules, and finally  we also know where our actual application markup will live.

Models and Collections

Backbone provides the basis for models and collections that will store your data on the front-end, communicate with your back-end web service endpoints, and provide you with a mechanism to build event-driven front-end applications.

Views

The last piece is the Backbone View which handles all the front-end logic and business rules. View respond to user actions such as clicks, manage models on the front-end and synchronize them with the back-end. A typical view would 1) fetch some models or collections from your back-end, 2) allow the user to update the model and finally 3) send the model to the back-end to get saved all while keeping the actual view in sync with the model.

Event Driven User Interfaces

The key to a successful view pattern is to fully embrace event driven development. One pattern we use, is we introduce a “dummy” model for the client’s state. We then use that model to track and listen to state changes. The end result is a completely event driven. The event-driven approach also allows us to easily re-wire the events and callbacks to create a completely different user experience at a reduced effort.

var DocumentView = Backbone.View.extend({

  events: {
    "dblclick"                : "open",
    "click .icon.doc"         : "select",
    "contextmenu .icon.doc"   : "showMenu",
    "click .show_notes"       : "toggleNotes",
    "click .title .lock"      : "editAccessLevel",
    "mouseover .title .date"  : "showTooltip"
  },

  render: function() {
    this.$el.html(this.template(this.model.attributes));
    return this;
  },

  open: function() {
    window.open(this.model.get("viewer_url"));
  },

  select: function() {
    this.model.set({selected: true});
  },

  ...

});

The above code sample illustrates how simple it is to define an event-driven view. Furthermore, by simply altering the event callbacks or trigger we can easily  change the user experience in our Liferay application.

Liferay is a powerful platform for deploying your rich applications on to, it is also pretty flexible in how you build your applications so don’t be afraid to diverge from their tutorials and documentations and include your own technologies and frameworks; especially when it comes to your portlet’s front-end.

Liferay Accelerates Mobile Application Development

, , ,

Today, Liferay Inc., a leading open source portal software company announced the release of a Mobile SDK that will ship with Liferay Enterprise Edition 6.2. You can read about all the technical benefits here, but, so what does this mean from a business standpoint? Mobile application development isn’t a new concept and for the most part, major industries, like financial services, have figured out a way to get to market with mobile apps either through the use of partners or through their internal capabilities. So, the process of creating mobile apps already exists. How does this move by Liferay change your world and is this relevant?

It’s quite obvious that investments in mobile technologies are increasing year over year and month over month due to the ubiquity of smartphone and tablet usage. In short, user experience and adoption are driving investments in mobile application development. In fact, mobile internet usage is expected to exceed desktop usage in 2014. With this in mind, overtime, your user base will increasingly expect more than just default mobile views of your application, they’ll start to expect mobile application functionality and much like how you’ll lose business with a terrible looking website, you’ll start losing your users with poor mobile user experiences.

So, what happens now? What happens now with no mobile SDK? In short, redundancy. Building a rich internet application, followed by the implementation of a mobile application across multiple devices can only be streamlined to a point, for example, at the database layer. This redundancy results in higher exponential costs for design, development and testing and much longer development cycles. Not a good combination if you’re striving to create amazing user experiences.

With the mobile SDK and beyond, Liferay will continue to create and add to the plethora of services that can be consumed in a mobile application context. And the more shared services, content & collaboration features available to you when you build your applications, the less redundancy you’ll encounter and the quicker you’ll be able to get to market with a mobile version of your applications.

This is an extremely positive announcement from Liferay and aligns very closely to our lean development principles. For us and our customers, it means we can extend the benefits of our development practices to mobile and accelerate the release of those applications even faster and most cost effectively by using Liferay as a central application hub.