This website uses cookies to ensure you get the best experience. Learn More.
Managing Liferay through the Gogo shell
I have done a huge refactor for most of our OSGi related work, moving the majority of its components to the Liferay plugins SDK. Everything except the graphical admin UI is already in the master branch of the official repo so you can play with it; we would love to hear your feedback.
My goal with this post is to show you how create a new OSGi bundle in the plugins SDK using a practical example: extending the OSGi shell (we have spoken about it sometime ago). Let's try to do it:
Currently there is no target in the SDK which allows you to create a bundle (I will push it soon) so you can use this example (or the other modules as http-service-shared or log-bridge-shared) as the basic skeleton for your tests:
As you can see, the structure is very simple; let my try to highlight the main OSGi related points:
<import file="../../build-common-osgi-plugin.xml" />
As I have told you before I will include an Ant target to create this basic skeletons, but, until then, you need to do this by hand. Sorry about that :(.
As we have stated at the beginning of the post, we are going to write a bunch of custom commands for the Gogo shell. As you will see, this is an extremely easy task.
This commands can be created using a simple OSGi service with a couple of custom properties. We will use the OSGi declarative services approach in order to register our commands (Liferay already includes an implementation of the Declarative Services specification in the final bundle, so you don't need to deploy it by yourself).
At this point, we are ready to write our first command: the ListUsersCommand:
The @Component annotation let us to define a new OSGi service in an extremely easy way. The Gogo commands are registered in the console using the properties osgi.command.function and the osgi.command.scope. The first one establishes the name of the namespace where the command will be allocated (in order to prevent name collisions) while the latter specifies the name of the command. It is important to note that the Declarative Service annotations I am using does not support inheritance, so everything you declare in a base class will not be inherited down in the hierarchy.
And, how do I write the implementation of my new command? You just need to write a new public method named as the value written in the osgi.command.function. If your command needs some argument you will need to specify as a parameter of your method (an the console will do the coercion of the basic types). In our example we are creating a usermanagment namespace, with a command called listByCompany which expects the companyId (long) as the unique parameter.
Easy, isn't it?
I would like to highlight the implementation of the listByCompany command (I am sure you have already guessed the previous command retrieves all the users of a certain company).
In order to get all this info we need to call the corresponding method in the users service. We could do something like UserLocalServiceUtil.getCompanyUsers(companyId) but this is not a good approach, so we are to going to get all the benefits of having all the Liferay services as OSGi services. We just need to grab a reference to the UserLocalService bean:
@Reference
public void setUserLocalService(UserLocalService userLocaService) {
_userLocalService = userLocaService;
}
protected UserLocalService _userLocalService;
ant jar
listByCompany ID_OF_A_COMPANY (mine is 10153)
Users of the company 10153
User default@liferay.comwith id 10157
User test@liferay.comwith id 10195