In the first installment of this series, I showed several (hopefully useful) code snippets demonstrating the programmatic creation of various things in Liferay - pages, portlets, and structured web content, which can be found in the smoldering ashes of the 7Cogs sample data included in Liferay until version 6.1.
I am using these snippets in an app that auto-populates a blank Liferay Site with interesting eye candy people and content, useful for showing demos and running tests that require a lot of user-generated content (you can see examples of such content in the third welcome video created for the 6.1 launch).
In this blog post, we'll look some of the code that generates the fake users and content. These snippets build on, but are not not directly copied from, 7Cogs. So quality is most likely decreasing :) But most of the Liferay logic is derived from 7Cogs.
As a Reminder
- This should all work in the latest Liferay 6.1 CE and EE releases.
- Not a lot of clever coding. I'll post the full source to git as part of the final installment and invite you to fork and fix.
- Not a lot of error checking here. If it fails it doesn't end up blowing up, but also doesn't continue. I leave it to your trusty development skills to fix this.
- A lot of this is hard-coded or assumes the English language is being used. You can undo this with basic development skills as well!
- I don't go into excruciating detail about some of the Liferay APIs used here. Javadoc is your friend. Most of the time.
Get a random point in time
This method is used when setting the creation date of user-generated content, to simulate that the content was created at some point in the past. It makes time-based visualizations more interesting!
Create a Profile Avatar/Picture
Now the fun, fragility, and questionable coding begins! The
SocialDriverConstantsclass has a bunch of hard-coded user names, job titles, Gravatar picture IDs, industry keywords for Wikipedia searches, and such, used when generating the content. This code fetches a random picture from Gravatar for use when creating new user profiles later on.
Generate Friend Requests
This code links users together through Social Relations (aka Friending). It will optionally confirm the friend request. This is used to randomly friend users to make them less lonely and make the social graph appear more interesting.
Creating and assign fake Addresses
Here we are randomly creating an Address and assigning it to a user, for later visualization. You can also see a slight bias for the United States and Japan (you can change this). 10% of the time, the user's address will be in the US. 10% of the time, it will be in Japan. The other 80% of the time it'll be in a random country in the world (of the countries defined by Liferay). This is used later when visualizing user's locations.
You may be wondering what that hard-coded
11002is doing there. Addresses can be of different types (e.g. Personal, Business, and Other.
11002is the constant for Personal. This is defined in Liferay's default SQL data, and not in Java, so I had to hard-code it here.
Setting User Password, bypassing TOU, Father's Middle Name
It also sets a user's profile picture using a random Gravatar ID through the call to
Randomly assigning some Friends
This picks some random users with which a relationship is established. It avoids friending the "default" (guest) user, and also avoids friending the user with themselves (which is weird, right?). It uses the previously defined
addSocialRequestfrom up above.
Setting up a User's Profile
This rather long method is in the spirit of 7Cogs. It first assigns the user's public pages a theme (lines 7-10) (if this option is chosen in the GUI to be seen later). It then adds three Web Content Articles (lines 19-52) (each based on a Web Content Template and Structure). These are special web content articles that I'll show you in the next installment in this series. These articles, along with some other Liferay portlets (like a calendar, documents and media, recent bloggers, etc), are placed on the user's newly-created 4 profile pages (lines 54-126):
- User's Name (Friendly URL: /profile)
- Expertise (Friendly URL: /expertise)
- Social (Friendly URL: /social)
- Blog (Friendly URL: /blog)
- Workspace (Friendly URL: /workspace)
Programmatically Creating a Liferay User
This code creates a new Liferay User. Some notes:
- If it finds a Site called "Sales", it'll assign the newly created user to it, in addition to assigning them to the Guest Site. This is because I use a demo group called "Sales" (mimics a typical enterprise sales organization) so I want to add users to it if such a site exists.
- It will also imbue the new user with the "Social Office User" role if such a role exists (and it will, if you are using Social Office).
- Note that Social Office comes with a nice looking theme, so in most cases if you are using SO, you'll not want the theme assignment to happen. There is an option in the UI for this.
- It finally assigns a random address to the user, configures their account to make it easy to login the first time, assigns random friends, and then sets up the new user's profile as defined above.
Get (or create) a random User
This code will pick a random user from the set of defined users in our constants file, and if they don't exist yet, it'll create them (via prior code above). It is used when creating fake content (blogs, wikis, ratings, comments, etc).
Removing Stop Words
This removes common English Stop Words, those that are very common and are useless as tags, such as The or A, or any word that is 2 characters or less, which are pretty useless as tags too. I'm pretty sure the Big-O performance of this is really bad.
As part of this app, we also generate a bunch of user content in the form of:
- Blog Posts
- Wiki Articles
- Forum Posts
- Blog, Wiki comments
- Forum responses
- Blog, Wiki, Forum ratings/votes
The content is generated by going out to Wikipedia and fetching articles based on pre-defined search terms. The title of each article is used to generate a set of tags for the article (ignoring common words like a and the). The Wikipedia JSON service is used and abused. This content is cached for use while the generator is running. Here's how to fetch it:
Picking terms for Wikipedia Searches
Here we are just picking a random number of random terms from a pre-defined list. Woo! Note if you pick too many terms, you won't find anything on Wikipedia (since it's an AND search). And if you pick too few, you'll get a LOT (which is great, but sometimes searching for java might get you coffee articles, or searching for mobile will get you information about a certain southern US city. So it's good to have a set of related keywords.
Fetching articles from wikipedia
Not much to do with Liferay, but this method queries Wikipedia via its JSON web services, using the supplied String, and established HTTPClient object (this uses Liferay's built-in, old version of the Commons HttpClient).
The result of a JSON web service call to Wikipedia is a JSON object (see their docs) containing the results of the search. You can see what it looks like in your browser. We grab the title, and break it apart (and remove stop words) and use the result as the tags for the article. The body is represented by the article's snippet (you can't get the full content from Wikipedia due to usage restrictions). The result of calling this method is a library of
ContentArticleojects that are very simple (just a container for the title, tags, and content of an article, used later on to make the content in Liferay). You'll see how this all comes together in the next blog post in this series.
By the way, you can repeatedly call this to get more articles as needed. It's a good idea to call it a several times (like 10 times with different search terms if you want to generate a LOT of Liferay content).
Creating a Blog Post
Now we are back to Liferay APIs. Here we are randomly picking a date and a user and publishing a blog post using random content and tags from earlier Wikipedia fetches. This has the side effect of making a new Activity Stream entry, and accumulating Social Activity points! More on this in the next installment. We are doing the ServiceBuilder dance here as well, just like before.
Commenting on a Blog Post
This is where things get even more interesting. Comments in Liferay are created and managed through the MB (Message Board) functionality. So, you'll see some of those APIs here. Discussions are associated with content (like blog posts) through the standard className/classPK linkage pattern found throughout Liferay's Asset Framework. So this code simply picks a random, existing blog post to comment on, and adds the comment to the thread associated with the blog post. Other content types are very similar (e.g. Wikis, Documents, etc).
Voting on a Blog Post
Here is how to programmatically find and randomly rate a random blog post (1 to 5 stars), using the RatingsEntry service. The deal with the PrincipalThreadLocal on line 19 is that this is how Liferay knows "who" is voting (since voting is typically done in the context of a request/response).
Creating, Commenting, and Rating other Content Types
Looks at watch - Wow, where did the time go? This will have to wait for the next installment, and I will show you how to wrap all of this into a simple Liferay portlet with a horrible yet usable UI for controlling the creation of content and social data.