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.:

You will find controllers for the admin area of the application in the com.fluxtream.mvc.admin.controllers package.

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

Additionally, Updaters declare:
  • 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 called api
  • 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
  • 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:

  • value: these are powers of 2 for easy bitmasking; lets us further filter facets in SQL (JPA) queries
  • 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)