Backend Improvements 6 22: Difference between revisions

From Open-Xchange
No edit summary
 
(12 intermediate revisions by the same user not shown)
Line 11: Line 11:


These simplifications to exception handling imply severe impact on existing OX6-compliant source code that need special developer’s intention:
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.
*There’s no more the need to create own exception class, but only creating an enum that implements OXExceptionCode.
— * 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.
*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 v6.22 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).

Latest revision as of 09:50, 4 September 2012

Improvements Overview of 6.20.x to 6.22 Backend

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 Server v6.22 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 v6.22 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).