Core Concepts
Spring Controllers
We use the SpringMVC Framework. Controllers for various specialized areas of the application can be found in the com.fluxtream.mvc.controllers package, e.g.:
- AppController: this is the "main" controller that displays the master template and initializes a user session.
- SupportController: this is the controller that lets user recover a lost password
- ConnectorsController: lets users add, configure and remove connectors
- SettingsController: saving and retrieving user settings (units of measure, addresses, etc.)
- NavController: calendar-oriented navigation
JAX-WS Controllers
We use JAX-WS to expose our Web API. JAX-WS is a specification, mainly a set of annotations that strongly resemble those of the SpringMVC framework. The concrete implementation we use is Jersey.
The API is in the com.fluxtream.api package in the fluxtream-core-webapp module.
Spring Services
We use standard stateless Spring singletons to expose our services. Their interfaces can be found under the com.fluxtream.services package, implementations are in com.fluxtream.services.impl package. To give you an idea of these services' responsibilities:
- ApiDataService: storing and retrieving connector data, e.g. getApiDataFacets(...) or cacheApiDataJSON(...)
- GuestService: user management, including storing and retrieving API keys
- SettingsService: storing and retrieving user settings
- etc.
Connectors
The Connector class
The Connector class provides a few static methods that are used throughout the code base to retrieve information about the connectors that are available to the application. This information is retrieved on initialization by looking at the sub-packages of the com.fluxtream.connectors package. The Connector class' initialization routine uses introspection to retrieve metadata about the different components of a connector implementation. By connector implementation, we mean: the different classes inside a specific connector package, e.g. the classes in the com.fluxtream.connectors.twitter package. A Connector instance encapsulates all the information about a concrete connector that are needed at runtime.
Following is the description of the different types of classes that make up a connector implementation.
Updaters
Updaters are marked with the @Updater annotation. Updaters are responsible for retrieving connector data (JSON or XML). Depending on the update strategy it uses, it can be called
- externally by a Push-oriented API (Fitbit, Zeo or Withings) →NeverUpdateStrategy,
- or it will be called internally,
- either in an incremental way →IncrementalUpdateStrategy
- or as often as possible for those APIs that require it (e.g. Google Calendar or Toodledo) →AlwaysUpdateStrategy
- a
value
integer: this is a very important piece of information: every Connector has one unique value that allows to identify their associated facets; in AbstractFacet, this value is calledapi
- a list of ObjectTypes, which are Class instances that inherit from AbstractFacet; this way,
Connector
instances know what Facets are available for any specific API. - an
extractor
(see below): that is the Class that is responsible for creating concrete Facets from the JSON or XML data that we get back from APIs - a
prettyName
suitable for human consumption
Facets and ObjectTypes
Remember that @Updaters have an ObjectTypes
attribute which point to Facet Class instances? Now Facet implementations; in turn, are annotated with an @ObjectTypeSpec annotation. This annotation allows Connector instances to further specify the facets associated with a Connector. Attributes of an ObjectTypeSpec annotation are:
- a
value
: these are powers of 2 for easy bitmasking; lets us further filter facets in SQL (JPA) queries - a
name
: the 'technical' name for this Object type - a specialized
extractor
: this is optional and is used only if we need a more specialized extractor than that which was specialized for this Object type's Updater - a
parallel
flag: lets us know if we are allowed to parallelize calls to the API or if we need to do them sequentially (for the same user) - a
prettyName
for your reading delight
Extractors
These extend AbstractFacetExtractor: these Classes are instantiated every time we need to "turn" JSON or XML data into a persistable Facet
Value Objects
These extend either AbstractInstantFacetVO or AbstractTimedFacetVO, depending on wether they describe an instantaneous event or an event that has a duration. These are the value objects that are going to be converted to JSON when they are sent to the client. When converting a Facet to a FacetVO, the following parameters are used:
- the user's Locale
- the Time Zone they were in when the event occured
- the user's preferences (e.g. preferred units of measure)