Top 10 ways to keep up with the Liferay Community

General Blogs October 2, 2014 By James Falkner

At this year's Spain Symposium and North America Symposium (which begins in about 294,682 seconds from now), I'm going to be holding a session on 21 Ridiculously Simple Ways to Contribute to the Liferay Community. In a related development, I've recently heard from several of you recently that you'd missed some interesting news items that happened, and didn't know how best to avoid missing stuff, so as a companion to my talk, I thought I'd also list the Top 10 Even More Ridiculously Simple Ways to Follow the Liferay Community! So here they are:

  1. Subscribe to the Community Blogs. This is probably my favorite, because the most important stuff gets posted here all the time.
  2. Follow @Liferay, @LiferayApps, and "Liferay" (not #Liferay) on Twitter. Also, you may want to filter out the tons of job postings (unless you're looking for a job! Also - we are hiring too).
  3. Setup a Google Alert for Liferay. There are some amazing community members, journalists, and random people that create great content about Liferay, and they aren't always posting to the blogs on this site. 
  4. Subscribe to RSS feeds for Bugs and Feature Requests. Yeah, RSS is dead, I know. Portals are dead. Java is dead. Apple is doomed. 640k ought to be enough memory.
  5. Subscribe to Announcements and the Community Security Team. If you run Liferay CE, you really need to keep abreast of secuity advisories. Or, if you want to drink from the firehose, subscribe to everything.
  6. Follow RSS feeds for our Sourceforge repo. If you had, you'd have seen that the 7.0 Milestone 1 was already out like a month ago (we are planning on more activities around the milestones in the near future!).
  7. Join hangouts every other Tuesday (and subscribe to the calendar). Free workshops every 2 weeks. Good times.
  8. Subscribe to the Releases page, and learn of current and upcoming releases before your friends do.
  9. Lurk on our IRC channel. Several experts hangout there, and many other developers. It's a great way to meet fellow devs.
  10. Subscribe to and listen to Radio Liferay. Olaf has done an amazing job offering up compelling content from a wide range of topics.

How do you keep up with Liferay? Let us know in comments! See you in Boston!

iBeacons and Liferay for Audience Engagement: Part 3

Technical Blogs September 22, 2014 By James Falkner

This blog is part of a series of entries documenting how we are using iBeacons and Liferay to better engage our audiences at events throughout the year. [Part 1] [Part 2] [Part 3]

Update: Check out my new eBook! Finding Your Way Around iBeacons for Event Marketing.

Download the eBook

In Part 1 I introduced the concept of using iBeacons for Audience Engagement and reviewed knowing your audience and the physical space. In Part 2 we took a step down and covered more technical details about beacon programming and management. In this third and final installment we'll discuss how we use Liferay to manage beacon configuration, some anti-annoyance strategies, and a comparison of iOS to Android when it comes to beacons.

With all of your newfound knowledge about how iBeacons work, let's talk about how to integrate them into the Liferay Portal platform.

Liferay Integration

There are many variables to consider when designing an app that will interact with Bluetooth beacons. How many different spaces and times you want to support, the physical size and layout of the space (your local user group meetup, or the World Cup?), what kinds of interactions you wish to have, how crowded the space will be, how many beacons you can get your hands on, and a whole lot more. This means that your beacon configuration is most likely going to be changing a lot, and in some cases will be unknown until you are actually present to do setup. So no hard-coding of beacon identifiers or region names or anything of the sort is allowed!

In addition, as we previously discussed, beacons are pretty dumb - they simply emit a unique code over and over again (you know, like... a beacon). The interesting stuff happens when your app responds with unique and engaging content.

So, your app needs to be able to reconfigure itself on the fly by reading dynamic beacon configuration from a network location and serve unique and engaging content based on user behavior in the field. Of course we would use Liferay, as it does this really well!

Dynamic Data Lists

When you start up the Liferay Events app, it asynchronously downloads its data and beacon configuration from Liferay in the form of Dynamic Data Lists. This Liferay feature allows you to create lists of... dynamic data. You can try this now: access the real, live DDL data using's JSON web services by reading through the "DIY: Liferay Events Hacks" blog!

We needed to massage the data coming out of the DDL a bit (for example, we add a UUID to every returned record to use for internal record keeping in the app, which by default is not present, and we also wanted the date format to be consistent), so we created a very simple plugin on top of the standard DDL service which returns the data from the DDL in a friendlier format using remote JSON web services (if you want to learn how to do this, don't miss tomorrow's session!).

For Liferay events, each event typically gets a separate Site on (we call them 'microsites'). Here's the DevCon microsite. Within each microsite lives the data for the event (as discussed in the DIY blog), including beacon configuration described below.

We designed 4 different dynamic data lists to hold the beacon config for each event to support the kinds of interactions we described in part 2 of this blog. Basically, the 4 lists provide beacon region definitions, event definitions, and forms to fill out for certain kinds of interactions.

1. The Beacon Regions List

This list defines the set of beacon regions for a given event. For example, in the Benelux Solutions Forum we had 5 different regions. As you know, each region is defined with an identifier, and one or more of Beacon UUID, Major, and Minor. So that's the schema for this dynamic data list:

  • name - A human-readable identifier that shows up in the app (but is otherwise unknown to the beacons)
  • beacon_uuid - The hardware UUID of all beacons in this region
  • beacon_major - The hardware major number of all beacons in this region (or blank to represent any major number)
  • beacon_minor - The hardware minor number of all beacons in this region (or blank to represent any minor number)
  • muted - a flag that allows event staff to selectively turn off a region for any particular reason

2. The Beacon Region Events List

This list defines the things that can happen based on region actions such as entering or leaving one of the above defined regions. This turned out to be the biggest list compared to the others, because most interactions are based on region entry/exit (which is the only thing your app can detect when it's backgrounded or quit entirely). We had a particularly strong desire for this application to NOT be annoying, so most of the elements below are designed to STOP the app from doing anything! Only those events deemed most worthy make it through the gauntlet of checks represented by the below. So each possible interaction is defined with this schema:

  • region_name - A textual description of the region for which the action should occur (this name shows up in the app as well)
  • on - A 'select' field to define the kind of event for this region - entry or exit.
  • initial_delay - How long to wait after entry/exit before the notification is shown. This allows you to delay the notification (e.g. waiting 10 minutes after entering the Cafe before offering a discounted drink ticket). It also works with the cancelable flag below to avoid transient events and NOT trigger interactions in certain situations.
  • repeat - How many times to repeat this specific notification. No sense in repeating most messages, right? Maybe 1-5 times, but more than that and people get annoyed.
  • min_repeat_period - How long to wait before repeats. If you have a repeating message (e.g. a "Welcome to the sponsor expo, sign in to get your prize" kind of interaction, you would get annoyed if you got that every time you walked in!)
  • cancelable - A flag to indicate that a delayed notification can be cancelled if the user reverses their behavior. See Death Row below.
  • message - the initial message to display (and we have string substitution, for example $SESSION_TITLE and $SPEAKER_NAME so we can show dynamic messages, based on the agenda and time of day)
  • actions - the options to present. Each notification consists of the message and an optional set of actions the user can take. For example, in a "Welcome to the event" message you might want to offer a quick link to the registration desk map, a link to the agenda, or a link to checkin on Foursquare or Twitter, or a form to fill out to register for something. We invented our own simple list syntax here to encode a list of actions into a String, which identifies different kinds of actions (take the user to a specific screen in the app, load a web page, show a document or form, create a tweet that the user can edit and send, etc).
  • preferences_gate - We created this to allow logic to be introduced as part of the gamification design. Preferences can be programmatically set based on user behavior (e.g. filling out a form, finding a mystery object, or completing a game quest), and those preferences can then be checked later on using this field to avoid showing the wrong notification, or duplicate notifications for game elements that have already been completed.
  • start_date/start_time/end_date/end_time - A way to avoid interactions at certain times of the day. For example, you don't want to show a "Come join us after today's sessions for happy hour!" if happy hour took place yesterday.

All of these configurations are designed to filter the interactions to only those that really should show up. In addition, the app also hard-codes a global event frequency limit, so even the most "chatty" event staffers can be thwarted in their plan to fill your notification tray (see below for more detail on anti-annoyance)

3. The Individual Beacon Events List

In addition to region-wide events (entry/exit) we also want some interactions to take place within the context of a specific beacon. The schema is virtually identical to those for region-wide events, but in this case you define the action to occur based on proximity to a specific beacon:

  • beacon_name - The name of the beacon (a human-readable name, e.g. "Mystery Object 5")
  • region_name - The name of the region in which the person must be in for this event to occur. Because beacons can be in multiple logical regions at a given time (remember the overlapping regions?), we wanted some actions to only occur relative to a specific region.
  • beacon_major/beacon_minor - Since this event is specific to a specific beacon, you need to identify it here!
  • on_proximity - How close you have to get to the beacon before triggering the interaction. It's a multi-select field for immediate, near, or far, or any.

The rest of the schema is identical to the schema for Region Events.

4. Beacon Forms

One of the interactive features of the Liferay Events app is the ability to present forms to the user as part of a region or beacon trigger. We used this as part of a "mystery guest" game where attendees would walk around to each sponsor booth and be presented a form, and if they entered the right values they'd be entered into a drawing for a prize. The form is submitted to a special game server which evaluates the answers and returns results (a simple Liferay web service). So in the above event definitions, there is an "Actions" field and one of those actions is to present one of these forms.

  • form_id - The identifier for the form (referenced from the actions list above)
  • title / subtitle / sub-subtitle / intro - These are textual elements at the top of the form (introductory text for describing the purpose of the form)
  • form - The form itself. The syntax here is out of scope for this blog, but it basically allows you to define the fields of the form itself (text fields, text areas, sliders, multi-select fields, etc).
  • content_url - If present, this is a URL to a piece of web content on Liferay to display at the top of the form. Useful for marketing collateral!
  • preferences_on_success - Remember the preferences_gate defined for beacon events? If you successfully fill out the form, these preference_on_success flags are "set". If you fail the form, the preferences_on_fail preferences are set.
  • repeat - How many times to repeat the form. You might only want some forms fill-out-able once.

That's it! Using the above configuration, event staff can create the iBeacon interaction they desire, while avoiding annoyance as much as possible.

Avoiding Annoyance

Each time the app thinks it wants to engage you with an iBeacon notification, it has to pass through a gauntlet of anti-annoyance checks to try to ensure you only get the messages you really should get, without being annoying. If any of these "fail", then nothing happens:

  • Has it been long enough since your last notification? No? Fail.
  • Are you currently busy with a previous notification (e.g. are you in the middle of filling a form?) Yes? Fail.
  • Have you seen this notification enough times already? Yes? Fail.
  • Has it been long enough since you last saw this particular notification? No? Fail.
  • Is it the right day or time of day to show this notification? No? Fail.
  • Have you told us not to show notifications from this location? Yes? Fail.
  • Are all of the possible actions you could take as part of this notification invalid at this time? Yes? Fail.

As you can see, there are many types of anti-annoyance configuration elements (e.g. minimum repeat times, date/time filters, etc) and some built-in logic (e.g. global speed limit) that means you can't get flooded with beeps or vibrations every 10 seconds. It is highly recommended in your applications to avoid annoying users, because they will just get irritated and possibly tell all their friends about it.

Death Row - or how to deal with transient events

Imagine if you set up a "Welcome to the event!" message that shows when attendees first arrive at your event, and you also have a "Goodbye - thanks for attending!" message that should show when attendees leave your event. Now, imagine an attendee arrives at your event, and they get the welcome message. So far, so good. Now, imagine that before the opening keynote they have to make a pit stop at the WC, which is in the basement. While in the WC, your app no longer detects any beacons because you didn't put any there. When the attendee walks out of range of the beacons and into the WC, the app will think that they left the event and issue the "Goodbye" message, and they'd get rather confused and think they entered some kind of time warp to the end of the day. Further, when they return from the WC they might get the "Welcome!" message again! That's not going to do.

So instead of blanketing a space with hundreds of beacons to ensure 100% coverage, the app has a built-in death row. By adding a 15 minute delay (for example) to the "goodbye" message AND setting the cancelable flag , when the attendee goes to the WC, the "Goodbye" message is queued to trigger in 15 minutes, as usual. When the attendee returns from the WC, the "Goodbye" message (which hasn't yet been triggered) is put on a software Death Row. If the attendee remains in the event, the "Goodbye" death sentence is carried out before the timeout expires, and the Goodbye message is "killed" (i.e. not shown). However, if the attendee then turns around and really does leave the event, the Goodbye message is "pardoned", taken off death row, and is allowed to occur after the specified delay.

This is akin to the "double bouncing" effect in electrical circuits. When a switch is closed, there is a momentary bouncing of the electrical signals as the two parts of the switch come together to complete the circuit. This can cause lights to flicker, or multiple forms to be submitted on a website, so logic is needed to wait until the switch is "really" closed with purpose, and this maps perfectly to this scenario - as attendees often "bounce" between indeterminate states (are you in the WC? Or in the event? Are you actually walking into a breakout session, or merely passing by?). Beacon-enabled apps should ensure that user actions (such as walking into a room) are intentional and not transient.


The app deals with data that isn't very sensitive, so if it is compromised, bridges won't fall and lights won't go out. But as a good practice we employed several basic security measures to protect overall integrity:

  • Uses HTTPS everywhere
  • Signed requests when writing data back to web services
  • OAuth for external sites (e.g. Twitter, Facebook)
  • Does not require login; usage is completely anonymous

The event app records a list of beacons your device can see every few minutes while the app runs, and passes this back Liferay, using another simple web service creating using Liferay's ServiceBuilder framework (see Privacy section below for details).

Android vs. iOS considerations

First the software: The app itself is written using Titanium Appcelerator, a hybrid app platform that cross-compiles JavaScript apps to native languages for iOS, Android, Blackberry, and Windows phones. From there, the native SDKs are invoked to create truly native apps that are then uploaded to the various app stores. Titanium does a good job at providing parity between the different platforms, sometimes sacrificing OS-specific features in order to maintain parity, but plugins (called modules) can be written and plugged in to provide access to native APIs. Titanium itself does not know about iBeacons, so we ended up using an open source library for iOS, and for Android we wrote a custom module which wraps around Radius Networks' Android beacon library.

As for the hardware: Both Android 4.3+ and iOS 7.0+ support Bluetooth LE, on which iBeacons are based, but you also need hardware that implements it, such as an iPhone 4S or later, Galaxy S3/S4/S5, Nexus, and many others. There are other differences noted below that we discovered during the last several months, that might help you understand what to expect. We've tested across about 10 different Android devices (out of a possible 8,423 devices) and 7 different iOS devices:

  • Accuracy - winner: iOS. We can confirm reports that iOS does a better job of reporting closer-to-reality proximity information (it also smoothes the data for you).
  • Sensitivity - winner: Android - it can "see" for miles and miles and miles. We think it's because of the built-in smoothing of data in iOS and dealing with transient detection, which is not present (or just not as robust) on Android, which just tells you like it is, without any sugar coating (and we like it that way)
  • Programming Model - winner: iOS. When we started this project, there were no free/libre/open source Titanium modules for interacting with iBeacons on Android, so we wrote one instead, using the awesome Radius Networks' beacon Library. iOS' LocationServices also seemed a more natural and higher-level abstraction than Android's lower-level Bluetooth APIs.
  • Debuggability - winner: Android. Open source. 'nuff said.
  • Backgrounding support - winner: Android (Barely). All you have to do when your app goes into the background is throttle down the Bluetooth LE scanning rate, but otherwise your app continues to run as it was written. With iOS, you have to do this ridiculous song and dance with a separately-scoped background "service" and seriously reduced feature set. Yeah, we know it is supposed to make multitasking better and keep app developers from crashing/killing your phone. But still, it's difficult to get the dance right between foreground and background. What makes iOS really nice here is even if your app is hard-closed, it is awoken when iBeacons are detected. But even that presents its own challenges.
  • Robustness/lack of befuddling crashes and weird stack traces: Tie. Both produced the occasional wtf moments, but there wasn't a clear bias from one or the other for "Sharepoint moments".
  • Power consumption - winner: iOS, but it might have been because we had tired batteries on Android. More rigorous test is probably needed.

Overall winner: "It Depends". It depends on which of these are more important to you. But iOS+Android make up like 99% of the market, so if you just target one or the other, you'll be missing out.


When iBeacons first emerged, they got a pretty bad rap, when phrases thrown around like "Marketing tools for the NSA". As in most cases, reality is much different than the fantasyland of the mass media, and iBeacons don't in and of themselves cause you to be tracked and reported to the authorities if you cross a double yellow line on the highway or steal toiletries from a hotel room. But they also don't prevent it :)

What does pose a danger are irresponsible (or malicious) app developers coupled with unsuspecting owners of smartphones who click on every link they see on Pinterest and give their private data to anyone that asks. This danger has existed since the mists of antiquity, it's just easier to do on a bigger scale now.

By default the Liferay Events app sends mostly-anonymous data about iBeacons back to our servers. The "mostly" bit is due to the fact that it also includes an "identifier", but that ID is associated with the installation of the app, not the person or the device. If you re-install the app, it gets a new ID. We feel this is a good way to it, and respect the privacy of the user. Oh and you can also switch off Bluetooth. Or uninstall the app!

Future Enhancements

There are a lot:

  • Integration with services (e.g. being able to log in, and link your event activity with your online profile)
  • Detection of nearby interesting people, not just objects, and getting you to talk to them
  • Auto-registration (pre-register in the app, and then when you walk up to the registration desk, the app emits a QR code that is scanned to confirm your presence)
  • Rewards for attending certain types of sessions or tracks
  • Pattern recognition for sessions, in order to suggest other, related sessions or people
  • Realtime analytics, trendspotting

Wrapping Up

Computers and electronics in general continue their march toward smaller, faster, cheaper, more efficient, and more approachable footprints. Along with those advances comes new ways to apply them to solve problems that were historically difficult or impossible. And we are just getting started with mobile devices and apps, which open up a whole new class of applications that benefit not just the technically elite but also those that have until now been economically or socially disadvantaged.

iBeacon is one example of this, and in this author's opinion is a stepping stone to a really cool future involving location-aware computing and better, more personal engagement with our devices. Of course there will be missteps along the way and there are plenty of risks (privacy or lack thereof, securing transactions between moving people and things, EM radiation and interference, safety while operating heavy machinery, Skynet-type takeovers, and more), but this author is also optimistic that we can and will solve these issues. It's an interesting future! Thanks for reading!

iBeacons: The Next Liferay Chapter

If you'd like to know more about using iBeacons for engaging audiences and event marketing, check out my new eBook Finding Your Way Around iBeacons for Event Marketing.

Download the eBook

2014 Liferay Marketplace App Contest Results

General Blogs August 25, 2014 By James Falkner

Today Liferay announced the winners of the 2014 Liferay Marketplace App Contest! This year, we were super excited to see what our community could dream up, and you did not disappoint. The review team witnessed an unmistakeable and significant increase in overall app quality this year, so it was even more difficult to pick the winners. A big thank you goes to each of you who took the time to create and submit your apps to the contest, because without you, we'd never see the variety and creativity of apps that a big community of awesome people can produce. Ok, enough babbling, onto the results!

The Grand Prize Winners

This year, with the introduction of paid apps, we judged across two different axes: commercial/non-commercial and free/paid, which resulted in 4 different categories and 4 grand prize winners (and 4 runners up). This allows those with less available resources (i.e. people, time, and money) to still compete and win! Apps were judged for their creativity and usefulness, ease of installation/setup, user interface, user experience, Liferay integration, and completeness of solution. Here are the grand prize winners for 2014:

Social Apps Proxy (Free; developed by Stian Sigvartsen)

If you are building apps that integrate with all the things social, this app implements the most boring and complex part of that integration, and exposes a simplified interface for your app's customers to connect your app with their preferred social networks. It acts as a proxy between your app and any OAuth-based social network (like Twitter, LinkedIn, etc). OAuth is complex and difficult to get right, so this app does the magic for any number of external networks with which you wish to integrate, and does so securely within the Liferay platform!

Visioneo Reports PE (Paid; developed by Dominique Pardon)

Visioneo is a complete reporting application, allowing you to embed high quality reports into Liferay. Using the popular Open Source BIRT Eclipse designer, you can create powerful reports containing charts, data tables, cross-tables, images, grids, multiple pages and many other things from your own datasources (including Liferay itself!). There are two versions available: a Community Edition (CE) and a Professional Edition (PE). The Professional Edition includes enhanced Liferay integration through reports permissioning and document integration.

Tori Forum (Free; developed by Vaadin Ltd)

Tori is a discussion forum portlet with a fantastic user interface and experience. Features like real-time notifications and in-page navigation make it easy and comfortable to use. Also included are real time notifications, a re-use of Liferay's forums backend (and is therefore a drop-in replacement), enhanced SEO and page indexing, custom badging, and much more. With a fast and fluent in-page navigation pattern and integrated analyics, Tori Forum is a great alternative front to the built-in message boards!

Vahtie - Survey and Insight (Paid; developed by Arcusys Ltd)

Vahtie is a powerful survey and feedback management solution for organizations to do employee, customer and research insight. It's designed to support large scale organizations natively on Liferay platform. It's proven and tested in production and it's currently being used by organizations with tens of thousands of users. It's a turn-key solution to a problem that pretty much every company or organization has - how to improve business based on feedback from those that use whatever it is that your company or organization produces.

Each Grand Prize app will be on display at an upcoming Liferay Conference - if you're interested in learning more about them and meeting the developers and companies behind these apps, check out our upcoming events listing to see if there is an event nearby that you'd be interested in attending!

The Runners Up

Announcements (Free; developed by Guillaume Lenoir)

This app implements a social announcements platform, using categories and vocabularies from Liferay. Users can create and manage announcements of varying purpose across multiple different sites, and includes support for adding rich media, workflow for announcements, native integration with Liferay's asset management framework, support for social activity streams, comments/likes/views, and uses Liferay's out of the box UI to provide a pleasing experience with virtually no changes.

Social Login for Liferay (Paid; developed by Moisés Belda)

Social Login for Liferay is a plugin which enables users to login to Liferay using their preferred social networks, including support for the most popular social networks like Google+, Facebook, Twitter, LinkedIn, and even includes support for Microsoft network login. It is OAuth2-based, and uses AlloyUI components to give users a great mobile and desktop experience when logging into your portal.

MapIt Now (Free; developed by 3F Consulting)

This plugin uses a visual geographic map to visualize the location of content such as blog and wiki posts, forum threads, users, and any other asset type in the Liferay platform. Implemented as a standard AlloyUI/JavaScript component, you can add multiple maps to a page, and link it to other built-in asset presenters such as Liferay's Asset Publisher. Administrative controls allow you to selectively enable or disable different asset types, and choose which mapping service and layers to use (e.g. OpenLayers/OpenStreetMap, Google Maps, Bing, and others). Paid plugins are also available to change the way the data is presented.

Intelligus TeamWorXX (Paid; developed by PFI Knowledge Solutions Ltd)

Intelligus TeamWorXX is a web-based collaboration and social networking suite, which leverages and extends the social and collaboration features of Liferay. TeamWorXX is aimed at helping groups of users work together effectively and share knowledge online. Used by over 250,000 users worldwide, Intelligus TeamWorXX is a feature rich web collaboration platform that hosts the UK's largest platform for public service collaboration. Intelligus TeamWorXX lets your users manage everything from searching all visible groups, members and content, to contributing ideas, posting announcements and creating polls.

Some Stats

  • 301 apps available on the Marketplace
  • 750 Enrolled Marketplace Developers
  • 150 Enrolled Marketplace Companies
  • 98 Total contest submissions from 15 countries (Australia, Belgium, Costa Rica, Czech Republic, Ecuador, Finland, France, Hungary, India, Italy, Peru, Romania, Spain, UK, USA)

... In Closing

This year we saw a huge increase in app quality during the contest: initial setup, UX, Liferay integration, you name it. Every single app in the contest was useful and I think shows the power of a community of people finding new and creative ways to use Liferay technology to solve real issues. Well done everyone!

DIY: Liferay Events Hacks: Part 1

Technical Blogs August 18, 2014 By James Falkner

Liferay hold many events throughout the year (10+ this year alone), featuring keynotes, workshops, expert speakers, onsite and offsite events, and multiple venues around the world. The data associated with past, current, and future events includes huge agendas, many speakers, rooms, activities, maps, locations, analytics during the event, and much more.

Finding an effective way to aggregate and display all that data for attendees (on multiple devices) is a challenge! We have websites and mobile apps that are designed for displaying this data, but there are things some folks want and others do not, so we are challenging you, the community: do it yourself and make it better than ours, and show everyone what you made!

We're opening up the data stream for our community, and want to see what kinds of new and interesting things you can do with the data. Think dynamic maps. Floating faces. Wordles. Mind maps. Semantic content analysis magic. Mashups with social media. Interactive websites. Ways to connect the dots that no one else thought of. The data is simple, and your creativity is unending, so show us what you can do! (BTW: Technically, the data has been open, just undocumented!)

What's in it for me?

You'll gain respect, love and admiration from our community. Not enough for you? We will also show everyone your creations at the upcoming symposiums and DevCon this fall and tell everyone you are a rockstar!

How do I participate?

Simple - create something awesome using the data feed (see below for details on the format and meaning of the data), and tweet the result (pics, screenshots, videos, links) using the #DIYLiferay hashtag. Also, feel free to blog, forum-post, and anything else you want to use to get the word out. We want to see what you did!

There is a lot of data - you don't have to use all of it. Just pick the stuff you want to use, and ignore the rest. Even just the speaker headshots could be used for some rotating awesome 3D sphere of heads. Also, I tried to describe everything in excruciating detail below, but may have missed stuff, but the names and content should be pretty straightforward, and you can check out the data feed and compare it to the microsite and mobile app to see how the data is used there, to give you some idea on how to use it for your own purposes.


  • If you write code, seriously consider licensing it with an OSI-approved open source license. We want to learn from you! And find bugs for you.
  • You must follow applicable laws (e.g. copyrights, trademarks, logo usage, etc). Nothing new here.
  • Since the event data changes constantly, you should include the following statement prominently in your solution: "This presentation of Liferay Event data was created by [Your Name Here]. Please note that all data is subject to change and Liferay's official event data can be found at"

Liferay Events Data Feed Details

All event data are stored internally on in Dynamic Data Lists, and can be downloaded as individual JSON documents using Liferay's built-in JSONWS service. We layer on a plugin (which will eventually make its way to the Marketplace) to do some post-processing of the returned documents for easier usage in the mobile app.

What code do I need to write?

You can use any language or framework that can retrieve and parse content (so basically, any language!). See the end of this post for working code that you can quickly try out to see how things work. But the main workflow is:

  1. Get a list of events in JSON
  2. Get data about a specific event in JSON
  3. Do something awesome with the data

General guidelines

  • All dates are represented in format YYYY-MM-DD or HH:MM and are assumed to be in the local event timezone unless otherwise noted.
  • Boolean values are represented by the strings 'true' and 'false' - you will need to convert these to real booleans in your chosen language if desired.
  • Some items are themselves are strings that represent JSON documents and must be parsed as such again, in code. For example, you might find a string like "{\"foo\": \"bar\", \"baz\": 3}" and you would need to parse this to programmatically access it (e.g. using JSON.parse()).
  • Some items are lists of name/value pairs, e.g. a=b,c=d and may contain whitespace (including tab characters!) that should be trimmed. That means you should parse 'a=b,c=d' the same as ' a =b , c = d'. Also, colon-separated lists like 'a:b:c,d:e:f' is the same as ' a: b : c ,d: e :f '. Recommendation: use String.trim(). Enjoy!
  • Every record returned via a JSON endpoint will have a UUID associated with it named uuid. This is sometimes used to relate two items together, e.g. agenda items have a list of speakers represented as a list of uuids, which can be used to get the right speaker record via the uuid (assuming you have already retrieved the list of speakers).
  • I suggest you download and cache all event data for a given event at once, and store them internally (possibly using hashtables for quick lookup based on things like uuid). If you only download half the data, you might not be able to de-reference certain pointers (like speaker UUIDs). That's what the mobile app does (and periodically refreshes data once every 30 minutes while the app is running).

Step 1: Getting the list of events

As we have many different events throughout the year, the first thing to get is a list of events, using the following endpoint (notice the hard-coded ddlRecordSetId value - this is your key to the kingdom and should never change for the event listing):

Go ahead, click it! You know you want to.

This is the same endpoint used by the mobile app to show you the event select screen when the app is first used. The returned document is a JSON array with the following structure:

  { "dynamicElements": EVENT_1_DATA_JSON_OBJECT },
  { "dynamicElements": EVENT_2_DATA_JSON_OBJECT },
  { "dynamicElements": EVENT_N_DATA_JSON_OBJECT }

Each event is represented as an object in the above array, named dynamicElements. Each event object (the EVENT_N_DATA_JSON_OBJECT from above) has the following elements:

  • active: 'true' or 'false' (note they are strings, not booleans), inactive events aren't finalized and should be ignored (and are blocked in mobile app)
  • booth_map_name: name of map (see below) that represent sponsor booths
  • end_date: when the "thanks for attending" message should show in the app, format YYYY-MM-DD
  • end_time: when the "thanks for attending" message should show in the app, format HH:MM
  • event_hashtag: official event Twitter hashtag (e.g. #lrdevcon for the upcoming developer conference)
  • event_type_dict: translations for select options for sponsor levels, session types, and agenda filter names. Format: comma-separated name=value pairs. E.g. "diamond=DIAMANT,gold=Gold" means the level with key "diamond" should be displayed as DIAMANT (German translation of Diamond) and key "gold" should be displayed as Gold.
  • event_tz: number of hours ahead or behind GMT (negative numbers indicate ahead, e.g. France is -2 in summer, can be used to correct for phones that are set to a different timezone than the event itself to calculate 'local event time' based on device time.
  • event_url: Web URL to the event microsite
  • eventid: identifier used to namespace the user data for this event
  • inactive_msg: message to show user when trying to access inactive event via mobile app
  • latitude: Decimal degrees of latitude for event location (approximate, used for the 'pick the closest location' button in app)
  • location_label: Name of location (usually a city name, e.g. Paris or Boston)
  • logo: the logo to use to represent the event. This string is an embedded JSON document which can be used to construct the final URL to the logo, format is: {"groupId": gid, "uuid":uuid, "version":version}. You can parse this with JSON.parse(). The final URL can then be constructed:[groupId]/[uuid]
  • longitude: Decimal degrees of longitude for event location (approximate)
  • menutitle: String which appears at top of mobile app screens
  • metadata_types: [see below for details]
  • news_type: ddlRecordSetId of the list of news to show user, can periodically check this to see if there is breaking news (see news item below)
  • ordered_sponsor_levels: the order and size of the sponsor logos on the Sponsors screen. Format: comma-separated list of [name:logos-per-row:size] triplets. For example diamond:1:large,platinum:2:small means that Diamond-level sponsor logos should be shown at the top, 1 per row, and 'large' size, where Platinum-level sponsors are shown 2 per row, and a smaller size. Size can be large or small. Names of sponsor levels are used in the sponsor list, and the display name can be found in the event_type_dict.
  • randomize_sponsors: 'true' or 'false': whether to randomize order of individual logos within each sponsor level.
  • register_url: the URL for people to register to attend.
  • session_survey_questions: A list of questions to ask when survey feedback is given. The format of this is beyond the scope of this challenge :)
  • start_date: when the event begins, used to order on the 'event select' screen. format YYYY-MM-DD
  • start_time: when the event begins, used to order on the 'event select' screen. format HH:MM
  • survey_questions: A list of questions to ask when event feedback is given. The format of this is beyond the scope of this challenge :)
  • title: name of event to show on the event select screen.
  • track_colors: Custom definition of track bar colors for agenda screen. Format: comma-separated list of hex values (where the first one represents track 1, etc) For example #234233,#66DDAA
  • upload_photosetid: the photoset id used to upload and retrieve pictures from the event [see below for details]
  • uuid: unique identifier for this particular object

As new events come online, they will appear in this list. And past events are here as well, in case you wish to test with past event data to fine-tune your app!

The metadata_types element

Each event has a metadata_types field. This is the key to drilling down and getting event-specific data (like agendas, speakers, etc). The format of this element is a comma-separated list of name:ID pairs. For example agenda:12323423,activities:23423243,... You use these IDs to retrieve data of a particular type for a particular event, for example: just as you did for the event list. The elements in the metadata_types list include:

  • agenda: A giant list of all agenda items for the event that appear on the microsite and mobile app
  • activities: A list of onsite and offsite activities (e.g. community meetups, social hours, etc)
  • contacts: A list of initial contacts to populate the 'Contacts' screen for the event
  • galleries: A list of photo galleries to show on the 'Gallery' screen for the event
  • maps: A list of maps to show on the 'Maps' screen for the event
  • rooms: A list of rooms used at the event (used to map agenda items to physical rooms)
  • speakers: A list of all speakers (used to generate pics, biographies, etc)
  • sponsors: A list of the sponsors of the event, for the 'Sponsors' screen

Each type of data is explained below. You will also find elements for beacon_forms, beacon_individual_events, beacon_region_events, and beacon_regions: These are related to our iBeacons feature at events, and will be covered in part 2 of this blog post.

Step 2: Fetch data about an individual event

Once you have fetched the list of events above, you can then use the metadata_types object for an event to access details about the specific event, using the ddlRecordSetId's in the metadata_types field for that event. For example, the agenda for France Symposium is 35246557.  You should fetch all data (agenda, speakers, rooms, etc) for a given event at once, because some elements reference other elements (e.g. an agenda item lists speakers by their uuid, which can be looked up in the speakers data for the event).

Fetching The Agenda

The agenda is the most complicated of all the event data types. Here's the France Symposium agenda. Note that all agenda items are represented here, including breaks, after-parties, registration, etc. Some elements may not have all fields filled out (e.g. there are no speakers for the 'Breakfast' agenda item, and no video URLs either). The format is the same as above, with the following elements:

  • custom_css_class: ignore this, not the droid you are looking for
  • date: Day of the session, format: YYYY-MM-DD
  • display_in_mobile_app: whether to display in mobile app or not (some items are not)
  • display_on_live: whether to display on microsite or not (some unfinished items are not, and you should ignore these)
  • download_label: Slide download URL (only active after event)
  • download_url: Session replay URL (only active after event)
  • enable_notes: Whether to enable 'personal notes' field in app (e.g. "Lunch" is not enabled for this)
  • enable_ratings: Whether to enable the session to be rated (e.g. "Afternoon Break" is not rateable)
  • end_time_hour: When the session ends (it's actually a JSON array with a single element representing the hour of end - don't ask why)
  • end_time_minutes: When the session ends (it's actually a JSON array with one element representing the minutes of end time - don't ask why)
  • room_uuid: The UUID of the room element that in which this session takes place
  • session_summary: The human-readable abstract/summary of the session
  • session_type: A single-element JSON array representing the type ("Technical", "Case Study", "Workshop", etc. used to put cool icons on the display)
  • speakers_uuid: A comma-separated list of speaker UUIDs for the session. You can look up speaker details via the UUID and the speaker list below.
  • select_category: If present, then this is a JSON array representing a list of categories to which this session belongs. E.g. all Mobile-related talks would have mobile as a category, or perhaps mobile, responsive. These are free-form tags that are used on the website and mobile app to allow attendees to only show certain kinds of sessions. The display name of the filters can be found in the event_type_dict dictionary for the event.
  • sponsors_uuid: A comma-separated list of sponsors that are sponsoring the session (e.g. for sponsored after-parties, etc)
  • start_time_hour: When it starts (again, a single-value JSON array)
  • start_time_minutes: When it starts (again, a single-value JSON array)
  • survey_questions: The list of questions to ask when rating the session. Out of scope for this challenge!
  • title: The title of the session
  • uuid: The unique identifier for this session
  • video_url: Direct video replay URL (available after event)

Fetching The Speakers

Here's the France Symposium speaker list. Format is the same, with the following elements:

  • speaker_bio: Human-readable biography of speaker
  • speaker_company: Their company
  • speaker_highlight: true or false. Whether they are highlighted. Highlighted speakers are shown on a "Highlighted speakers" page on the microsite.
  • speaker_image: The URL to the headshot. Again, it's a JSON document that can be used to construct the URL in the same way as other images (for example the logo element in the Event List)
  • speaker_keynote: true or false. true means it's a keynote, and is highlighted on the agenda listing.
  • speaker_name: Name of speaker
  • speaker_social_blog: URL to their blog
  • speaker_social_facebook: URL to their Facebook page
  • speaker_social_liferay: URL to their Liferay profile
  • speaker_social_linkedin: URL to their LinkedIn page
  • speaker_social_twitter: URL to their twitter page
  • speaker_social_youtube: URL to their youtube page
  • speaker_title: Their job title
  • uuid: Unique identifer for this speaker

Fetching The Sponsors

Example from France Symposium. Here are the elements:

  • docmedia: The sponsor's logo. Same deal as above, it's a JSON document which can be parsed to construct the URL.
  • level_rank: Their rank within their level. E.g. a Gold sponsor of rank 2 would be displayed below rank 1 or 0. Ignored if randomize_sponsors is in effect for this event.
  • link: The link to the sponsor's homepage/website.
  • name: The name of the sponsor.
  • rank: Their rank - it's a single-element JSON array indicating the key of their rank. e.g. 'diamond' or 'platinum' or 'exhibitor'.
  • type: A single-element JSON array. 'event' is a traditional sponsor. 'photo' is a photostream sponsor. 'scan' is a badge scanner sponsor.
  • uuid: Unique identifier for this sponsor.

Fetching The Rooms

Rooms are linked to sessions via UUID. Here's the France Symposium room list. Elements are:

  • display_as_track_heading: ignored (it used to mean something, but no longer)
  • map_id: Unused currently (we use the name of the room as a key in the other lists)
  • room_name: Name of room (e.g. "Grote Zaal" or "Grand Ballroom")
  • room_number: Unused currently
  • uuid: A unique identifier for the room

Fetching The Activities

Activities are things like Community Meetups, etc that appear on the "Activities" screen in the mobile app. Here's the France Symposium activities list. Elements:

  • date: The date of the event, format: YYYY-MM-DD
  • description: Human-readable description of event
  • endtime: When it ends. Format: HH:MM
  • hostedby: Company or individual that is hosting activity
  • map_name: The name of the map element that can be used to generate a pointer to the map itself.
  • picture: A JSON object that can be used to construct a pointer to the image for the activity.
  • starttime: When it starts. Format: HH:MM
  • title: The title of the activity
  • uuid: A unique identifier for the activity.

Fetching The Maps

Maps are used to show room layouts and provide maps to relevant physical locations (e.g. hotels, pubs, tennis courts, etc). Here's the France Symposium map listing. Elements includE:

  • address: The physical address of the place. Don't try to parse it, just use it as input to some map service like google. Also, for room maps, there's no address.
  • icon: A small thumbnail representing the location.
  • image: A bigger image representing the location.
  • name: The name of the place (is used in the Activities list to generate a link to this map)
  • phone: If you want to call/text the location, use this phone number.
  • show_map: For items that don't have an actual address (like a room in a venue), this is 'false', and the mobile app won't generate a dynamic google map.
  • uuid: A unique identifier for this map. Is used elsewhere (e.g. in the agenda's room_uuid element) to reference this map.

Fetching The Contacts

In the mobile app, there is a Contacts screen with a default list of contacts, that can be added to at certain events that have QR codes printed on badges. Here's the France Symposium contacts list. Elements:

  • blog: Their blog pointer
  • city: The city in which they do business
  • companyname: Name of company
  • country: Name of country
  • facebook: Their facebook page
  • firstname: Their given name
  • googleplus: Their Google+ page
  • lastname: Their family name
  • linkedin: Their LinkedIn page
  • phone: Their business phone number
  • picture: Their image (again, a JSON object that must be parsed to construct an image URL)
  • readonly: Whether they can be deleted. 'true' or 'false'.
  • state: Their state/region
  • street: Their street address
  • twitter: Their twitter page
  • url: Their company's URL
  • uuid: A unique identifier for this contact
  • youtube: Their YouTube page
  • zip: Their postal code

Fetching The Galleries

In the mobile app, there is a Gallery page with different tabs for different events. Generally, the gallery in position 1 is the gallery representing the current event that is being brosed. Here's the France Symposium gallery list. Elements:

  • photosetid: The photoset identifier (see below)
  • position: The position of the tab (1=leftmost, 4=rightmost)
  • rateable: Whether pics in this gallery can be rated (thumbs up). Generally only the current event's pics can be rated.
  • title: The title of the gallery (appears on tabs)
  • uuid: A unique identifier for this gallery entry.

During the event, attendees are encouraged to take pics and upload them with the mobile app, and the pics go to Flickr. You can retrieve a listing of all the pics from Flickr using the photosetid and Flickr's REST web service (you have to have an API Key, and follow their docs closely to do this). This listing you get back from Flickr also includes a direct photo URL for each photo, so you can make pretty pictures dance.

And that's it!

Trying it with Sample Code

Since you're reading this on, simply open your Developer JavaScript console in your browser, and copy/paste this code into it and press return. Note there's absolutely no error checking whatsoever.

var eventsUrl = '';

function listener() {
    var events = JSON.parse(this.responseText);
    var eventList = '';
    events.forEach(function (el) {
        var event = el.dynamicElements;
        eventList += (event.start_date + ' ' + event.title + ' ' + event.location_label + '\n\n');

var req = new XMLHttpRequest();
req.onload = listener;'get', eventsUrl, true);

This will generate an alert popup for our events by retrieving the listing and parsing it out:

Another Example

This one is a bit more complicated, it retrieves all of the events, looks for our North America Symposium entry, then retrieves its agenda and looks for sessions that are categorized as mobile sessions, and shows its details in another annoying popup.
var urlPrefix = '';

function handleAgenda() {
  var agenda = JSON.parse(this.responseText);
  agenda.forEach(function(info) {
    var agendaItem = info.dynamicElements;
    if (agendaItem.select_category) {
      var cats = JSON.parse(agendaItem.select_category);
      if (cats.indexOf('mobile') != -1) {
        alert('A a mobile session: ' +
              agendaItem.title + ' on ' +

function handleEvents() {
  var events = JSON.parse(this.responseText);
  // find the NAS Boston event
  events.forEach(function(event) {
    if (event.dynamicElements.eventid === 'lr-nas-2014') {
      // get the metadata_id for the agenda and put it into a dictionary
      // dealing with whitespace via trim()
      var eventDict = {};
        .map(function(el) {return el.trim();})
        .forEach(function(nvpair) {
          var parts = nvpair.split(':').map(function(el) { return el.trim();});
          eventDict[parts[0]] = parts[1]
      var agendaId = eventDict.agenda;
      var agendaReq = new XMLHttpRequest();
      agendaReq.onload = handleAgenda;'get', urlPrefix + agendaId, true);

var eventsReq = new XMLHttpRequest();
eventsReq.onload = handleEvents;'get', urlPrefix + '36416693', true);

Good luck, and don't forget to tweet your creation with #DIYLiferay or leave it in comments below! Happy hacking!

Image credits: DIY Google Glass from FalconHive

Changes to Community Blogs

General Blogs July 28, 2014 By James Falkner

Over the weekend you may have have noticed our community blogs page got a makeover! There are several new additions and changes to the page which we hope will make your blogging experience better and more informative, and make it easier for you to not only keep up with what's going on but to contribute your ideas in a more structured/categorized way.

Highlighted Bloggers

First, I wanted to thank all of you who have contributed to your blogs on!

Since opening up blogging to our entire community in 2013, we have been thrilled to see how our community has responded, with lots of informative entries and quality content.. but the very coarse categorization (Staff vs. Community) isn't enough, can be confusing for staff, and the sheer number of posts showing up in each of these buckets means that you get a big flat list of tons of blog entries, some really good, and some that could have used more polishing before publishing smiley

To help you with choosing what to read, the new main blog landing page is now a curated list, showing you the "best of the best" (as decided by our editorial staff and feedback from the community on specific posts). As a reader, it should be the first thing you follow/subscribe to! The same list of highlighted blogs will also appear on the right side of the community landing page.

You can still follow all of our community's blog posts by clicking on the All tab, which will work as before and show a reverse chronological list of all blog posts. We hope that you find value in the curation and are motivated to produce high quality posts that show up here!

How do I get highlighted?

It's really easy (well, easy to understand, a bit harder to execute) - just publish quality content that is easy to read, informative, and does a good job at reaching your intended audience. You might want to read through the Blog Guidelines at the bottom of the Content Policy page for some tips about writing quality posts. If you do it enough, your readers will respond, and our curation department will most definitely recognize you and highlight you or your blog posts, or both!

Non-highlighted posts will continue to show up on the All category (and of course, your personal blog page!).


Not everyone is interested in technical blogs, or blogs about Liferay the company, so we've enabled Categories (using Liferay's built-in categories feature of course!). Categories allow blog authors to mark their posts to be in a particular category, causing it to show up on the specific sub-page of the All tab. You can also subscribe/follow individual categories using the RSS links at the bottom of each tab. We started small: Company posts relate to Liferay the company (such as Zeno's recent post about his Liferay Brazil office experiences), whereas Technical posts are (you guessed it) more technical in nature, like Srikanth's recent post about Service Builder. The General category is for posts that don't fit in the other categories.

As an author, you will be required to specify a category (with the default being General). Be sure to choose wisely! Only staff members will be able to pick the Company category. This will help your readers pick the posts they are most interested in. If you have suggestions for more categories, let us know in comments (yeah, there are tons of possibilities here, but the simpler the better, for UI and UX!).

Also note that your past posts aren't automatically categorized - if you want them to appear in the proper category, you will need to Edit them and select the right category on the Edit screen.

Most Active Bloggers

There is also a new link on the left navigation area under Blogs - Most Active Bloggers will show you the most active bloggers by number of posts in the past 6 months, regardless of whether they have produced any highlighted blogs. Readers who want to keep up to date in the community can find out exactly who is contributing on blogs using this page. The page also features easy RSS feed links for each individual author.

Note that this list only shows bloggers from - if you had your external blog listed previously, it will be returning very soon, so stay tuned!

Updated Look & Feel

The blogs pages also has a new look, with rounded pictures, crisper fonts, more category and subject lozenges, and new icons for views and comments. We hope you like the look of the new page, along with the new features and new curated lists.

How do I post a blog?

Everyone who has an account on can publish blog posts. To publish a blog, visit your profile page by logging in, clicking your profile picture at the upper right, and choose Account and then click Profile at the top next to your profile picture (or, if you know your screen name, just type in{screenname}/profile into your browser's address bar).

Once on your profile page, look for the Blog link on the left, and click on it, and click the Add Entry button to draft a new entry using Liferay's built-in WYSIWYG editor. If you do not see a Blog link, you will need to request a blog (this is an additional anti-spam measure, as long as your account is in good standing you will get a blog!). Happy blogging!


As usual, I am only the messenger here, and several people chipped in to make this a reality. Ryan Schuhler, Nathan Cook, Enoch Chu, Luke Shackelford, and Amos Fong worked on the frontend and backend development, while Juan Hidalgo and Yoshiki Hisamoto were responsible for the awesome design. And you, our community, were and continue to be instrumental in making our blogs interesting and informative! Community Developer Sessions

General Blogs July 15, 2014 By James Falkner

I'm not sure if I've said it enough -- our community is awesome! Each of us comes from different geographic places, cultural backgrounds, and Liferay experiences and we bring that collective story together through software by developing contributions, cool apps, and ultimately learning through sharing. And in that spirit I'm happy to announce a new initiative for our developer community: Community Developer Sessions!

2 weeks from today will begin a regular series of online hangouts designed for you, the Liferay Developer. Don't worry, these won't be boring slide presentations, but instead will each be unique and interactive hands-on coding sessions with a small, focused goal that each of us can achieve during the session and can then take home for later. Think of it like a mini-"workshop/hacking session" with a small, well-defined goal, led by your fellow developers from around the community. You won't find intro to portlets or here's my fully baked project - good luck kinds of sessions here. You will however learn something new every 2 weeks.

Specifically, these will be 60-90 minute hangouts every 2 weeks using Google+ Hangouts and YouTube, along with interactive features like a dedicated IRC chat room for Q&A, online collaborative coding whiteboards, Q&A and more. Simply show up with your mind (and your development environment) and start hacking! We are all stuck behind a monitor and keyboard most of the day, so this gives us all a chance to “get out there” and get more personal with our community and meet and engage with others in the world of Liferay and teach small things that can lead to larger things later on. And best of all, it's totally free (as in beer).

To give you a taste of what's coming, here are some example sessions (some of which are already on the calendar):

  • Calling a Liferay service from a mobile app
  • Sending out mass emails using Liferay's SubscriptionSender
  • OSGi and Gogo Shell interface examples
  • Extending AlloyUI's FormBuilder 
  • How to use other Databases/data sources in your app 
  • Creating a service using ServiceBuilder
  • Integrating custom assets into Recycle Bin
  • Creating a custom JSON Web Service that's anonymously accessible -
  • Defining a custom resource and permissions
  • Lucene/Solr integration for custom apps
  • Creating a simple Spring MVC Portlet
  • Converting an out-of-box Bootstrap theme to Liferay
  • Using Application Display Templates in your app
  • Creating power macros for FreeMarker
  • Integrating custom assets into ADT
  • Using Liferay JavaScript to call a service
  • Configuring a simple cluster
  • Integrating Liferay with an external CMIS repository
  • Turning on and using Social Activities features in custom apps
  • (And my personal favorite) Answering random posts from the community forums!

It's a big experiment that I hope you will enjoy and participate in. The first session is on July 29 at 1400 GMT (that's 0400 HAST, 0700 PDT, 1000 EDT, 1600 CEST, 1700 EEST, 1930 IST, 2200 CST, 2300 JST, 0000 AEST, and so on...) where we'll go over the typical dev environment one might use, how to use the collab tools, and introduce the upcoming sessions. As we go along we might change the tools, but the spirit of the sessions will remain the same. Following the first session, we'll do one every 2 weeks at about the same time of day. We have about 10 sessions in the pipeline so far (the next 3 sessions are on the upcoming sessions page).

How to Participate

To participate, check out and join us on July 29. On the site you'll also find a list of upcoming sessions (along with any prerequisites for each session), a calendar to which you can subscribe, and more information about the sessions. Each session will be broadcasted via Google+ and YouTube, but you need only visit the home page to join the session (there is an embedded YouTube stream and IRC chat on the page). You should also join IRC (specifically, the #liferay-dev-life channel for use during the session, and #liferay for general community chat) to join in the online chat in parallel to the hangout, as useful links and other information will be given, and you can directly interact with others. 

These sessions are geared toward Liferay Developers, and so you should also have your preferred development environment set up and ready to go if you intend to participate (and I highly recommend you do - you'll learn quite a bit more when forced to do things vs. passively watching!)

Calling all Developers

This is an ambitious effort to undertake, and your fellow community members would be super-appreciative to see what you're working on or what you've achieved with Liferay. Why not lead your own session? If you're interested, email me at with your ideas - everything development-related is welcome, but please no sales pitches or theoretical physics papers :) These are real world tasks with real results, buddy! And you'll get a small gift in return for your efforts!

So get fired up for, be sure to read the prerequisites for each session and get your toolbox ready to rock. It should be fun!

iBeacons and Liferay for Audience Engagement: Part 2

General Blogs July 1, 2014 By James Falkner

This blog is part of a series of entries documenting how we are using iBeacons and Liferay to better engage our audiences at events throughout the year. [Part 1] [Part 2] [Part 3]

Update: Check out my new eBook! Finding Your Way Around iBeacons for Event Marketing.

Download the eBook

In Part 1 I introduced the concept of using iBeacons for Audience Engagement and reviewed knowing your audience and the physical space. In this entry, we'll cover more technical details about beacon programming and management, and what we learned in Amsterdam and Paris. First off, let's explore how devices "listen" for beacons.

Beacon Identification

As we discussed previously, each iBeacon you put in a space continuously emits a Bluetooth LE signal, that contains data that uniquely identifies the beacon. Your app must be coded to enable beacon listening, and then provide code (callbacks) that is called when beacons are detected. In addition, devices must have turned on their Bluetooth radio and the user must have explicitly given the app permission to use the incoming data (this varies by device - for example on iOS the user must grant the Location Services permission, and on Android the user must grant the permission during app installation).

Beacons are uniquely identified with 3 pieces of information: UUID, Major, and Minor. Your app must know of these identifiers and be coded to respond in various ways when beacons are detected. These identifiers are part of the Bluetooth LE signal sent by each beacon. It's important to understand this - the beacons themselves aren't sending any "real" content (no web content, no credentials, no Java or HTML or JavaScript or PHP or Assembly code or pictures of your cat). It's up to your app to detect the presence of beacons and respond appropriately.

Beacon Regions and Region Monitoring

Suppose you have 100 beacons placed in various places at a venue (hotel, grocery store, football stadium, etc). In one large room, you might have 5 beacons to cover the entire space. To detect when the user has entered that room, your code would need to scan for all beacons at all times, and then if one of those 5 beacons were detected, your app would know the person has entered the room. When you can no longer detect any of those 5, then the person has exited the room. Your app would have to remember that a person entered a room so that it can also know when they exit (and what happens if one enters your room, and then restarts your app?) In addition, some beacons might be part of multiple and physically overlapping places to which you wish to respond. For example, at the Liferay France Symposium, the Registration Desk beacons were also in the Rotonde room, for which we had separate events. In a football stadium, Section 232 might be part of both the East and North seating area.

Coding for all that detection logic for each of your 100 beacons would quickly get tiresome, so some smart designers introduced an abstraction to help deal with the complexity. In this case, the abstraction is known as a Beacon Region. A Beacon Region is defined in software only - beacons themselves don't "know" they are "part of" a region. Only your app and device "knows" of these regions, and your app can be notified when the device "enters" or "exits" a region without you having to explicitly code for each individual beacon. This is known as Region Monitoring and is what occurs most of the time during your beacon-powered app's lifecycle.

One thing to keep in mind - even though your app will only get notified on entry or exit of a region, additional logic in your app can set you up to respond to things like "person has been in this region for XX minutes" or "person has gone from region A->B->C->A" and that sort of thing. It can be useful for better engagement (more on this later).

Beacon Proximities and Ranging

In addition to monitoring and responding to Region entry/exit events, your app can also be notified of its proximity (how close you are) to each individual beacon. Thanks to real world physics, the proximity isn't all that accurate - you can't know for certain that you are exactly 1.233 meters away from a beacon, due to multiple sources of interference and the frequency of broadcasts. iBeacons designers also knew this, and introduced 4 "zones" in which a beacon might be. The immediate zone is (from our testing) about 1m away or less. The near zone is about 1-5 meters. The far zone is 5m or further, until you reach the unknown zone which is usually a temporary zone just before the beacon becomes undetectable (and this also where you end up if you dig too deeply in Minecraft). This again is a software abstraction to help your code be simpler. Beacons don't "know" which zone they are in, no do they do anything different due to an approaching person or device.

Proximity detection (also known as Ranging) is also much more expensive in terms of energy consumption (i.e. drains your battery faster), because the hardware must scan for beacons frequently to get a somewhat accurate reading on each one. So you don't typically want your app continuously ranging for nearby beacons. In fact, some devices like the iPhone do not let your app do ranging when it is in the background for this reason. In the Liferay Events app, we only turn on ranging when the app is in the foreground and you have positively entered a region.

During ranging, your app will receive reports of each detected beacon, and in some cases reports of "boundary crossings" (e.g. when you go from near to immediate for a given beacon, and you want your app to do something special). Each beacon's hardware broadcast strength can be set by an administrator, and that setting is included in the packets sent over the air in the Bluetooth broadcast, so the beacon software in devices can do fancy math to calculate an approximate distance based on the power setting and the actual strength of the signal received. For example, if you crank the broadcast power to maximum on the beacon itself, but then the actual received signal is fairly weak by a device, then you can kind of know you're pretty far from the beacon.

Foreground vs. Background

From early testing we discovered most people don't run your app and walk around staring at the screen waiting for popups, looking like Dr. McCoy with a tricorder. Should be obvious, but sometimes you get blinded by the awesomeness of new tech and forget about how people really get along with it. So in reality, for your app to be engaging it has to provide value even when the app is in the background, or it is quit entirely.

For example, iOS allows monitoring but does not allow ranging when the app is in the background or quit entirely, so if all your app does is respond to ranging events, it's not going to be very interesting to most people, because it's not going to do anything while backgrounded/locked/quit. You need to combine region events with proximity events, and we did exactly this for the Liferay Events app. Again, people don't attend our events just to play with an app or their phone, they are there to learn about Liferay, attend sessions, and meet people, so most of the time their phone is in their pocket and not top of mind.

iOS 7.1 introduced a new feature that allows your app to receive beacon event messages even if the app is hard-closed. Again, only beacon monitoring works in this case, so your app should use region monitoring to ensure your users can be engaged even if the app is backgrounded or closed.

How we configured our beacons for events

So now that you understand how beacons work at a slightly lower level, let's talk about how we used them at our events. As part of this experiment, we decided to start small and feature the following types of engagements to engage both business and technical attendees:

  • Venue information and workflow - for example, a welcome message on arrival to the venue, with directional maps to the registration desk and WC, and a quick way to check in on social media, or some reminders to pick up name badges, or discounts at the cafe.
  • Sponsor Engagement - Interactive sponsor and partner marketing, including lead generation (e.g. "fill out our form for more info" or QR code scanning)
  • Speaker Engagement - Information about upcoming sessions occurring in the area you are in, or getting feedback from attendees as they leave a session
  • Gamification - Rewarding attendees by making them go to places (like a scavenger hunt) or using the app as a "virtual railpass" to force them to visit with and engage sponsors
  • Analytics - we wanted to (anonymously) see how people moved through the venue, to see if elements of the event (e.g. sponsor booths, hands-on demos, different food areas) were effective or not.

To support all these types, we defined several beacon regions (one for each discrete room that we wanted to act on) and also a venue-wide region encompassing all beacons (so we could show welcome messages even for those who snuck in through the back door.) We also used individual beacon proximities and ranging for certain triggers, such as when you approached a sponsor's booth, you'd get interactive and engaging content, or when you approached a "mystery guest", you got a trigger to engage in a game (more on gamification later).

Beacons are not super-expensive, ranging from USD 5 [reportedly] - USD 30 each. At typical Liferay events we can have up to 5 or 6 different rooms, and we also wanted to support sponsors, so we ended up needing around 20 beacons (a few more than absolutely needed, for backup purposes). You will also lose some, unless you hide them really well or lock them in a box.

Liferay Portal Solutions Forum Benelux 2014 Configuration

This event took place in a somewhat compact venue (Pakhuis De Zwijger), with the registration area, sponsor area, and main speaking room all within about 50m of each other. We configured the following beacon regions and individual beacons:

iBeacon Config for Benelux Symposium

Region Name UUID Major Minor
Venue B9407F30-F5F8-466E-AFF9-25556B57FE6D [Any] [Any]
Grote Zaal B9407F30-F5F8-466E-AFF9-25556B57FE6D 1 [Any]
Registration B9407F30-F5F8-466E-AFF9-25556B57FE6D 0 [Any]
Expo B9407F30-F5F8-466E-AFF9-25556B57FE6D 2 [Any]
Cafe B9407F30-F5F8-466E-AFF9-25556B57FE6D 3 [Any]

So any beacon with the UUID of B9407F30-F5F8-466E-AFF9-25556B57FE6D would be considered in the "Venue" region (and we had entry/exit triggers setup for entering or exiting the Venue, e.g. "Welcome" and "Goodbye" with links for event surveys, social media, etc). Any beacon with a UUID of B9407F30-F5F8-466E-AFF9-25556B57FE6D and a major of 2 would be considered in the Expo region (this is where the sponsor booths were). Further, each sponsor booth had a beacon dedicated for it, using B9407F30-F5F8-466E-AFF9-25556B57FE6D for the UUID, a major value of 2, and a minor value starting at 0 and going up (we had 6 sponsors). If you're wondering, that special UUID is simply the default UUID of Estimote Beacons, the vendor from which we sourced the beacons.

The main hall (Grote Zaal) was a large space, so we used two beacons placed on either side of the room, up high, to cover the entire room, and this worked pretty good (each were configured with a major value of 1). The other areas were served with 1 beacon each.

We also featured a "mystery guest" game. The goal of the game was to engage attendees through a game, while at the same time forcing them to engage with the sponsors at the event. To play the game, attendees had to find a special person who was secretly carrying a beacon. When you got close to this person, the app would respond and ask you a question, to which only the mystery guest had the answer. Upon learning the answer (and typing it in correctly), you could then proceed to each sponsor booth, and on approaching the booth, you would get more notifications with marketing messages from the sponsors and a form to enter your info, along with the answer to another question (the answer would be found by talking to the sponsors, forcing attendees to engage!).

We then configured the app and Liferay to support the following beacon notifications

  • Venue Entry - Welcome message with registration maps and social media checkins
  • Venue Exit - Farewell message, encouraging you to fill out survey or visit
  • Registration Entry - Reminder of what to not forget, links to agenda and social media checkin
  • Registration Linger (5 minutes or more) - Detail about venue and what's upcoming and interesting
  • Expo Entry - Detail about sponsors along with sponsor links and content
  • Expo Linger - More sponsor info
  • Grote Zaal Entry - Links for speaker, session topic, session survey, twitter
  • Grote Zaal Exit - Thanks message, links to agenda, and encourages survey feedback
  • Mystery Guest Proximity - encourages you to find them and pops up form to enter the game
  • Sponsor Proximity - Individual sponsor-provided content and forms (one per sponsor)

There are many details about how these worked and were configured in Liferay - more on that in the next post!

What we learned in Amsterdam

  1. Attendees aren't there to play with your app. We didn't get nearly as many people engaged with the mystery guest game as we'd hoped. About 20% of the attendees began the game, but only about 2% actually finished the game (visited all the booths, entered all the answers correctly). It took quite a bit of effort to complete the challenge, and there was limited time (the event was only a 1-day affair). So the lesson here is don't make things too hard to use! Perhaps at DevCon we may do something more technically difficult yet interesting, but for the two events we've had so far, they just weren't that into it :)
  2. There are many Android devices :) We knew this up front, but were unable to purchase and test all 8,432 Android devices the app supports, so we found several glaring bugs on certain devices (which were fixed either during or shortly after the event). Lesson: Test on as many devices as you can. Ask your friends and colleagues to test the app. Use simulators with reduced memory footprints and weird device types.
  3. Beacon ranging is useful, but cannot be relied upon for initial engagement, since it is disabled when the app is backgrounded/locked/quit.

Liferay France Symposium 2014 Configuration

This venue (Shangri-La Hotel) was a little more spread out, offering a bit more breathing room and chances for engagement. The crowd was also more technical (the first day's sessions were entirely technical). The beacon configuration here was similar to Benelux, but we had several more regions to support the additional areas, and we converted the beacon proximity events for sponsors into beacon region events (so that they worked even when phones were backgrounded/locked/quit).

What we learned in Paris

For the France Symposium, we decided to make the game part much easier to "complete" and took out the mystery guest element entirely, which proved to be too much "game for the game". Instead, we did a simple scavenger hunt (We had a Beacon region named Trésors cachés) - we hid 4 beacons in various places, and when you got close to one, you were given a hint as to where it was, and if you found it, you could enter your information for a chance to win a prize. We gave away all 10 prizes that day, and people were generally more engaged (the analytics data also revealed this fact - we had about 30% more attendees using the app and looking for secret beacons than we had at Benelux).

We also finally decided that any engagement actions in the app must begin through region monitoring, because that is what works when the app is closed or the device is locked (which is like 90% of the time for most people). So, for example, the Trésors cachés game began through beacon region monitoring (as opposed to only relying on beacon ranging and proximity to find the beacons, which would not work when the phone was locked/backgrounded/quit). The other events (entering/exiting breakout rooms, getting notified of upcoming sessions, visiting booths) were also triggered by region monitoring vs. ranging. So people are much more likely to engage with your app and your content if they can get notified when they're not explicitly staring at the screen.

And finally, we learned a hard lesson in upgrading - our beacon vendor decided a couple of days before the event to update the app I was using to program the beacons to require login and that each beacon be associated with the account used to order the beacons. This is great because previously, anyone could re-program your beacons and mess with yo stuff. But not so great when the beacons weren't properly linked to my account. So 2 hours before the France Symposium began, as I sat down to program the individual beacon UUIDs/Majors/Minors, I found that I could not! After several frantic emails to their HQ in Poland, their customer service reps were able to fix the issue - so that's +1 for Estimote.

Coming up next...

That's it for this entry. In the next entry I'll discuss:

  • How the Liferay Events app integrates with Liferay Portal
  • What kinds of beacon actions are good for different audience types, and how to not annoy people
  • Dealing with unintended audience behavior - using a Death Row analogy
  • Android vs. iOS considerations
  • Data collection, analytics and Privacy
  • Future Enhancements

Stay tuned!

iBeacons: The Next Liferay Chapter

If you'd like to know more about using iBeacons for engaging audiences and event marketing, check out my new eBook Finding Your Way Around iBeacons for Event Marketing.

Download the eBook


[Region image courtesy of TheNewStack. Proximity image courtesy of PassKit.]

iBeacons and Liferay for Audience Engagement: Part 1

General Blogs June 24, 2014 By James Falkner

This blog is part of a series of entries documenting how we are using iBeacons and Liferay to better engage our audiences at events throughout the year. [Part 1] [Part 2] [Part 3]

Update: Check out my new eBook! Finding Your Way Around iBeacons for Event Marketing.

Download the eBook

Earlier this year my colleague Ruud Kluivers introduced me to a new technology called iBeacons - it has gained a lot of traction since Apple introduced it last year, and more and more devices get support for it each day. We thought it would be interesting to apply it to our ongoing audience engagement efforts at Liferay, so the past several months I've been integrating it into our hybrid mobile app for Liferay Events. We've used it at two events so far (the Benelux Solutions Forum in May and France Symposium earlier this month), and have learned quite a bit about what worked well and what didn't work so well.

During development I found a lot of technical resources for iBeacons, but little or no research on how to apply it in engagement applications. What kinds of triggers are useful for different audiences? How often should my phone buzz in my pocket? How to avoid annoying people and having them uninstall your app and complain on Twitter? What about privacy?

This series of blog posts will attempt to document what we've done and what we've learned about getting over the hype of the new technology and really thinking about how it can deliver on its promises, without being annoying or just "fluff".

What is an iBeacon?

An iBeacon is a small Bluetooth LE transmitter that continuously sends out a unique code up to about 50m. When sprinkled throughout a space, these beacons can be "seen" by devices capable of receiving the transmissions and can trigger location-aware events like notifications, automatic app navigation, and other kinds of events. As each iBeacon transmits a different code, the app can respond differently based on the user’s location, providing location awareness and contextual engagement possibilities.

You may have heard of them already - several companies are using them in retail stores and other public places, including Apple, Macy's, Fluwel's Tulpenland, Major League Baseball, and more. These companies provide engaging content depending on where their audience is at the moment, making the experience more enjoyable while at the same time developing a closer relationship to customers. It's effective outdoors and indoors where there is often no way to receive GPS signals from satellites. It's cool, but can be creepy, so keep reading...

You got iBeacons to work - congratulations! Now what?

Making iBeacons work at it's lowest level is pretty straightforward - there are some really good blogs and even ready-made libraries (like this one we developed for Titanium) for various mobile and desktop operating systems and the APIs for talking to iBeacons are pretty straightforward (you turn it on with one API call, then it calls your callbacks when various beacons are detected or un-detected). But true benefit comes not just from the technology, but also in understanding human behavior and and applying it to your specific situation.

For our use case, we wanted to provide additional value for attendees, sponsors, and event staff, as well as show off Liferay (of course!). To that end, our goals specifically were:

  • To showcase Liferay’s flexibility and power to integrate with bleeding-edge technology and show how it can be used to more fully engage Liferay users through a combination of mobile and desktop features.
  • To provide great value to attendees by giving them location-aware contextual information and interactive features to help them get the most out of their investment in attending, without being annoying.
  • To provide great value to potential event sponsors to help them drive booth traffic, and be able to interactively engage with attendees for awareness, metrics, and lead generation.
  • To provide great value to Liferay event staff for pre-planning, realtime, and post-event metrics to measure effectiveness of the agenda, venue layout, special events, and other items associated with the event.

Knowing Your Audience

This is the most critical part of any effort to engage an audience - you have to know your audience. In this case, Liferay has held different kinds of events with different kinds of audiences over the years, and we're constantly learning new things about what drives people to attend and what they're looking for. Why do people attend?

  • To learn more about past, present, and future Liferay technology and overcome business and technical challenges
  • To network with other companies and people with the same real world problems
  • To meet our community of experts (employees, partners, sponsors, ISVs, developers, etc)

Attendees come from a broad spectrum of business and technical knowledge, vertical industries, and professional roles, so it's important to understand exactly the kinds of people you expect to engage before doing so. For example, a more business-oriented professional will seek information on ROI, ability for Liferay and its community to support a specific business need, and contacts from similar professionals with the same role (e.g. CTO-to-CTO encounters). A more technical-oriented attendee wants to know specifications, architectural best practices, upcoming features, wants to attend workshops, and wants to understand how Liferay and related software will work in their technical environments.

So how does this knowledge translate into iBeacons? Well, for starters, understand this: attendees aren't there to play with your app! They can do that at home. They are physically there (and spent money to be there) because of the above reasons, which involves person-to-person exchanges. No amount of clever smartphone notifications can replace intimate contact with experts or tell them why their Liferay deployment is slow. However, mobile apps and iBeacons can be an effective tool to help them get the most from their investment in your technology and your event, giving supporting information about the venue and sessions, or suggesting which sessions to attend, or encouraging them to visit sponsor booths using gamification. And to be honest, there is still a certain "coolness"/newness factor that exists with iBeacons which will wear off eventually. But in summary, there are many ways to engage, so you need to know your audience and decide what you think they will want.

One other thing to consider: iBeacons are relatively new, and not every device supports them, so don't assume all of your audience will be able to use them. In particular, it requires Bluetooth 4.0, found only on newer iOS and Android devices. So, for example, we can't (yet) replace the paper surveys and "railpass" games that we typically have at events with iBeacons, as not everyone would be able to participate.

Knowing the Physical Space

Before deciding exactly what you want your app to do, consider the typical space in which they (and your beacons) will be. For our purposes, the main consideration is the overall size of the venue and number of rooms. At it's lowest level, iBeacons transmit an EM signal at a frequency of about 2.4GHz. These signals can be attenuated or blocked entirely by metal and concrete, other 2.4GHz signals (think microwaves and cordless phones), and water. And ideally your space will be filled by lots of moving buckets of water (a.k.a. attendees), so that can present challenges.

In the ideal case, you can place iBeacons in each of your discrete areas (breakout rooms, main hall, entrance, cafe, etc) with no signal overlap. This provides the most possibilities with location awareness, because you'll be able to accurately detect and respond to movement (or lack thereof) into, within, and out of those areas. Of course, this never works in practice, because most buildings and rooms are square, whereas the Bluetooth signal emanating from each beacon is spherical. Round peg into a square hole, that sort of thing. But you can get close by placing beacons in strategic spots, using walls and other blockers to try to contain the signal to the areas in which you want them, and adjusting the signal strength. Walk around the venue beforehand, and see what you've got to work with. For example, here's the quick & dirty diagram from the Benelux Symposium:

We ended up using two beacons turned "all the way up to 11" to cover the Grote Zaal space, and placed them in the rafters. The rest of the areas were served by a single beacon each, and then we had individual beacons for each sponsor booth as well. We had plenty of "overlap" and the potential for attendees to get flooded with notifications, so there is a lot of code to deal with that. We also wanted to re-use it for different events and audience types, so there are lots of configuration options for the app. More on the technical side of things in a future post!

After you place your beacons, walk around with any 3rd-party iBeacon detector app and see what it sees. Also, code in a "debug" easter egg into your app, to make your app report what it "sees". There is one in the Liferay Events app (press and hold your finger on the Gallery title bar, then return to the main screen, and you'll see it!) 

What we learned is that even though the Benelux space was more compact than I'd envisioned, it was still possible to map out discrete locations and serve them with iBeacons by placing the beacons in strategic (and hidden) spots and tuning and broadcast power to suit the space. Assume you will have overlap, and that people will do unexpected things such as walking into and out of a space quickly, detecting beacons through what you consider impermeable walls, or lingering in a "Lagrange Point" between two overlapping beacons :) If your app is to be effective, you must consider these kinds of behaviors.

In the next few posts we'll get into more technical detail, including:

  • True engagement - not just popups
  • Understanding and programming beacon regions and proximities
  • What kinds of beacon actions are good for different audience types, and how to not annoy people
  • Gamification possibilities and what we learned
  • Dealing with unintended audience behavior - using a Death Row analogy
  • Android vs. iOS considerations
  • How the Liferay Events app integrates with Liferay Portal
  • Data collection, analytics and Privacy
  • Future Enhancements

Hopefully this intro whets your appetite for future posts. See you next time!

iBeacons: The Next Liferay Chapter

If you'd like to know more about using iBeacons for engaging audiences and event marketing, check out my new eBook Finding Your Way Around iBeacons for Event Marketing.

Download the eBook

Liferay Cloud Services Beta

Company Blogs May 20, 2014 By James Falkner

UPDATE: Liferay Cloud Services has a new name! See this blog post for details on Liferay Connected Services!

Today we are announcing an open Beta of Liferay Cloud Services! If you're interested in participating, check out the landing page - you won't be able to miss the big form on the right (there are only 50 slots left - hurry!).

What is Liferay Cloud Services?

"Liferay Cloud Services is a new online platform that offers tools and services that will help our customers suceed on Liferay projects."  That sounds great, right? So, for example, you have 10 Liferay servers in your farm - do you know if they are all up to date? Do you want to manually go through each one and update them? What if one is running low on memory - wouldn't it be great to get an alert on your mobile and correcting the issue instead of receiving an angry customer call an hour or two later?

LIferay Cloud Services will do all that - and more! The more: Fix Pack Management, Metrics, Dashboards, and Alerts. I won't ruin the surprise here, so please check out the Beta landing page to see more information about these. The best part is we can easily add new services without impacting existing services. It's all on the cloud!


Liferay Cloud Services will be available for systems running on 6.1 CE/EE GA3 or later (and of course 6.2 CE/EE GA1 or later). And yes, my community brothers and sisters, it is also available for Liferay CE (although limited, still very useful, otherwise I wouldn't be blogging about it here!) It also works with on-premesis or cloud deployments, so we can target the maximum number of kinds of deployments.

Beta Program

This beta program is intended find issues (what??), and get real feedback from real customers using it in an as-close-to-real-as-possible way. It also gives our community a way to interact directly with the product team(s) at Liferay, before it is finally launched. We learn a lot about our products from you, we rely on you to tell us what to fix, what to improve upon, and how to best meet your goals. In short, we cannot be successful without you, so we really need your help! The beta is a great way to do this, so I highly recommend you sign up. There are only 50 spots total, if you're interested, you should move quickly!

What's Next

The good news: it's a cloud-based service, and the team is looking at a range of new features to offer to you - not only health services, but also processing services (e.g. offline video transcoding), more analytics, and others. So get involved in the Beta today and see what it can do for your Liferay deployments!

Amsterdam Liferay Community Meetup

General Blogs May 16, 2014 By James Falkner

If you're in or around Amsterdam next week, we're having a community meetup prior to the Benelux Solutions Forum event and you're all invited! Join our local community of rockstars for some knowledge sharing, and drinks in the center of town at the Café The Flying Dutchman [map], May 19 (Monday) starting at 20.30! The entire community is invited (you don't have to be attending the event the following day).

There is no agenda or set presentation, but there will be plenty of great conversation and interesting characters from our Dutch community, along with myself and a motley crew of Liferay'ers from around the world. Looking forward to seeing everyone!

If you're planning on attending, please let us know how many you will be in the comments below, to give us some idea of how many of us will be there!



Liferay Benelux Solutions Forum - Amsterdam

Company Blogs May 12, 2014 By James Falkner

As part of my community party planner role at Liferay (aka community manager), I try to get out and meet many of you at industry and Liferay conferences and other events. I think it's really important in this webified world that we keep the human touch at least a little! At our events I get to learn about new cultures and make new friends, learn how people are using Liferay and getting along in our community, and try to contribute back a little through knowledge sharing on what I've learned over the last couple of years.

Next week I'm attending the first ever Liferay Benelux Solutions Forum in Amsterdam, and wanted to let you know about some of the awesomeness in store for you, and encourage you to check it out if you can make it!

First, I'm happy to go to the home pitch of one of our most active and influential user groups, the Liferay Netherlands User Group, housing many of our community rock stars, indicative of the selfness nature of our Dutch Liferay community and surrounding regions. When people like this come together, it makes for one of the best places to come to learn more about our community, and about Liferay. It reminds me of an experience I had last year at another Liferay event (actual picture over there on the right), where a couple of engineers from Liferay and other companies sat together with a customer for 15 minutes and figured out a perplexing issue on a production Liferay server -- during one of the breaks. That would have normally taken countless emails, IMs, and phone calls. It happens all the time at Liferay user group meetups and official conferences such as this one when sharp people get together, and I haven't yet seen the Dutch disappoint!

It's also one of our first "big" events of 2014, with what looks to be some fantastic speakers, and I can't wait to see the first official roadmap presentation of the year (no pressure, Ed!), hopefully with some details on what lies in store for the future of Liferay, version 7 and beyond. Also featured at the Solutions Forum will be the return of the Expert Exchange discussion groups, in the style of the World Café. It's speed dating with basically every other attendee on various focused topics related to getting the most out of Liferay as your audience engagement platform. I loved this style of event last year, and learned some interesting ways our customers and community are engaging their own communities of partners, employees, and customers.

On a more technical level, I've had the privilege to work on some exciting new technology we'll be demoing at the Benelux Solutions Forum, using Liferay and iBeacons. We're going to sprinkle several of them throughout the venue and in conjunction with our Liferay Events mobile app [iOS | Android] you'll receive localized and contextually-aware messages and helpful hints throughout the event (with a few surprises thrown in for good measure, none of which involve tracking your every move! I value privacy as much as you!). We'll also demo how the whole thing works, from the Bluetooth transmitters, through the mobile environment, and into Liferay as the core engagement platform, hopefully spurring you to think and ask about how you can get more out of your investment in Liferay.

Finally, the venue itself (Pakhuis De Zwijger) has a lot of history (ok, not as much as the city itself, but you get the idea). It used to be a cold storage facility that fell into disrepair in the late 20th century, and was planned to be demolished to make way for a new bridge over the nearby haven only to be brought back to life thanks to some innovative dutchies, and is now a "Cultural meeting place, multi-arts center and gallery, with multimedia studios" (and soon to be acquiring a few strategically-placed iBeacons). A bridge through a building! Nice one.

So I hope to see you there next week!

PS: I'm also dropping in on the Vaadin crew later next week after the solutions forum, for a Liferay+Vaadin developer hangout. More on this later, but be sure to sign up if you are into great user experiences and awesome portal platforms, with a great developer community behind it all. How can you say no to that?

L.A. Liferay Community Meetup

General Blogs May 1, 2014 By James Falkner

If you're in or around the L.A. area next week, we're having a community meetup during Gartner's "Portals, Content, and Collaboration" event and you're all invited! Join me and several others for some technical and non-technical presentations/discussions, knowledge sharing, and free drinks/food in downtown L.A. at the Caña Rum Bar [map], May 5 (Monday) starting at 8pm! The entire community is invited (you don't have to be attending PCC) and Xtivia and Solea have graciously decided to sponsor it, making it all that much more fun and exciting :)

Registration and participation is free. We're going to do a few short presentations to get things started, and I would love to see any of you in the area drop by and say hi, discuss or ask anything you like, and hopefully learn a few things about Liferay in the process from our community leaders and experts. Our fearless presenters will discuss:

  • The Multimedia Blog Journey
  • Nuggets of Wisdom
  • 5 Common Trends in Liferay Implementations

We'll also be giving away T-shirts and books and a few other goodies. So if you're in the area, be sure to sign up and I will see you next week! 

Liferay 2014 Marketplace App Contest

General Blogs April 16, 2014 By James Falkner

It's back! To celebrate and reward our outstanding community of Marketplace developers, I am happy to announce the opening of the 2014 Liferay Marketplace App Contest! Last year, we had over 70 submissions and many winners (so many that we had to extend the review period an extra week). We saw some really great and innovative apps, and also saw a nice bump in Marketplace activity in general. Last year's winners saw an average of 7x increase in downloads and 2000+ views! So while the prizes are nice, the increased visibility (and bragging rights) are even sweeter. So we're doing it again.

Contest Timeline

  • April 16: Contest Open
  • August 8: Last day for submitting apps
  • August 25: Winners announced

That gives you around 4 months to complete and submit apps for the contest. Note that apps that were already on the Marketplace as of December 31, 2013 are not eligible to be entered into the contest, except for those apps submitted last year that did not win anything (giving our previous contestants a chance to improve and re-submit!).

What can I win?

This year, we have 4 categories: Community/Free, Community/Paid, Commercial/Free, and Commercial/Paid. In each of those categories, there is a chance to win a grand prize (a paid trip to a Liferay Conference, plus other benefits), or a runner-up prize (US $300 gift cards, plus other benefits). See the contest page for more details and official rules.

Why should I enter the contest?

Besides the great prizes offered, your apps will be listed in various places ("Featured Apps", contest follow-up, and at future events) which has historically been shown to greatly increase your apps visibility and subsequent downloads and activity. Not only that, you will forever be recorded in the annals of Liferay history as an awesome app contest winner, and can even make tee shirts about it. Woo!

So how do I compete?

It's easy:

  1. Develop a Liferay App
  2. Submit App to Marketplace
  3. Fill out contest entry form
  4. Win! (Maybe)

Remember, you have until August 8, 2014 at 11:59pm US/Pacific to enter, so be sure to check out the Marketplace Developer Portal for everything you need to get started. Don't forget, even after you submit the app itself to the Marketplace, you still need to fill out the contest entry form!

We've seen a lot of great apps this year in the Marketplace (I happen to use several on a daily basis, and I am immensely grateful to the developers of those apps). I can't wait to see what our community can do this year!

Liferay Mobile SDK Now Available

Company Blogs April 1, 2014 By James Falkner

Today Liferay released the first version of the Liferay Mobile SDK! [Download | Documentation | Project Page]

The Liferay Mobile SDK makes it super-easy for mobile developers to integrate mobile apps with Liferay Portal, by taking care of common tasks like authentication, exception handling, parsing responses, and exposing Liferay's JSON web services in their preferred mobile app development environment (e.g. Objective-C interfaces for iOS developers, Java interfaces for Android, and potentially others in the future). Custom objects and their web services (created via Service Builder) can also be accessed through the Mobile SDK just as easily as core services.

The Liferay Mobile SDK is compatible with Liferay Portal 6.2 and later. The Mobile SDK's official project page gives you access to the SDK releases, provides the latest SDK news, and has forums for you to engage in mobile app development discussions. Bruno Farache also did an excellent blog post for the beta release earlier this year with some working code examples and technical discussion.

Download and Install

There are two ways to get and use the Mobile SDK:

Liferay IDE / Developer Studio / Eclipse Plugin (for Android apps)

For Android developers, Liferay provides the Liferay Mobile SDK Eclipse plugin for you to use in developing your mobile Android apps. It's powerful Mobile SDK Builder generates libraries that enable your app to communicate with Liferay Portal and with the custom portlet services deployed on your Liferay Poral instance. Check out the Developer Guide for details on how to install the plugin into your environment.

Manual Installation (iOS / Android)

For Android and iOS developers, manual installation is pretty simple: download a JAR or ZIP file and import it into your project, either in Eclipse, XCode, or other development environment. The Developer Guide contains details on how to install the SDK into virtually any mobile development environment.


Due to the close relationship between the Mobile SDK and Liferay itself, the Mobile SDK follows a similar release version scheme, and each release works with both CE and EE. Multiple Mobile SDKs can also be used in parallel (e.g. to support multiple major Liferay releases in a given app) thanks to the versioning present in the package namespaces.

Source Code

As an open source project, the Liferay Mobile SDK's source code can be found it its main Github repository or as a downloadable zip bundle.


Contributions are the lifeblood of our community, and as an open source project, the Mobile SDK is no different. The process for contribution to the SDK is the same process used for Liferay itself. Simply fork the repository, make your contribution, and issue pull requests to the project lead(s). It's a great way to get involved and to give a little back to our community!


The Mobile SDK's official documentation lives in the Liferay Developer Guide, covering everything you need to know, including detailed guides for installation and development in both Java (Android) and Objective-C (iOS and XCode) and will be updated as necessary as new features are added or changed.

Getting Support

Support for the Liferay Mobile SDK is included in Liferay's Enterprise Subscription, which provide regular service packs, a commercial SLA, and more.

If you are using Liferay Community Edition, visit the project site or check out the Mobile SDK Forums to find out more about the myriad avenues through which you can get your questions answered.

Bug Reporting

Like other Liferay projects, the Mobile SDK project uses to report and manage bug and feature requests. If you believe you have encountered a bug in the new release (shocking, I know), please be cognizant of the bug reporting standards and report your issue on, selecting the Mobile SDK Project and release as the value for the Affects Version/s field.

Feature Requests

If you have a great idea for the next Mobile SDK, be sure to file a Feature Request through the JIRA project or on the Ideas Dashboard (they both go to the same place!). If you have the time, consider contributing your amazing new idea to the project, we in the community would love to see what you've done!



Liferay 6.2 CE GA2 Now Available

General Blogs March 21, 2014 By James Falkner

Today Liferay released an update of its flagship software: Liferay Portal 6.2 CE GA2! [Download] [Quick Start]

This update corrects several issues found since the GA1 release in late 2013 found by our community and Liferay's continuous testing teams. Want to know more? Read on!

Release Naming

Following Liferay's official versioning scheme, this release is Liferay Portal 6.2 CE GA2. The internal version number is 6.2.1 (i.e. the first update release of 6.2). Future CE releases of 6.2 will be designated GA3, GA4, .. and so on (assuming they are needed to fix issues, which is not always the case). See below for upgrade instructions from 6.2 CE GA1, 6.1.x, 6.0.x, and 5.x.


You can find the 6.2 CE GA2 release on the usual downloads page. If you need additional files (for example, the source code, or dependency libraries), visit the additional files page.

Source Code

As Liferay is an open source project, many of you will want to get at its guts. The source is available as a zip archive on the downloads page, or in its source code repository on Github. Many community contributions went into this release, and hopefully many more in future releases! If you're interested in contributing, take a look at our contribution page.

What's New / Changed?

This update fixes many issues, but here are some of the more important and/or popular ones that you may be interested in:


The Liferay Documentation Team has been continuously adding and improving on the official documentation. This includes updated javadoc and related reference documentation, an updated User Guide and Developer Guide, and a new properties listing in convenient web page form. Our community has been instrumental in identifying the areas of improvement, and we are constantly updating the documentation to fill in any gaps.

Support Matrix

Also, Liferay recently published the official support matrix for 6.1 and 6.2, which lists the exact versions of software that Liferay is supported with. You no longer have to wonder which exact version of GNU Hurd you can run Liferay on (Hint: The Hurd is not supported :) ).

Liferay Marketplace

Most Liferay-authored plugins were updated to support 6.2 GA1 when it was first released, and remain compatible with this updated GA2 release.

If you are a Marketplace Developer, and have authored a 6.2 CE GA1-compatible app, you should ensure your app continues to work with this 6.2 CE GA2 release. It is Liferay's aim to remain compatible within a given release family, so in the unlikely event that your app works with GA1 but NOT GA2, you will need to make any necessary changes and re-submit, and let the Marketplace team know about any incompatibilities you discovered. Chances are you will have nothing to do (since you declared compatibility with 6.2.0+, which includes 6.2.1).

Also, Marketplace developers should be sure to check out the new Marketplace Developer Portal, and get access to a one-stop shop of resources for... well, you get the idea. It's for app developers. Go there and learn.

Bug Reporting

As always, the project continues to use to report and manage bug and feature requests. If you believe you have encountered a bug in the new release (shocking, I know), please be cognizant of the bug reporting standards and report your issue on, selecting the 6.2.1 CE GA2 release as the value for the Affects Version/s field.


Good news for those of you on 6.0 or prior! Liferay introduced the seamless upgrade feature with Liferay 6.1. Seamless upgrades allow Liferay to be upgraded more easily. In most cases, pointing the latest version of Liferay to the database of the older version is enough. There are some caveats though, so be sure to check out the Upgrading Liferay chapter of the Liferay User Guide for more detail on upgrading to this release.

Getting Support

Support for Liferay 6.2 CE comes from the wonderful and active community, from which Liferay itself was nurtured into the enterprise offering it is today. Please visit the community pages to find out more about the myriad avenues through which you can get your questions answered.

Liferay and its worldwide partner network also provides services, support, training, and consulting around Liferay via its Enterprise Subscription.

Also note that customers on existing releases such as 6.0 and 6.1 continue to be professionally supported, and the documentation, source, and other ancillary data about these releases will remain in place.

What's Next

Of course we in the Liferay Community are interested in your take on the new features in Liferay 6.2 and the updates in this GA2 release. Work has already begun on the next evolution of Liferay, based on user feedback and community ideas. If you are interested in learning more about how you can get involved, visit the Liferay Community pages and dig in.


This release was produced by Liferay's worldwide portal engineering team, and involved many hours of development, testing, writing documentation, translating, testing some more, and working with the wider Liferay community of customers, partners, and open source developers to incorporate all sorts of contributions, both big and small. We are glad you have chosen to use Liferay, and hope that it meets or exceeds your expectations!

In addition to Liferay's engineering staff, a special thanks goes to the many open source developers who volunteered their time and energy to help with the release, whether it was bugfixing, idea generation, documentation, translations, testing, or other contribution that helped to improve this release. Check out the Community Contributor Hall of Fame and be sure to thank them if you run across them in the community!

Marketplace E-Commerce Now Available

Company Blogs March 18, 2014 By James Falkner

The Liferay Marketplace has come a long way since opening its doors in August 2012. Since then it has grown almost 5x in number of apps and has registered more than 600 developers from over 25 countries. And we continue to evolve the Marketplace so that it creates value for Liferay customers, while staying relevant to our community of partners and developers.

I'm happy to announce today that the Liferay Marketplace now supports paid apps, using the much-anticipated new E-commerce feature of the Marketplace! The Liferay Marketplace engineering team and our community of Liferay developers have combined efforts over many, many months to bring this fantastic opportunity to our ecosystem, and we hope it meets or exceeds your expectations. With E-Commerce, the vision put into motion several years ago reaches a new milestone, one that benefits everyone that has chosen Liferay for their web platform needs.

How does it work?

If you've developed and published an app on the Marketplace, you are already familiar with the process, but there are some new concepts in play with the advent of E-Commerce:

  • License Types and Regional Pricing - As the developer, you have ultimate control over how to price your app. You choose the license type (Standard vs. Developer), license terms (Perpetual vs. Annual), pricing structure (bundled pricing and discounting), and regional availability. You can specify discounted prices for bulk orders, or different prices (and different currencies) in different purchasing regions. You can also optionally offer paid support for your software, giving purchasers peace of mind that you stand behind your paid apps. For example, suppose you offer a perpetual license for your app at a one-time cost of €100. You can optionally add support for an additional €20 per Instance per year. If, on the other hand, you want to offer an annual license, you could charge €100 per Instance per year for an unsupported license, or €120 per Instance per year for a license that includes support (an Instance refers to a single installation of Liferay Portal, which corresponds to one (1) Liferay Portal .WAR file.)
  • Payments - The Liferay Marketplace uses PayPal for payment processing, developer payments, and for purchasing paid apps. You will need a PayPal Verified Business Account to publish paid apps. Liferay will automatically collect Sales Tax / VAT for most countries, which is typically one of the most complex issues in international E-Commerce.
  • 30-Day Trials - You can also offer free trial licenses, which allows consumers to test drive your apps before they purchase, to ensure that it meets their needs. Once satisfied, your customers can upgrade their licenses at will.
  • Revenue Sharing - For each app sale, you will receive 80% and Liferay will receive 20% of the sales proceeds. We believe this type of fee structure is extremely competitive vis-a-vis other online app marketplaces, and Liferay uses its share to continually improve the Marketplace and Liferay ecosystem.

Getting Started and Staying Informed

Be sure to bookmark the new Liferay Marketplace Developer Portal and get access to all of the resources you need to design, develop, and distribute apps for the Liferay Portal platform. Whether you're looking to showcase your capabilities or reach new customers, becoming a Liferay Marketplace developer is your launching point to half-a-million-plus Liferay deployments worldwide, and this new developer portal is the best place to get to all of the resources you will need for app development.

Be sure to register yourself as a developer (either as an individual or a company). You will need a account to do this (it's free to register on!).

During the app publishing process, you will select whether your app is a Free or Paid app. Publishing a free app remains free (as in beer). The first time you attempt to publish a Paid app, you will be required to upgrade your account to enroll as a paid app developer. This ordinarily requires a $99 annual fee, but for the remainder of 2014, Liferay is waiving this fee for all developers as an added incentive to get started with paid apps (yeah!). You will also need to provide a tax form to identify yourself or your company for tax purposes, and have an active PayPal account to receive periodic payments from Liferay for the apps you sell.

Once you've upgraded your account for paid apps, you're ready to begin publishing!

Develop a Paid App

Since apps are nothing more than collections of individual plugins, your first step in developing a Marketplace app is to develop the functionality in the form of one or more Liferay plugins. The Liferay Developer Guide contains everything you'll need to develop apps.

Security and trust are important concepts, and become even more relevant with the advent of E-Commerce and paid apps. To that end, paid apps must enable the Liferay Plugin Security Manager (this has been optional for free apps, but is required for paid apps). The Liferay Developer Guide has details on how developers can make use of this.

To reach the widest possible customer base, you are encouraged to develop apps for both the Liferay CE and Liferay EE software versions (this is not new, but important to re-iterate when considering paid apps). Developers wishing to target EE can request a free developer license.

Publish a Paid App

Now the fun part begins - getting paid for all that hard work! Check out the latest additions to the Liferay Developer Guide, where you'll find a complete walk-through of publishing a paid app, including details on licensing and pricing options. E-commerce in a multi-cultural, multi-currency, multi-governmental world can be challenging but the Marketplace team has worked with our community to make it as painless and simple as possible, but no simpler than that!

Also, be sure to read the App Pricing, App Metadata Guidelines and App Review Process to understand how each app is reviewed. These guides will help you choose the best options for your paid apps, and ensure a smooth flow during the publication process!

Managing Paid Apps

Once published, you can track the sales performance of your apps, as well as see order histories, and manage purchased licenses across all of your customers. When you're ready, you can publish updates to your apps for customers to provide bugfixes or new features.

Enhanced metrics have been added for developers to track the performance of their apps over time and spot important trends in the lifecycle of their apps.

Buying Paid Apps

Purchasing a paid app is straightforward - The Marketplace uses the familiar concepts of shopping carts and "checking out". During the purchase process, you'll create a shopping cart and specify how many of each license type you wish to purchase. During the checkout process, you'll be directed to PayPal where you can pay with a credit card, existing PayPal balance, or other payment option. You can also elect to pay via a manual invoicing process, which is completed via email. Paid apps will only function with a valid license.

After the sale, customers can upgrade or renew their purchased licenses using the same concepts as in the initial purchase.

More Questions?

Check out the Frequently Asked Questions forum on the Developer Portal to get answers to questions such as "What is the Marketplace Refund Policy?" or "Why is app licensing only on a 'per Instance' basis?" and many others.

Reporting Problems

If you have additional questions about how the Liferay Marketplace works, please post your questions on the Marketplace Forums. If you have issues with accounting, billing, or finance-related questions, contact the Marketplace team.

In Closing

The Liferay ecosystem thrives on the creativity and innovation of its worldwide community of developers, service partners, ISVs, and contributors. The Liferay Marketplace and its new E-Commerce capability gives all of us new opportunities to grow with Liferay and showcase the power of a solid Liferay platform coupled with a rich selection of apps and functionality from the community, both free and paid. There are a lot of really great ideas out there, and it's great to see them available through this Marketplace!


Dumping ADT+WCM Template Variables

General Blogs February 18, 2014 By James Falkner

Ever wonder what exactly is available to you as a WCM Template author, or ADT wizard, or Theme developer? Ever forget the name of that weird request variable that gives you the current URL? Or wonder what happened to VelocityVariables in 6.2? Of course you have. Well, wonder no more! With this handy context dumper, you can see all of the available utilities, variables, their values, and their callable methods from your template, ADT, or theme context. Here's what it looks like:

It also dumps a hierarchical view of the request variable at the bottom of the listing, for ADTs and WCM Templates:

Just copy and paste this code into your theme (should be compatible with 6.2 and 6.1), ADT or WCM template, and explore. If I had more skills as a designer I'd make this into some kind of auto-expanding AlloyUI table with music. But I don't, so I can't. Any volunteers?


Special thanks to Chaquotay for the base code. I had to modify it because if you try to do a deep expansion of everything (i.e. the .data_model special variable), it opens a black hole in your server as it recursively tries to expand everything in the universe.

Community Roundup

General Blogs February 7, 2014 By James Falkner

Hello, wonderful World of Liferay! It's (way past) time for another Community Roundup! This is an ongoing (but sadly sporadic) series of blog posts that summarize the latest news from around our community. As your community manager, I'm very humbled and thankful for all of you who take the time to participate or give back to our community in some way. It would be a sad and lonely place without you, so I will try and highlight relevant news and activities from around the community.

First I'd like to recognize our awesome Top Contributors from the last half of 2013. These women and men have gone above and beyond the call of community in many ways, and deserve a hearty thanks for their contribution. Andrew, Jan, Dhrituka, Nagul Meera, Denis, and Pier exemplify what our community is all about by spending their time and resources helping others. Thank you to them and to all that selflessly contribute to our little corner of the world! Now, on with the links!

  • This year, we're renewing our focus and efforts on the Liferay Developer experience. There are many different areas we can improve, and here are a few we've identified that we're working on for you:
    • Getting started / onboarding - Liferay has historically had a steep learning curve. Aside from ongoing efforts to improve documentation, usability, and quality of the platform, we're also trying to add content for new and existing developers to quickly get up to speed on Liferay and related technology.
    • Developer Network - a new site dedicated to developers, to put the resources you need only a few clicks away, organized to not only for participation (e.g. blogs and forums), but with easy to follow guides, samples, and content geared toward development with Liferay.
    • Forum improvements, such as additional view options (best answer first), categorization of developer topics, badging/achievements, and more ways to find relevant and timely posts besides "Recent Posts" (feel free to add comments in this thread!).
    • More interactive/live tech sessions - We've done these sporadically over the years, and I'd like to make it a regular (i.e. scheduled) series with focused topics in each session. No "Intro to Liferay" here!
    • Much of it is still in progress, but hopefully in the next few months you'll start to see more content dedicated to our community developers, and we can together make it a fun and exciting place to be :)
  • As a community grows, it becomes more important to document the nature of the community and expectations between its members. This gives the community a greater sense of identity, direction, and purpose, and helps new members understand what the community is all about and what they can expect from it when considering joining. To that end, our leadership team has created a Community Ethos for this purpose, documenting who we are and what we collectively stand for.
  • Last year, Bitergia worked with Liferay to better understand our project and the trends in the development of Liferay in our community. It's an interesting read on how we're doing, and we're using much of this data to drive community initiatives in the coming year.
  • Peter Mesotten has written up a nice piece on Liferay 6.2 "Under the hood". Also, I wish Liferay had a Marketing "machine"!
  • Although we get a ton of community traffic on the forums, it is not the only place where one can get some awesome Liferay action. Check out the Liferay leaders on, who tirelessly help our community wherever they may be needed.
  • The Liferay Portal 6.2 Community Beta program was a smashing success, with over 70 participants, 130 issues reported, and 81 resolved! As you can see, a lot of work went into this release, both from Liferay staff and our generous and ambitious community, and I would like to personally congratulate and thank each and every person who contributed to this release. Participants even got a fancy custom tee shirt for the program! Expect more in the coming months as we march toward more releases!
  • Since the opening of blogs on to the community last year, I've seen a lot of really great blogs by many of you. We're going to be making it even more of an exciting adventure in the near future, through regular highlighting of blogs, and adding categorization so you can more easily subscribe and find blogs of interest. In the meantime, we have a new Community Content policy guide which covers things about what is and is not allowed in content. Please give it a read if you are contributing on our forums, wikis, or blogs!
  • JavaScript is cool again (but you can still write bad JavaScript)! And several traditionally server-side programming paradigms like MVC are moving into that place where JavaScript has awesome support - the ubiquitous client side browser. Check out Sampsa's experiments with AngularJS!
  • Speaking of Frontends, Liferay's very own Frontend engineer Zeno Rocha (@zenorocha) has been nominated for Net Awards' Young Developer of the Year! Take a moment and vote for Zeno, and let's see if this Liferay guy can make it big time!
  • Do you love Jenkins? We certainly do. We even continuously develop and integrate Liferay with it. Manuel has written a sweet Jenkins Dashboard portlet for Liferay, with awesome status graphics and a nice AlloyUI-based user interface.
  • Nightly builds of portal have begun again (after quietly and accidentally dying for a brief period of time). This is a nightly build of the master portal branch, and is very useful to see if things have been fixed, or to check out upcoming new features. It also likely has bugs, instability, and other attributes of most open source nightlies :) Occasionally the build fails entirely, so there may be a day or two lapse of the builds, but rest assured we know who broke it (evil grin).
  • I am always a fan of clever ways to do things programmatically. Who wants to click and click and click? Check out Daniel's example of programamtically setting workflows on Document Library folders!
  • Radio Liferay is back in action, with some really awesome episodes from Alberto Chaparro, Iliyan Peychev, Daniel Sanz, The folks behind Valamis, and more! If you have pressing questions you'd like answered, head over to the Radio Liferay Google+ Community and ask away!
  • All about versioning of Liferay's document library and how to integrate it into Amazon S3, from our friends at
  • The Liferay Spain office holds regular Tech Talks about focused technical topics in and around Liferay. You can see many of the slides and code at in the repo, and stay tuned for more talks in the future!
  • Getting involved with a local Liferay User Group is one of the best ways to grow your Liferay chops. New user groups in China, Seattle, Tunisia, and Vietnam have started, and are looking for new members! If you are interested in starting your own User Group, there are new resources (and a nice video intro from Savoir-faire Linux) available on the User Group site. And don't miss our user group's and local community's upcoming events, such as Frankfurt, Portland (Oregon), Bangalore, Bloomington (Minnesota), Den Haag, and more!
  • Support RTL (Right-to-left) languages and Bi-directional pages is really important in our multi-cultural and multi-language projects, especially in the Arabic world. Thanks to the work from Iliyan and several others, Liferay now has exceptional support for this, and most of it is automatic.
  • From the releases desk: If you're watching the releases dashboard, you'll know that there have been recent releases of Liferay Portal (6.2), Liferay Faces (3.1.3), Liferay Sync, and Liferay IDE (2.0)! Next up will be Social Office 3.0, and the Liferay Mobile SDK will go Beta. Lots of new goodies to get us started this year!
  • The Liferay conference season gets underway early this year, starting with the popular Portal Solutions Forum in May in Amsterdam. The full schedule will be released soon, with new conferences in many yet-to-be-visited places, so stay tuned!
  • Meera Prince (also a top contributor from Q4 2013) shows us how to open any portlet inside an AlloyUI popup dialog window. Very handy for certain data entry portlets, as you don't lose your place on the page by having to switch pages. Thanks, Meera!
  • Ideas: everyone has them, and they drive innovation into many things in life, including Software. With Liferay's Community Ideas Dashboard, we now have an easy to use tool to let our creativity loose, and get that awesome feature or Marketplace app you've been dreaming of to become reality.
  • Speaking of Marketplace apps, we're up to around 230+ apps on the Marketplace. All of them free, but coming up in Q1 of 2014 will be the ability to sell apps via the E-commerce feature that many of you have been waiting for. Also, for those of you who wish to get notified of new and updated apps, check out the @LiferayApps twitter feed, and don't miss a single update.
  • Lots of awesome and informative blog posts on the community blogroll. A few highlights: The Nitty-Gritty: Theme Improvements and Bootstrap in Liferay, OAuth Client Portlet ImplementationLiferay Portal SSL ConfigurationFast development using Compass/Sass and Liferay PortalMicrobenchmarking Liferay Registry with JMHStaging in Liferay 6.2 - basicsCriando um ADT que acesse a estrutura de um Web Content (em português)

That's all for now. I look forward to seeing all of you out and about in our community, and hope this year brings you peace and prosperity!

DevCon 2013: Liferay WCM Apps and an Expando Browser

General Blogs November 15, 2013 By James Falkner

At Liferay's first ever Developer Conference in Berlin last month, I had the privilege to present my experiences in building apps with Liferay WCM (similar to the techniques discussed in a prior blog post, and this one too). I make use of this feature to quickly build relatively simple apps for our community, saving a lot of time during development and deployment. At DevCon, I demoed a bunch of simple apps, building up to a more complex app used to browse and modify Expando values in Liferay's Expando subsystem (this post is not about Expando specifically; for more details about Expando, check out Ray's excellent series of blog posts [1][2][3]).

In this post you will find the code from the examples shown at Liferay DevCon 2013, along with additional detail about the code above and beyond the amount I was able to squeeze in 30 minutes.

New templating Features in 6.2

In Liferay 6.2 there are a number of new features that enhance this, both in terms of security and development ease, and I briefly touched on them.

  • Enhanced Template Editor - no longer "just a text area", the new editor has automatic code completion, syntax highlighting, and more.
  • Freemarker Debugging in Liferay IDE - starting with Liferay IDE 2.x, you can will be able to do true debugging of Freemarker templates, e.g. stepping line-by-line, inspecting variables, etc.
  • Template Security Configuration - In prior versions it was possible for one to write a poorly- or maliciously-constructed web content template that could do anything its author desired. In 6.2, the default configuration now restricts that using portal properties like freemarker.engine.restricted.classes. To undo all of this (with an understanding of the consequences), you can add this to your

You can also fine-tune the above to restrict it down to just the stuff you need/want (or that your web content template developers need/want). For the below examples, the only ones that do not work without this are examples 8 and 9, as they use a Class.forName as an example (which is not needed with Freemarker, see below). Other examples should work without any extra configuration.

Examples from DevCon

The examples I showed were done so in a particular order, from super-simple to more complex, in order to demonstrate some of the important concepts one needs to know to build apps with WCM. So I will repeat this here, using snippets of code with explanation below each.

All of these apps are written in Velocity, however I have started using Freemarker for new stuff, due to its (what I believe to be) superior feature set (like a ton of cool builtins, sophisticated macro features, stronger typing, no silent failures, and more). These apps are all simple enough to be easily converted to Freemarker, but I have not yet done so. It would be a good exercise for Velocity users who may be looking to pick up Freemarker skills. Also, for Freemarker and Liferay fans, check out Andreas Magnusson's awesome solution for using Freemarker to render true portlet views, with storage and versioning of templates provided by Liferay's Document Library.

Each app consists of a Liferay WCM Template, which is used to render a WCM Article based on a WCM Structure. Since the point of this is to demonstrate features using the templating bit, the structure is not important, and a 'dummy' one is used. However, structures with multiple fields can be used to essentially provide configuration options for the app if so desired.

To use these examples, simply create a WCM Structure with one or more fields, then create a template associated with the structure using the example code, and then create an article based on the structure, and add it to a Liferay page.

Example 1: The Hello World app

About as simple as you can get. It shows you how many users are registered on the Liferay instance on which it runs. It also shows how to access structure field values (e.g. if you wanted users of your 'app' to be able to provide customized values for one or more features in your app, using WCM structures)

Example 2: A sucky Hello World app

This is the same app, but with horrible performance, showing what happens when an article is rendered that has a lot of code or long-running process in it. Don't do this.

Example 2a: An improved Hello World app

Here we show how the Portlet lifecycle is exposed when writing WCM templates. As Liferay WCM apps are run in the context of a portlet (the "Web Content Display" portlet or "Asset Publisher" if you use that), you can separate code to run during the RENDER_PHASE of the portlet (when the browser is requesting the page) from the code that runs during the RESOURCE_PHASE, a JSR 286-defined lifecycle event that lets you call back into the template to do asynchronous processing (not synchronous with the RENDER_PHASE) and return stuff, separate from the rendering of the app/portlet itself.

Example 3: Passing parameters to the RESOURCE_PHASE via an HTML form

Here we show how to pass parameters into the RESOURCE_PHASE and access them using the $request variable. Handy for lots of things, but still forces a full page refresh on form submittal (hello, 1998).

Example 4: AJAXification with AUI and JSON

Here we show how to use AlloyUI's built-in AJAX utility to periodically (every second) call the app's RESOURCE_PHASE to get stuff. The 'stuff' in this case is a JSON payload which is then parsed by the app and displayed in the browser. Good times ahead (note there is no parameter passing - that's example 6).

Example 5: Same thing, but using jsonFactoryUtil to properly create and emit JSON objects

The point of this example is that it is difficult and unnecessary to form a JSON string using the templating language. Instead, we use Liferay's built-in jsonFactoryUtil to construct a proper JSON object, fill it with data, then emit it using its toString(), thereby not having to worry about escaping special characters or that we possibly left off a { or a ] or a ,.

Example 6: Same thing as example 5, but passing parameters via AlloyUI and accessing in the RESOURCE_PHASE

Not terribly interesting, we pass parameters during the AJAX call to the app's RESOURCE_PHASE, and use the values to construct a JSON object which is returned and displayed. Note the use of the ${pns} (Portlet Namespace) variable - this is required as of 6.2 to ensure all parameters are namespaced to avoid conflicts from other instances of the same app on the same page. See LPS-39748 for details, and also note that when we pass the parameters we prefix the names with ${pns} but when accessing from code in the RESOURCE_PHASE, we just use the name of the variable without the prefix.

Example 7: Intermission

In this example we illustrate how to asynchronously call Liferay services (like UserLocalService) using a client-side JavaScript library included out of the box, rather than having to do it yourself via an AJAX request to your own code. All of Liferay's services are exposed in this way, as are any custom JSON Web Services you may have running on Liferay. Whee!!

Example 8: Expando Basics

In this example we demonstrate how to use Liferay's Expando services to create new data schemas and get/set data using according to that schema. From templates, you have access to services for creating new tables, rows, columns, and data (e.g. $expandoTableLocalService.getExpandoTable()). In this example, we use it to create a new Expando table, populate it with some fake data, and echo that back, all done in the RENDER_PHASE for brevity.

One thing you see in this example is some complaining about Velocity vs. Freemarker. Since Velocity has no way to natively access static member variables of a Java Class, I had to resort to an ugly workaround. With Freemarker, it's much simpler (see commented-out code). A note for Velocity fans, the Velocity Tools project does include a utility method to access statics, but Liferay does not include this out of the box (I dunno why). We do with Freemarker though (via the staticUtil object).

Example 9: Expando Basics, but slightly better

Same as example 8, but here we are using an AJAX call to the RESOURCE_PHASE of the app, and $jsonFactoryUtil to properly construct the response. The same fake data is created each time the RESOURCE_PHASE is accessed.

Example 10: The complete meal

In most cooking shows, they skip the part of meal preparation where the meal is cooking in the oven for an hour. They instead show you the ingredients, a few basics about how the meal is constructed, then walk over to the oven and pull out the complete dish, and the audience oohs and aahs.

Well, here we are doing the same thing. We put the concepts of Liferay WCM (for templating), accessing Liferay Services like UserService and ExpandoService, AlloyUI (for AJAX calls and a fancy DataTable), parameter passing, JSON object construction, and whip it all together into a single app which is basically a glorified Database browser and editor, but built on top of Liferay Expando. If you use Expando a lot, and are using a traditional RDBMS browser to inspect values, then this final example may be of use to you!

Here's what it looks like when browsing some sample data:

And here's the code

This 'app' renders a few drop-down selectors, and to use this app, do this:

  1. Select one of the Classes from the first dropdown (this list is generated through an AJAX call to the RESOURCE_PHASE, retrieving all possible class names that have one or more Expando Tables associated with it). To understand the relationship between Expando classes and tables, read the wiki page.
  2. After selecting a class, select an Expando Table that is associated with the class (this list is generated the same way as #1 is).
  3. Once a class and table has been selected, an AUI DataTable will be displayed containing all of the rows and columns of the selected Expando Table (again, using an AJAX call to retrieve the data).
  4. If you want to change one of the values, double-click on it, make the change, and click Save. The value will be stored via another AJAX call back to the RESOURCE_PHASE, passing the identification and value of the edited cell, which is used to update the data in the Expando Table.

Because it shows all tables and all classes, you can even see the values for a User's "Custom Fields" (a feature in Liferay). For example, if you go to Control Panel->Custom Fields and create a new field for Users (e.g. "Favorite Color"), and then visit "My Account" and give yourself a value for that field, you can then see that entry in the com.liferay.portal.User / CUSTOM_FIELDS Expando table. Editing that value will change the resulting value for the user, if you re-visit your "My Account" page you will see this in action. Good times indeed.

Liferay Client-side IPC

You may also notice a Google map in the above screenshot. This was a simple demo of Liferay's built-in client-side IPC, which is just a glorified messaging using JavaScript, firing an event with, payload) and receiving it in the other portlet with Liferay.on(event). In this example, I am sending data from the clicked row, and displaying the results (the row contains a latitude, longitude, name, pic, etc).

Magic Upload Button

One other tidbit I showed at DevCon - I was using IntelliJ IDEA to show these example templates, and then clicking a magic button in IDEA to cause the template to be immediately updated in Liferay (vs. the old school way of copy/pasting it into Liferay's built-in template editor). Several people wondered about this magic.

There were actually two buttons: one to download all of the WCM templates on a given Site into a directory (the filenames are then the same as the templateId's of the templates on the site). And then another to upload the currently open template back onto the site, overwriting any other templates that may have been found. Yes, this is a big time hack to make it easier to quickly build apps, and could be improved to handle multiple templates. The files are renamed to have a .vm extension, so that IDEA recognizes it as a Velocity template file.

These button were linked to an IDEA External Tool which is a just a convenient way to execute an OS-level command (e.g. a bash script or any other executable) with textual substitution of the path of the file being edited, the root directory of the project, etc. So I had pre-created two "External Tool" buttons which, when I clicked that button, it called one of my custom scripts.

So, if I clicked the Download button, it would end up calling:


This script contained:

You can see I hard-coded several things (including the name of the subdirectory containing the downloaded templates, the hostname/port, and the name of the Site from which to download ("guest")). It simply downloads every template into a directory, and renames the file from [number] to [number].vm so that IDEA would "know" it was a Velocity template.

If I clicked the upload button, it would call:

/bin/bash [path-of-file-being-edited]

This script simply uploaded the currently opened template on top of any other template, based on the filenames contained in the subdirectory:

Both of these scripts relied on a tool called cadaver which is a WebDAV command like client for Mac OS X. The only reason I had to use this is because on Mac OS X, read/write WebDAV is not supported (thanks to Mac OS X, not Liferay). On Windows, it is properly supported, and so you could simply mount the WebDAV directory and edit the files directly on disk, and each time you saved them, they would automatically be updated.


So, that's it for the demos. The point of the presentation was that Liferay WCM is a good tool for rapidly prototyping (eventually converting to a 'real' app), and a quick and easy way to build simple "apps" on Liferay, without the need to deploy portlets (e.g. no IT needed), but it is NOT a substitution for java or true enterprise app development, and there are performance and security concerns that one must understand and accept. But it sure is fun!

2013 Liferay Community Pulse Awards

General Blogs November 11, 2013 By James Falkner

As 2013 comes to a close, I'd like to once again thank each and every one of you who have done your part to improve our community through valued participation and contribution. I know I sound like a broken record when I say this, but it's absolutely true that Liferay would not enjoy the success it has enjoyed nor be anywhere close to the same level of worldwide usefulness if it wasn't for our open source community.

One of the things I strongly believe in is recognizing those that give back, especially those that do so more than others. I believe peer recognition of achievements is of great value to the entire community, not just to those that receive it. So, as we close out this year, I'd like to once again recognize those individuals and companies that contributed more than most to our community over the last year, and hope that by doing so it not only encourages them to continue to give value to the community, but also sets a good example for others to follow in the future!

This year, Liferay re-branded all of the awards as Liferay Pulse Awards, and so what follows is a list and description of the community awards I was honored to be able to reveal and present at a few of the Liferay Conferences that took place this year. So.. on with the show!

Liferay Pulse Award: Community Contributor of the Year

This award is given to individuals (not employed by Liferay or its partners) that volunteer their time and effort to make Liferay and its community better. This year, extra marks were given for well-rounded participation and contribution in different areas, as well as for value given through venues (e.g. personal blogs,, and others).

In no particular order, I present to you our Liferay Community Contributors of the Year for 2013!

Aniceto P. Madrid

Aniceto Pérez y Madrid is CEO and founder of Innovasoft Proyectos y Servicios, based in Madrid, Spain. Aniceto actively contributed to Liferay in Community Verifier and other programs, and is involved with the Liferay developer community and participates in the Liferay Forums.


David Kubitza

Based in Germany, David's main contributions have been in Liferay core technology, and he's done a great job in BugSquad, finding and/or fixing almost 40 non-trivial fixes and improvements for Liferay projects. David is a regular IRC user and regularly visits the #liferay IRC channel to discuss bugs, features etc., get some help, and give some help back to other users.

Luis Mas

Another of our valued Spanish community members, Luis had probably the most well-rounded participation out of the bunch, singlehandedly translating all of Liferay Portal into Catalan, but also active on the forums and finding bugs in BugSquad. Luis is also an active member of the Spain User Group.

Gnaniyar Zubair

Gnaniyar is a Liferay consultant in Saudi Arabia and also has a very well-rounded profile in our community. He is very helpful on our forums (he had one of the highest answer-to-post ratio in the community), fixed several 6.2 bugs, and spreads his knowledge via his personal blogRecently, Gnaniyar contributed a WCM feature in Liferay for publishing any versions of the article and has been involved many R&D process which will be available soon in the Liferay Marketplace.

David Nebinger

A repeat winner from the USA, David is extremely helpful to newcomers and experts alike on our forums, with the highest total of posts and answers (over 1700 high quality forum posts in the last year), contributions to our wiki, an active blogger, and contributions to Liferay Portal core as well.


If you see these folks in our community, be sure to congratulate them on a job very well done this year!


Liferay Pulse Award: Community Excellence

The Community Excellence award is given to those worldwide companies in our Liferay Partner community who demonstrate a unique and valuable dedication to our open source community. Companies here have spent their own time and resources to make our community better, which of course benefits everyone, so we recognize them here and thank them for their dedication to growing Liferay and its community.

EmDev (Russia)

EmDev continued their unique track record this year with a team of highly dedicated and smart community members that were active on our Russian and English forums, and were one of the first to contribute to the Liferay Marketplace (and was a runner-up in the Marketplace App Contest), along with ensuring that the Liferay Portal Russian translation was 100% complete and of super-high quality.


Permeance (Australia)

Permeance had yet another stellar year in our community, super-active in both Community Verifier and in our 6.2 Beta program. In addition, Permeance helps to organize and contribute to the Australia user group, contributed over 7 apps to the Marketplace (and was a runner-up Marketplace App Contest winner).



Cignex Datamatics (Worldwide)

Cignex Datamatics has always been a hugely valuable member of our partner and open source communities, and this year is no different. They are again recipients of this Community Excellence award through their contributions in many areas including our forums, wiki curation, the Marketplace (where their app Mercado was a runner-up prize winner), and heavily contributed to BugSquad and Community Verifier.


Componence (Netherlands)

Again this year, Componence demonstrated their value through their tireless and well-rounded community activity on the forums, Marketplace, bugfixing, website contributions, and at local events for the Netherlands User Group and Liferay Conferences. Componence also ensured the Dutch translation was 100% complete and correct, and was active in BugSquad and our Community Leadership Team as well. We're very lucky to have them in our community!


Savoir-faire Linux (Canada)

Savoir-faire Linux is a long time contributor to open source (like the Montreal Python community) and Liferay. They lead the Montreal Liferay User Group as well, and have contributed major features in the past, and continue to do so this year. In addition, they are active on the Liferay forums, and actively maintain the French Canadian translation for Liferay Portal.



SMC Treviso (Italy)

SMC was one of the first partners of Liferay (and the first in Italy), and this year continued its tradition of supporting our community through contributions to our forums, several Marketplace apps, and is active in BugSquad and founded and continues to build the Italy User Group. They also help coordinate and contribute to our Italian translations (now at 100%), and even translated this year's mobile app for our Liferay Events.



Dunn Solutions (USA)

Dunn stepped up their game quite a bit this year, and firmly planted their flag in our community through high quality blogging of technical issues in Liferay, several Marketplace apps, and helping our community on the forums. Dunn also participates in and presented at the Chicago User Group.



Rookies of the Year

The final two awards went to relative newcomers to the partner ecosystem in the last year, and are quickly building their community chops by volunteering their time and energy to give back to the community in various ways. We want to welcome them and recognize their achievements using this award and hope they continue to build on their work done this year in the months and years to come, and set a great example of how our community can grow through consistent and quality participation and contribution.

DCCS (Austria)

Since becoming a Liferay partner in late 2012, DCCS used their prior Liferay expertise to immediately jump into the community and help out those in need on our forums. Looking beyond the dates considered for this award, DCCS looks to be continuing to participate and contribute, and I look forward to seeing them in 2014!



Solea Solutions (USA)

Solea Solutions, based in Portland, has displayed the kind of passion and willingness to contribute that makes our community great. Since becoming a partner in 2012, they have revived the Portland User Group with a number of outreach community events, contributed a handful of Marketplace apps, and even painted their ride for the North America Symposium.

Please join me in congratulating all of these individual contributors and partners. They, along with the rest of our community, are what make my job so rewarding and what I believe makes Liferay stand out above all as an example of open source and community at its best. Great job everyone! I am very happy to see all the enthusiasm and passion for open source and for Liferay, and I look forward to seeing what we can accomplish in 2014.

Showing 21 - 40 of 117 results.
Items 20
of 6