Liferay Beanshell Scripts for Sharded Environments

Liferay Beanshell scripts are a quick way of handling Liferay portal administration tasks that otherwise would take a very long time to do manually.

Liferay Beanshell Scripts

Every Liferay administrator, having worked enough with the Liferay Portal, came across the situation in which various batch operations are required. For example, if you need to add one user, then you can use the Control Panel > Users > Add new. But what if you need to add 100 users? Doing the same operation manually 100 times is not that fun. Therefore you need liferay scripts.

The solution: Liferay server scripts. Liferay supports several scripting languages:

  1. Beanshell
  2. Javascript
  3. Groovy
  4. Python
  5. Ruby

In this article (and in the following articles of this series if I’ll receive positive feedback on this) I will be using Beanshell.

Beanshell is very similar to Java in syntax, only that it is more loosely typed. For more information on Beanshell visit beanshell.org/intro.html

How Liferay server scripts work?

Liferay server scripts get passed to the server, the server compiles them on the spot and then runs them in the context of the server. In these scripts you will have runtime access to the Liferay API, so operations like adding or removing users are quite easy to do.

Liferay instances and sharded configuration

Liferay usually manages multiple instances. If you have multiple clients hosted on your installation then you probably set up a new instance for each client. Also, Liferay can be configured for using multiple shards. That means that it can separate the data for each instance (client) on a different database. If you would like to find out more about how you can configure a multi sharded environment see my post Liferay Saas solution – handling multi-tenancy.

Server side scripts can be run in the Liferay portal only in the default instance under Control Panel > Server Administration > Script section. Having instances configured to run in different database shards has a big impact on how you have to write your server side scripts. All scripts you run have to start with properly selecting the shard in which you want to do the operations.

Also, when writing server side scripts you have to have some knowledge regarding how Liferay stores its data in order to properly access it.

To give you an example: in a sharded environment information about all the instances (like the name of the virtual hosts) is stored in the company_ table ONLY in the default database shard. User information however is stored in the user_ table on each database shard.

So, when using the Liferay portal API in scripts you will have to be careful to access the right data in the right place.

Beanshell script basics

To keep things organize my approach to writing Liferay Beanshell scripts is to create 4 sections in the script:

  1. imports section – where I list all libraries required in the script
  2. initialization area – where I initialize constants and variables
  3. function area – where I define Beanshell functions that I will use
  4. the main are – where I write the actual operations that need to be performed

In the end the script will look something like:

/*import section*/
import com.liferay.portal.*;                                             
import com.liferay.portal.model.*;
import com.liferay.portal.service.*; 
import com.liferay.portal.kernel.dao.orm.*;
import com.liferay.portlet.documentlibrary.model.*;
import com.liferay.portlet.documentlibrary.service.*;
import com.liferay.portal.model.PortletConstants;
import com.liferay.portal.security.auth.*;
import com.liferay.portal.security.permission.*;
import com.liferay.portal.service.*;
import com.liferay.portal.kernel.dao.shard.*;

/*initialization section*/
String portletResource="20";
String selResource = DLFolder.class.getName();

/*function section*/
long getCompanyIdByShardName(String shardName){
...
}

/*main section*/
//actual code here
....

 

Beanshell script for working with a certain shard

As I mentioned earlier, when running a Liferay script in a sharded environment you need to first select the right shard where you want to do the operations. Usually you will only know the internal name of the shard (because this is usually configured by the administrator). Starting with this shard name, you find the id of the instance (companyId) and use that to select the right shard with the use of the ShardUtil class.

It is important to know that the ShardUtil class and all shard related operations are very sensitive and extensive care needs to be taken when working with them because selecting a shard works with an internal stack, and after use, if this stack is not restored at the initial state the portal will not function properly anymore.

This is why you should ALWAYS USE TRY / FINALLY BLOCKS when working in a sharded configuration. As an example, here’s the code for getting the name of a user for which you know the password:

 

/*import section*/
import com.liferay.portal.*;                                             
import com.liferay.portal.model.*;
import com.liferay.portal.service.*; 
import com.liferay.portal.kernel.dao.orm.*;
import com.liferay.portlet.documentlibrary.model.*;
import com.liferay.portlet.documentlibrary.service.*;
import com.liferay.portal.model.PortletConstants;
import com.liferay.portal.security.auth.*;
import com.liferay.portal.security.permission.*;
import com.liferay.portal.service.*;
import com.liferay.portal.kernel.dao.shard.*;

/*initialization section*/
String shardName="c1";
String userEmail="[email protected]";

/*function section*/
long getCompanyIdByShardName(String shardName){
	//get list of all shards
	//shard information is stored only in the default shard 
	//so no shard selection is necessary
	List allShards = ShardLocalServiceUtil.getShards(QueryUtil.ALL_POS, QueryUtil.ALL_POS);
	long result = 0;
	if (allShards!=null){
		for (i=0;i<allShards.size();i++){
			if (allShards.get(i).getName().equals(shardName)){
				return allShards.get(i).getClassPK();
			}
		}
	}

	return result;
}

User getUser(long companyId,String email){
	User user = null;
	try{
		//select the shard
		ShardUtil.pushCompanyService(companyId);
		user = UserLocalServiceUtil.getUserByEmailAddress(companyId,email);
	}
	finally {
		//unselect the shard
		ShardUtil.popCompanyService();
	}
	return user;
}

/*main section*/
long companyId = getCompanyIdByShardName(shardName);
User user = getUser(companyId,email);
if (user == null){
	System.out.println("User "+email+" not found");
}else{
	System.out.println("User found: "+user.getFullName());
}

I hope you enjoyed this post and please send me any remarks or questions you have related to it. I plan on creating more posts in which to describe all sorts of Liferay scripts that I often use to manage the Liferay servers I work with. I will post these scripts under the tag liferay script to allow you easier access.

John Negoita

View posts by John Negoita
I'm a Java programmer, been into programming since 1999 and having tons of fun with it.

2 Comments

  1. […] Setting document library folder permissions in Liferay can be a tedious task, especially if you have a complicated structure of shards and organizations. Using a script can be the faster way than doing it manually. In this post I will show you how I manage this task in production servers and will provide you with the Beanshell script. If you are unsure about how to run Beanshell scripts in Liferay you can also check out my post about Liferay Beanshell Scripts for Sharded Environments. […]

    Reply
  2. […] Setting document library folder permissions in Liferay can be a tedious task, especially if you have a complicated structure of shards and organizations. Using a script can be the faster way than doing it manually. In this post I will show you how I manage this task in production servers and will provide you with the Beanshell script. If you are unsure about how to run Beanshell scripts in Liferay you can also check out my post about Liferay Beanshell Scripts for Sharded Environments. […]

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top