Managing Liferay through the Gogo shell

Community Blogs 2013/05/14 投稿者 Miguel Pastor Olivar Staff

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:

Basic project structure

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:

Basic OSGi bundle skeleton

As you can see, the structure is very simple; let my try to highlight the main OSGi related points:

  • All the new OSGi plugins will be based in the great bnd tool . You can configure all your bundle requirement through the bnd.bnd file
  • The build.xml of the plugin must import the build-common-osgi-plugin.xml build file: <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 :(.

Writing Gogo shell custom commands

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?

Consuming Liferay services

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;
 

Building and running the bundle

Once we have written our command we need to build our final artifact: just type ant jar in the project folder and you will get the final jar file into the dist folder. Before deploying our new bundle let's connect to the Gogo shell in order to check which bundles we have already installed:
 
 
As you see, we have already a bunch of bundles running but nothing about the new commands we are writing. What commands are currently available in the console? Just type help in the console
 
Gogo shell available commands
 
Now we have to deploy our new bundle. To do that, we just need to copy it to the folder $liferay.home/data/osgi/deploy (it is the default folder, you can change it in the properties). You can use the deploy Ant task our just copy the folder into the previous folder. Once the bundle is deployed we should see it in the bundles list:
 
Available bundles once the custom command has been installed
 
Take a look to the last line; you will see our bundle has been deployed and it is, hopefully, running. Let's see which commands we do have available once our new bundle is already installed.
 
 
Do you see the last two lines? These are the commands we have written (in this post we only have described one command, you can find the other one in the companion source code). So, if I type listByCompany ID_OF_A_COMPANY (mine is 10153) (since there is no collision I don't need to prefix the command with the namespace) you should get an output similar to this:
 
Users of the company 10153
    User default@liferay.comwith id 10157
    User test@liferay.comwith id 10195
 
Along this post we have seen how we can extend the Gogo shell creating new commands, consuming Liferay services and building a basic OSGi bundle in the plugins SDK. It is not a big deal but I think it is a good starting point to get used to the new OSGi abilities. Hopefully I will be able to push some more complex examples in the near future.
 
You can find the whole source code in the shared/gogo-commands-shared folder at my plugins repo.

Leveraging a little bit of the OSGi power

Staff Blogs 2013/04/05 投稿者 Miguel Pastor Olivar Staff

These days I have been pushing all the OSGi stuff through the review process so we have already got some of the work in the master branch. Ray has written a really good blog post about using the Apache Felix Gogo console inside Liferay and he has already explained some of the benefits of our current work so I am not going to explain it here again.

We are still going through the peer review process so, at the time of this writing, some of the features could not be in the master branch yet. Anyway, we can still get many benefits and write powerfull applications which can exploit some of the benefits wich OSGi brings to us. In order to illustrate the previous statement, let's write a small, and extensible, metrics application.

Our goal is to build a small and pluggable monitoring system which allow us to track different aspects of the Liferay's internals like, for example, JVM statistics or whatever you can imagine.
 
The example is using the OSGI Declarative Services specification. It is a declarative and very easy way of declaring and consuming OSGi services. It is not included by default right now because, once all the stuff is already in master, we will try to push something very close to the approach shown in this example, but using the Eclipse Gemini Blueprint project, in order to keep all the Spring benefits we already own.
 

The metrics core system

The core of our metrics system is extremely simple, we just create a domain model to represent our system metrics
 
 
Another important piece of our metrics core component is the MetricsProviderManager. It is just a simple backgrupund task which, periodically, collects all the metrics extensions registered in the system.
 
 
As you can see, right now we don't have any source code which can provide us any kind of metric. At the beggining of the post we have said that our metrics system should be pluggable/extensible. In order to do that let's create an SPI (Service Provider Interface) which the extensions of our metrics system should fulfill.
 
 
Once we have the core of our system let's go and register it as a service inside the OSGi container (which is running inside liferay). We have different ways to do that: in this example we are going to show how we can achieve that using the Declarative Service specs:
 
 
What are we doing within the previous definition?
  • Declaring our Metrics manager as a component (OSGi service)
  • Get/UnGet a reference to every MetricsProvider service which is registered/unregistered in the OSGi container (note how easily we can extend our metrics system)

Our first metrics extension

At this point we have the core of our system, which, by its own, it does not measure anything :). Let´s build our first metric component, a JVM metrics provider (a stupid one :) ). How can we do that? Just two easy steps

Implement the SPI wich the core system is exposing

 

 

 

Register the previous implementation as an OSGi service (we are using the Declarative Service approach too):

 

And that´s everything we need to do. Simple, isn´t it?. Just package both components and deploy it to your LIFERAY_HOME/data/osgi/deploy folder and just see the logs. Now, you can connect to the console (as Ray has already shown) and stop your metrics-jvm component so JVM metrics will not be longer collected, or you can create a new metric extension, deploy it and start seing it metrics on the log.

I am, intentionally, hiding all the OSGi details since I want you to put the focus in the general idea, and not in the details of building a MANIFEST.MF. In the near future we will see more complex things like using Liferay services as OSGi services, creating OSGi based webapps, ...

You can find all the source code in the following Github repo under the folder liferay-module-framework/examples/declarative-services.

I would love to hear your feedback and if you would prefer having a wiki page with all the new module framework related stuff instead of having long blog posts like this one (sorry about that)

My 2nd birthray

Staff Blogs 2013/02/28 投稿者 Miguel Pastor Olivar Staff

It has been two years since I joined Liferay, it is incredible how fast time is going. Two amazing years I have been trying to enjoy as much as possible.

First of all I would like to thank all my Spanish colleagues to make me feel like if I were at home since the first day I ran into the office. And to all the people who usually works with me on the daily basis and they are able to bear me every day: Ray, Mike, ... Thx a lot to all of you guys!!

Hope all of you can enjoy as much as I am trying to do!

Thanks a lot guys!

Liferay and Modularity

Staff Blogs 2012/10/25 投稿者 Miguel Pastor Olivar Staff

A few minutes ago I have finished my talk about Liferay, modularity and OSGI at the Spain symposium. I am pretty sure I have covered the main points I have planned before the talk but I have many more different ideas I couldn't talk about because I just only got a 20 minutes slot.

You can take a look to the slides at my Slideshare account http://www.slideshare.net/miguelinlas3/liferay-module-framework and you will can download it at Liferay. I will push the source code of the examples to the Liferay Tech Talks as soon as possible.

Btw, Ray and I have been talking about many different concerns on OSGi and modularity stuff for the last months and he has already done a great blog post about that (needless to say I am completely agree with him). I would like to put some emphasis on the footprint and resiliency stuff. Once we could have all in place, I would like to put some effort on decreasing Liferay's resources usage putting in place all the benefits modularity, and OSGI, bring to us. This is a long story and I think this deserves more than a blog entry.

Thanks to all the guys who has attended my talk. Any kind of feedback will be extremely wellcome.

EDITED: You can find the source code examples here

Scala infrastructure in plugins SDK

Staff Blogs 2012/03/26 投稿者 Miguel Pastor Olivar Staff

 

I am an Scala enthusiast; I must to admit it :) ! It allows me writing clear and concise code having all the advantages of an extremely powerful type system, functional and object paradigms  among another such things.
 
But this is not a blog post introducing Scala benefits (you can see a very quick intro to the language https://github.com/migue/blog-examples/tree/scala-blog-examples/scala-talk) but talking about including it in the Plugins SDK so we can use it to develop our new portlets based on Scala.
 
This is a very quick overview on what you can do with the ongoing work (https://github.com/migue/liferay-plugins/tree/scala-support-infrastructure). I need to make some minor hacking but I hope to be pushing it to master during this week (if the child allows me to do it). Let's get started:
 
  • You can create a new Scala based portlet by executing the create script: create.sh portlet_name porlet_display scala
  • The previous command line execution will create a basic infrastructure with all the artifacts we need: a build.xml file, all the Scala library needed and a simple portlet class.
  • Using the previous build.xml file we can compile Scala code, Java code, use scalac (the single one compiler and the daemon) and make our deployments. This infrastructure will take care of the mixed compilation process if you are using both Java and Scala as your development languages for your new portlet.

I have some more work to do, like including a command in order to allow updating the Scala libraries with a specific version or generating IDE files in an automatic way. The current version is working fine but I hope to improve during this weekend and push it to master.

Short entry; hopefully I will write a more detailed one with some more news: I am working on building an Scala wrapper on top of the Liferay API . . . so stay tunned!! 

Hope you like it!

 

Writing custom SQL queries

Staff Blogs 2011/12/13 投稿者 Miguel Pastor Olivar Staff

Sometimes there is need of writing custom SQL queries in order to obtain the data acording to our needs. And, as all of you know, Liferay can run on top of the most popular databases so writing this queries should be written "carefully" to prevent unpleasant surprises in the future. 

The following lines summarize some of the most common tips that we must pay attention:

  • Using the "&" bitwise operator. Many databases, as Oracle, does not support using the keyword "&" as an operator, using a function instead. If you want to write an "bitwise and" operation in your custom SQL queries you will need to type something like BITAND(X,Y) and Liferay will translate your code according the underlaying database.  
  • Achieving casts in text columns. Another common difference between databases are casting text columns. You can solve this problem using the CAST_TEXT(text_column) function. So, every time you need to do a cast with text columns use this function and your cast operation will be working on the different databases.
  • Integer division. Some databases as MySql have an specific way on doing integer divisions. If you want to the integer result you should write A DIV B in MySql or TRUNC(A, B) in Oracle. If you want to make your query agnostic from the database use the function INTEGER_DIV(A, B).
  • Related with the first item, some databases as SyBase does not support using decimals columns in the bitwise operator. Liferay comes to the rescue again and offer you a CAST_LONG(x) function that will translate your sql code acording the current database.

There are some more tips but the previous ones, IMHO,  are the most common in the custom sql queries.

One simple advice: be careful when writing your custom SQL queries ;)

Cheers,

Migue

PD: I need to create a wiki page will all the technical details. When the page is available i will update this entry with the corresponding link.

PD2: I have a few pending blog entries related with Liferay and Cloud Computing. Hope I can write this posts as soon as possible :)

Debugging SQL queries with p6spy

Staff Blogs 2011/08/01 投稿者 Miguel Pastor Olivar Staff

Who has not ever had to fight with complex SQL queries and PreparedStatements? And, what about the ? symbol when enabling the sql log?

Last week I had to write a big migration process in order to complete a refactor and I have done some little hacking in order to use the p6spy driver when running a migration process from command line. This driver will resolve the values for the hated "?" symbols :).

My first step was to modify the portal/tools/db-upgrade/run.sh (I work on Linux) in order to launch the migration process from the command line witouth starting the application server.

Once the previous file has been modified we should include the p6spy.jar and the spy.properties files in the portal/tools/db-upgrade/lib/ folder.

We will need to configure three basic properties in the spy.properties file:

Basically we are configuring the path for the logged queries and the real driver we are using in our app (i am using MySQL at this moment)

The last step would be to tell the upgrade process to use a specific datasource (p6spy). We could achieve this by modifying the file portal/tools/db-upgrade/portal-ext.properties (pay attention to the jdbc.default.driverClassName property):

 

That's all! If you run your upgrade process by executing the run.sh file you will get logged all the executed SQL queries. And the most important thing; "?" symbols will be replaced with its corresponding values :).

We could use it for debugging SQL queries of the portal (hibernate.show_sql property does not replace ? ) but i left it for you as a homework ;).

Cheers,

Migue

PD: as far as I rembember, there is an eclipse plugin that displays the contents of the previous log much more beautiful than the plain text :)

ANTLR Creole Parser infraestructure

Staff Blogs 2011/06/21 投稿者 Miguel Pastor Olivar Staff

This is the first entry on my Liferay blog so, first of all, I would like to introduce myself. My name is Miguel Pastor and I have only been working four months in Liferay (since March 2011) but I'm very happy to be part of this incredible team.

In my first blog entry I would like to describe the general ideas of my first "contribution": The new Creole Parser infrastructure. Through this post, we will see an overview of the main architecture's components and some of our main ideas that could be introduced in a future.

Overview

The parser infrastructure is built on top of the main techniques used to build programming languages. The common flow of a typical parsing process would be the following:

  1. Parse the creole source code.
  2. The result of the previous parsing process is an Abstract Syntax Tree (AST)
  3. The previous AST is traversed by different visitors (right now there is some semantic validation visitors and a XHTML translation visitor)

In the following sections we are going to dive deeper inside some of the previous components

The parsing process

The parser is built with the invaluable help of ANTLR 3. For those whose don't know ANTLR, it is a tool that provides a framework for construction recognizers, interpreters, compilers, and translators from grammatical descriptions (LL(k)).

The grammar definition includes the needed actions to build the proper abstract syntax tree (see next section) from creole source code. This grammar is the responsible for validating the source's syntax and building the AST

Is someone is interested you could take a look at the grammar definition.

Abstract Syntax Tree

This kind of structure is usually used in compilers in order to represent the abstract structure of a program. Next phases of the compiler will perform multiple operations over this structure (usually using the Visitor Pattern).

The next figure shows a partial view of the hierarchy used in the AST representation (Composite Pattern)

Imagine for a moment that we have the following creole source code

 

= Header 1

== Header 2

[[http://www.google.com|Link to Google]]

 

=== Header 3

The abstract representation of the previous source code looks like something similar to this:

 

 

Code Generation and wiki engine

Once the previous structure has been built, a bunch of visitors could traverse it in order to do some work. The main feature implemented right now is code generation and link extraction:

  • XHtmlTranslationVisitor offers the basic funcionality to traverse the AST and generate the XHTML code (generic behaviour). In order to integrate with the wiki engine infrastructure already built in Liferay there is a XHtmlTranslator class (extending the previous one) conducting Liferay's particularities like link generation or table of contents.
  • LinkNodeCollectionVisitor allows us to extract all the nodes who represents a link in the original source code.

Following the previous patterns we could add a new visitor class to traverse the AST structure and perform whatever we want.

Future improvements

Using the previous pattern, i have already two main ideas in order to improve our current parser's infrastructure in order to allow extensions by external contributions:

  • The first one is creating a traversable structure in order to inject multiple visitor. Using this mechanism we could add new visitors in order to add new functions to our current parser. For example, imagine that we want to translate the creole code to XML instead of XHTML
  • The second one is adding extensions (similar to TableOfContents). At this moment the grammar allows (needs a little hacking) to include new terms in our Creole code using this syntax @@new term@@. This extension will be available at the AST in a node of type ExtensionNode (it does not exist right now so the final name could be different) and therefore, the visitor interface will have a method to deal with this kinds of nodes.

The above ideas has not been implemented yet but it should not be too complex :).

I'd love to hear your comments!

Cheers,

Migue

 

該当件数: 8 件
ページごとの項目数 20
/ 1