AppSuite:Backend API changes extensions

Foreword: This article describes the changes between backend version 6.20.7 and 6.22.0. It is sometimes considered to be the difference between OX6 and AppSuite, but we liked the improvements so much that we released them with OX6 v6.22.0 already. So if you are running a OX6 v6.22.*, you already have all those. Several companies jumped directly from OX6 v6.20.7 to AppSuite without 6.22 inbetween which is where the confusion likely stems from.

Open-Xchange App Suite – API Changes & Extensions

New Exception Framework

Exception handling is the process of responding to the occurrence, during computation, of exceptions – anomalous or exceptional situations requiring special processing – often changing the normal flow of program execution.

With Open-Xchange App Suite the exception handling has been heavily simplified. There is only a single class named OXException. As prerequisite for remodeling the exception handling, existing error code notations – e.g. APP-0015 – and uniquely identifying exception ID – exceptionID=-1272648052-227787 – need to be maintained. Newly introduced classes OXExceptionCode and OXExceptionFactory now replace formerly used classes Code, ErrorMessage, and ExceptionFactory respectively.

Moreover the new exception framework distinguishes between log and display messages. The log messages technically describe the occurred error with optional debug information (e.g. user, context, …). Whereby the display message is intended as a short, understandable and translatable message for the Open-Xchange user. The display messages are provided as public constants by a simple class implementing com.openexchange.i18n.LocalizableStrings interface.

These simplifications to exception handling imply severe impact on existing OX6-compliant source code that need special developer’s intention: —

  • There’s no more the need to create own exception class, but only creating an enum that implements OXExceptionCode.
  • Special handling through catch-clauses: Since there is only one exception class, there is no possibility for flow control through catch-clauses anymore. To look for a special error, the method OXExceptionCode.equals(OXException) is suggested for being used.
  • Special handling by error code numbers: Only comparing by code number may ignore equality of the associated code prefix. Using OXExceptionCode.equals(OXException) is recommended in this case, too.
  • Moreover the developer should be sure that the right category is selected for a certain error code. The category decides if exception is displayed to user or logged with certain log levels.

Unified OSGi

For developing OSGi bundles for Open-Xchange Server the helper class HousekeepingActivator is recommended. This subclass of OSGi’s BundleActivator interface offers many utility methods to register new services or to track needed ones.

Both, ServiceRegistrations and ServiceTrackers, are internally stored and automatically release if the stop() method is invoked. Thus it is ensured that any opened OSGi resource is orderly closed on bundle stop.

Central Dispatcher

The Open-Xchange Server generation v6.20.x and upward implements a HTTP based protocol with JSON formatted payloads to allow clients, mostly our own HTML/CSS/Javascript frontend, access to its functionality. Historically every module was implemented in a separate servlet making it hard to address overarching topics and leading to a lot of code duplication. In OX App Suite this has been streamlined by the introduction of a new framework for implementing HTTP API requests. While regular servlets will continue to function it is strongly recommended to migrate backend extensions that are accessed by HTTP API clients to the new framework to benefit from more generalized features (e.g. preview generation for file data, resizing and rotation of pictures, formatting options for output etc.)

To do so, you need to provide an implementation of the AJAXActionFactory interface which delivers an AJAXActionService implementation for every ?action=someAction type parameter in the HTTP API for your module. The AJAXActionFactory can be registered in the OSGi container by having your Activator subclass ModuleActivator and using its #registerModule method.

The meat of your HTTP API implementation will usually reside in the AJAXActionService implementations. They are expected to return an AJAXRequestResult for a given AJAXRequestData (which typically wraps an HTTP request, but could just as well emanate from a „multiple“ batch request or another interface). The AJAXRequestData provides access to the actions parameters and body data, already pre-parsed as JSON data, if that was possible.

AJAXRequestResults consist of the payload and the format that payload is provided in by the AJAXActionService implementation. This is used to automatically turn a given result type (say „contact“, which would be one or many contact objects) into, say a „vcard“, depending on what the client requested as desired format. Typically the response will be in JSON format, though.

Known types you can stick into an AJAXRequestResponse are:

  • „string“ which will be sent to the client as is
  • „json“, which will be wrapped in a {data: <your payload>} json structure as per HTTP API conventions
  • „file“, for which you will need to provide an IFileHolder (with lot’s of useful implementations already ready to use) implementation to have file data delivered to the client

For simple use cases that is enough. If you work with highly structured data (like OXs main data types contacts, appointments, tasks, files, mails) and introduce your own complex object type ( for the sake of argument say: an Order in a logistics application), it’d be best to introduce your own format („order“, or „ox:order“ with your own prefix instead of „ox“. Just pick one) and (at minimum) an implementation of ResultConverter that knows how to turn whatever object you supply as an „order“ into „json“. That way you can later easily add different output options for different clients (e.g. „csv“ to print a list of orders in a spreadsheet friendly csv file).

Index-Based Search

Solr is the popular, blazing fast open source enterprise search platform from the Apache Lucene project. Its major features include powerful full-text search, hit highlighting, faceted search, dynamic clustering, database integration, rich document (e.g., Word, PDF) handling, and geospatial search. Solr is highly scalable, providing distributed search and index replication, and it powers the search and navigation features of many of the world's largest Internet sites.

Solr is written in Java and runs as a standalone full-text search server within a servlet container such as Apache Tomcat. Solr uses the Lucene Java search library at its core for full-text indexing and search, and has REST-like HTTP/XML and JSON APIs that make it easy to use from virtually any programming language. Solr's powerful external configuration allows it to be tailored to almost any type of application without Java coding, and it has an extensive plugin architecture when more advanced customization is required.

Message Queue Pattern

Messaging systems allow you to loosely couple heterogeneous systems together, whilst typically providing reliability, transactions and many other features.

Unlike systems based on a Remote Procedure Call (RPC) pattern, messaging systems primarily use an asynchronous message-passing pattern with no tight relationship between requests and responses. Most messaging systems also support a request-response mode but this is not a primary feature of messaging systems.

Designing systems to be asynchronous from end-to-end allows you to really take advantage of your hardware resources, minimizing the amount of threads blocking on IO operations, and to use your network bandwidth to its full capacity. With an RPC approach you have to wait for a response for each request you make so are limited by the network round trip time, or latency of your network. With an asynchronous system you can pipeline flows of messages in different directions, so are limited by the network bandwidth not the latency. This typically allows you to create much higher performance applications.

Messaging systems decouple the senders of messages from the consumers of messages. The senders and consumers of messages are completely independent and know nothing of each other. This allows you to create flexible, loosely coupled systems.

The Message Queue Pattern

With this type of messaging you send a message to a queue. The message is then typically persisted to provide a guarantee of delivery, then some time later the messaging system delivers the message to a consumer. The consumer then processes the message and when it is done, it acknowledges the message. Once the message is acknowledged it disappears from the queue and is not available to be delivered again. If the system crashes before the messaging server receives an acknowledgement from the consumer, then on recovery, the message will be available to be delivered to a consumer again.

With point-to-point messaging, there can be many consumers on the queue but a particular message will only ever be consumed by a maximum of one of them. Senders (also known as producers) to the queue are completely decoupled from receivers (also known as consumers) of the queue - they do not know of each others existence.

A classic example of point to point messaging would be an order queue in a company's book ordering system. Each order is represented as a message which is sent to the order queue. Let's imagine there are many front end ordering systems which send orders to the order queue. When a message arrives on the queue it is persisted - this ensures that if the server crashes the order is not lost. Let's also imagine there are many consumers on the order queue - each representing an instance of an order processing component - these can be on different physical machines but consuming from the same queue. The messaging system delivers each message to one and only one of the ordering processing components. Different messages can be processed by different order processors, but a single order is only processed by one order processor - this ensures orders aren't processed twice.

As an order processor receives a message, it fulfills the order, sends order information to the warehouse system and then updates the order database with the order details. Once it's done that it acknowledges the message to tell the server that the order has been processed and can be forgotten about. Often the send to the warehouse system, update in database and acknowledgement will be completed in a single transaction to ensure ACID properties.

The Publish/Subscribe pattern

With publish-subscribe messaging many senders can send messages to an entity on the server, often called a topic (e.g. in the JMS world).

There can be many subscriptions on a topic, a subscription is just another word for a consumer of a topic. Each subscription receives a copy of each message sent to the topic. This differs from the message queue pattern where each message is only consumed by a single consumer.

Subscriptions can optionally be durable which means they retain a copy of each message sent to the topic until the subscriber consumes them - even if the server crashes or is restarted in between. Non-durable subscriptions only last a maximum of the lifetime of the connection that created them.

An example of publish-subscribe messaging would be a news feed. As news articles are created by different editors around the world they are sent to a news feed topic. There are many subscribers around the world who are interested in receiving news items - each one creates a subscription and the messaging system ensures that a copy of each news message is delivered to each subscription.