January 30, 2017
As many of you know, at Digitize we have been working with the Liferay platform ever since the Liferay v3.6 days (circa 2006), and over this time, not only have we seen the platform evolve and grow significantly with each release, we have continually innovated on top of the Liferay platform to deliver state-of-the-art solutions for our clients. With the recent release of the Liferay Digital Experience Platform (DXP) 7.0, and our preferred approach for modern web application development, we are introducing the Speedray Architecture Pattern for Liferay DXP to the Liferay community.In recent years, the adoption of REST services and single page applications (SPAs) has resulted in an extremely rich, fluid user experience similar to that of a desktop application. While end-users have benefited from this enhanced interactivity, it has also introduced a large amount of complexity and redundant scaffolding code for developers of these applications.
This architectural pattern is enabled in large part due to Liferay DXP’s implementation of an OSGI environment that provides a rich set of service development tooling and built-in support for JAX-RS services. This service tooling promotes microservices that coexist well with other service providers and integrate into disparate systems such as ERP, CRM, and others while being efficient in utilization of resources.
This architectural pattern is presented as a means to adopt them with minimal coding effort on the part of the application and services developer(s). To allow these three components to cohesively provide functionality that will most probably be developed by multiple parties, this pattern relies heavily on the API as a contract between the two other components. For this reason this pattern has adopted the OpenAPI initiative as the mechanism for describing the API contract and also as the basis for the API framework developed to generate the “scaffolding” implementations for the client and service providers adopting this pattern.
The client and services developers will therefore only need to conform to the provided API interface to communicate with each other. The REST API itself is described as either an OpenAPI YAML or JSON document or as either YAML or JSON generated documentation derived from the service implementation using Java annotations. This provides either the option to pursue a contract first or implementation first service development approach.
There are currently two LGPL3 licensed frameworks provided by Digitize. The first framework generates documentation from any JAX-RS and JSONWS services deployed in the Liferay DXP environment. This provides a solution for implementation-first development environments. The other framework has been provided by extending the existing swagger-codegen project to provide the client and services with a “scaffolding” implementation in a contract first development environment, or just the client implementations in a implementation first environment. In addition Digitize has developed a portlet that provides the swagger-ui portion of the OpenAPI initiative for all JAX-RS and JSONWS services deployed in the Liferay DXP environment, for testing of the specified API and developer orientation for the API.
The following examples will demonstrate a project that provides access to SalesForce Lead information. A Java service and Angular 2 client portlet will be hosted on the Liferay DXP platform.
There are two main approaches to development using the Speedray pattern. The first is the contract first development approach. When using the contract first approach the first step is to create a YAML or JSON file that conforms to the OpenAPI 2.0 specification. This file is used as the “contract” for the service producer and client.
Once this contract is created the code for the “scaffolding” portion of the application is generated using the swagger-codegen tool that Digitize has provided modifications to, for generating Angular2 services and JAX-RS based services hosted by Liferay DXP.
The coding task left to the Liferay application developer is to create the Angular2 code to display and interact with the data provided by the Angular2 service function calls – in our example application that displays a list of SalesForce leads with a drill-down into the lead details, the UI developer would consume services to “get all leads” (getAllLeads) and “get lead details” (getLead). These function calls were generated by the swagger-codegen tool.
The JAX-RS service “scaffolding” is also generated and only requires three pieces of code to be created by the service developer.
Once the created code is complete, as long as the contractual call parameters do not change (none in the getAllLeads function and the id parameter in the getLead function), the implementation code will not change regardless of the number of times the contract document is modified.
If a change to the contract occurs by either changing one of the parameters for the REST service call or a required model attribute changes, the continuous generation of the interface and model objects will force a compile time error that will allow the developer to identify and correct the contract breakage long before the application makes it way out of development.
This pattern is closely related to the microservices architecture pattern. It inherits the advantages of that pattern while also mitigating many of the cons. Some highlights include –
The following table contains a rating and analysis of the common architecture characteristics for the Digitize Speedray architecture pattern. The rating for each characteristic is based on the natural tendency for that characteristic as a capability based on a typical implementation of the pattern, as well as what the pattern is generally known for. This table is built upon the analysis performed for the microservices architecture pattern.
Analysis: Overall agility is the ability to respond quickly to a constantly changing environment. Due to the notion of separately deployed units, change is generally isolated to individual service components, which allows for fast and easy deployment. Also, applications built using this pattern tend to be very loosely coupled, which also helps facilitate change.
Analysis: Overall this pattern is relatively easy to deploy due to the decoupled nature of the components.
Analysis: Due to the separation and isolation of business functionality into independent applications, testing can be scoped, allowing for more targeted testing efforts. Regression testing for a particular service component is much easier and more feasible than regression testing for an entire monolithic application. Also, since the service components in this pattern are loosely coupled, there is much less of a chance from a development perspective of making a change that breaks another part of the application, easing the testing burden of having to test the entire application for one small change.
Analysis: With the standard JAX-RS based implementation in Liferay DXP, this pattern will provide reasonable performance for all but the highest demands of heavy messaging applications. In those cases a specialized protocol and implementation are recommended.
Analysis: Because the application is split into separately deployed units, each service component can be individually scaled, allowing for fine-tuned scaling of the application. For example, the admin area of a stock-trading application may not need to scale due to the low user volumes for that functionality, but the trade-placement service component may need to scale due to the high throughput needed by most trading applications for this functionality.
Analysis: Because functionality is isolated into separate and distinct service components, development becomes easier due to the smaller and isolated scope. There is much less chance a developer will make a change in one service component that would affect other service components, thereby reducing the coordination needed among developers or development teams. Digitize has also created an OSS framework under the Speedray umbrella that supports annotation-based authorization for any JAX-RS service in Liferay DXP.
Liferay DXP has made significant enhancements to create engaging experiences across all touchpoints, and provides a robust application development platform in addition to the core out-of-the-box functionality. The Speedray Architecture Pattern facilitates and speeds up creating modern web applications on Liferay DXP.