As many of you know, at XTIVIA 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.
Speedray Architecture Pattern Description
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 XTIVIA. 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 XTIVIA 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.
Speedray Architecture Pattern Examples
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.
Contract first development approach
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.
To assist in creating this contract document there is an online, browser-based YAML editor that is available at http://editor.swagger.io/ (if you prefer you can run this in your environment as well). This editor validates and provides error correction for the generation of the YAML specification file.
Once this contract is created the code for the “scaffolding” portion of the application is generated using the swagger-codegen tool that XTIVIA 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.
The function to log in to SalesForce when the service is started by the OSGI framework.
The implementation of the function getAllLeads. This function’s prototype is defined in a generated java interface by the code generator.
The implementation of the getLead function that is also defined in the generated Java interface.
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.
Implementation first development approach
The implementation first approach takes advantage of the Java Annotations that are provided for both JAX-RS and the OpenAPI initiative to provide the same service contract documentation as the contract first approach provides.
Therefore this approach would require the service developer to create a JAX-RS and OpenAPI compliant service first and then the client portlet would use swagger-codegen to generate the Angular2 service from the YAML or JSON URL that is provided out of the box by the Speedray framework, swagger-producer.
Once the Angular2 service is generated the same activities described for the contract first approach are needed to complete the portlet. This approach also provides the same benefits for reuse of the client implementation. The implementation code will only need to be modified if the service changes the calling contract or a required model attribute changes, and of course the codegen process is continuously performed for each deployment of the client application.
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 positives inherited from the microservices architecture are scalability, agility, testability and ease of deployment.
The first mitigated con is the decreased complexity due to the use of generated “scaffolding” implementations that can be used by both client and service provider of the REST API.
Additionally by default the performance with the Speedray pattern is higher, as it relies on the Liferay DXP JAX-RS and OSGI implementations. These implementations enforce a minimum level of performance for REST message handling, authentication, authorization and many other bottlenecks that occur with bootstrapped microservice implementations.
Speedray Architecture Pattern Analysis
The following table contains a rating and analysis of the common architecture characteristics for the XTIVIA 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.
Ease of deployment
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.
Ease of development
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. XTIVIA has also created an OSS framework under the Speedray umbrella (Service Guard) 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.