You are on page 1of 4

Architectural problems in Liferay projects In an increasingly agile business environment, with an increasing number of companies competing for the

same market share, the possibility of developing applications with many out of the box functionalities, Liferay framework is at least interesting. This article analyses the architectural problems that must be addressed at the beginning of the project in order to obtain a flexible product and to not to need major adjustments later on. With or without Liferay Liferay is an open source portal under GPL license, for enterprise applications. It comes together with many personalisable functionalities: user management, multi-tenant and multi-language, CMS, integration with rule engines, with search engines and many other out of the box. It functions on a series of application servers (among which JBoss, GlassFish), servlet containers (Tomcat, Jetty, Resin) and with many DBMS-es. It can be deployed in the cloud. Before starting any project, one must ask the following question: is Liferay really needed? Thus, if a complex portal is needed, an application which administers a lot of content, then it fits. If the application is big in size, but it is not content oriented (content-centric), Liferay may be useful, but not recommendable. However, if the application is simple and handles little content, then Liferay adds on too much complexity. It must take into account as well the fact that Liferay is a portlet container and it is not worth to be used for classical web applications. Service Builder or own services Layer Service Builder is a tool developed by Liferay in order to automatize the creation of interfaces and classes used by the portal and portlets for layers and data access services. The code for the beans is generated, the Persistence, the Model and the Spring mappings. This is the tool used as well by the Liferay developers in order to generate the Liferay core services. For this reason, it has been tested for a long time and the problems have been solved or at least identified. The problems encountered are logged in Jira and are public: http://issues.liferay.com/browse/LPS. The Service Builder ensures the service transactionality, it has a clustering mechanism and even offers the possibility of internationalising any entity with a minimum effort. Nevertheless, from the point of view of the documentation, the Service Builder benefits only by a wiki page that is not very detailed. This means that, if you do not understand exactly what specific attributes do, you must investigate the generated code in order to anticipate the manner in which it will act. Usually the need for these interventions can only be identified during implementation and this means unforeseen delays. However, there are training sessions organised by Liferay where one can acquire the needed knowledge. On the other hand, one can choose to develop their own services layer. The advantage consists in having complete control of the written code and the possibility of defining your own documentation. However, the overhead of defining two layers persistence and services with the interfaces and abstractisation level offered by the Service Builder is very high. Thus, the time for implementation and delivery (time to market) will be very long. Nevertheless, there are some cases in which the Service Builder is not necessary. For instance, if one communicates with a 3rd party system which administers data and exposes services, only their appellation will be required. In what follows we will be discussing the projects in which the Service Builder is being used. Decoupling the application components Like for any other layer architecture, the components must be kept separate, but the decision on the granulation level on which it is separated into artefacts, it must be carefully weighed, because it may bring a performance penalty or may make the code hard to understand and to maintain. Figure 1 presents the logical division of the components of a Liferay project. Implicitly, the Service Builder generates the api separately from the implementation, in a WEBINF folder. This is the Ant manner of structuring the project. The Maven manner is to generate it in a separate module.

Figure 1 In what concerns the packing of the components, there are several manners of doing this, according to the projects requirements. For the simplest project, it is enough to pack the api in a jar and the portlets together with the implementation in a war. The advantage of this solution is that once the contract is defined, the implementation may change and can be hot deployed. In theory, one can change the business logic and the server does not have to be stopped in order to have the solution in production. However, unfortunately, in practice it happens very seldom to work on a sprint in services and not change something from the interface. The hot deploy is rather more for the hot fixes.

Figure 2 In order to maintain a separation of concerns and to increase the level of isolation, it is possible that the service implementation would constitute a separate model and would be deployed as a jar, as shown in Figure 2. This would mean that, if at a given moment, the client decides that they want to store the data in a different manner, one must replace only the implementation module. The disadvantage is that the deploy lasts longer, which is felt especially during development. From this point of view, if the project is a big and fragile one, with an unpredictable client, the best solution would be to separate the service implementation in a different module from the start, but one gives up at the same time the possibility to deploy hot fixes on services. For development one can use a similar configuration to the one in Figure 3, in which this module is wrapped together with the portlets in a war and thus one can perform hot deploy and an overhead is not created for this.

Figure 3 Another aspect that differs from project to project is the manner in which the portlets are separated into plug-ins. The variations are very big: in one of the projects I worked on, we used one plugin per portlet, while in another project there was one plugin for all the portlets. Each approach has its own advantages and disadvantages. In the first case it is very easy to control what functionalities you make available to a tenant, but the deploy lasts longer and the inter-plugin communication may be expensive. The second option is quicker, the entire business being in one place. But this latter one is advantageous only up to a certain number of portlets. The decision depends on the clients needs and on the size of the project. When the latter starts growing, the functionalities that have a logical connection or make sense together for business should be grouped in the same plugin. Even if at the beginning of the project everything is developed together, it is possible that at a certain moment the client would want to make available to various tenants different functionalities. Interaction between components One problem that is often raised far too late is the standardisation at the project level of the communication between components. Liferay follows a Model Driven Architecture, where the Service Builder acts as a Model Driven Transformation Tool. Thus, the service layer is the one responsible with transforming the back-end entities into entities that may be used by the portlet layer. But, in the same way as the portlets, the services for the entities that have business value together should be grouped and these groups should be isolated one from another. This because it may be decided at any point that certain functionalities must be moved in a completely different environment. For instance, in an application handling student management, all information regarding exam grades should be moved into a trust centre for legal reasons. Under these conditions, in order to connect the presentation and the back-end, we need composite services, called wrappers. Figure 4 presents this architecture. Communication between the wrappers level and the portlets level is done using DTOs or business objects. The service layer exposes Service Builder entities and all operations it undertakes are atomic, because everything is in a transaction. Because of this, the granular level at which services divide in functional units must be carefully weighed in order not to remove from transactions the operations that should be atomic (e.g. erasing a student separate from erasing his grades). Moreover, the client may decide that they want to present their business as a service (Software as a Service). If the project is efficiently modularised, the business logic for a functionality is centralised, this change should be easy, because the Service Builder offers the possibility of showing REST or SOAP services only by writing an implementation in the service layer. However, if the wrapper layer is the one ensuring the consistency of the data base, the transition will be a painful one.

Figure 4 Conclusions In conclusion, there is no standard manner of structuring a Liferay application; there is only a series of questions which must be asked at the beginning of each project. The later these questions that standardise the manner of work are asked, the more expensive the re-factorisation will be, in order to have a consistent project, and the flexibility and extensibility will be affected.