View Models

In the model-view-view model pattern, the view model receives raw data from the model and transforms that data to produce a view. Brightspot’s view models accomplish this transformation in two steps. In the first step, the view model receives two categories of data:

  • Content, such as text, images, and videos available through methods in a received model object.
  • Web environment, such as HTTP header fields, query strings, and cookies available through annotations.

The view model implements methods specified in an underlying Java interface such that there is one method for each item appearing in the view. For example, if a view has three elements (headline, body, and date published), the view model includes three methods to return each element individually. If those elements require additional logic, such as instantiating a locale to properly format a date, the view model implements the corresponding methods and constructors accordingly.

In the second step, the view model transforms the extracted data into a form the view is expecting.

In the following example, the view model uses the getHeadline and getBody methods to access those model elements; it also uses the @HttpHeader annotation and getDatepublished method to access and format the publication date in a manner indicated by the client’s locale.

package content.article;

import com.psddev.cms.view.ViewModel;
import com.psddev.cms.view.servlet.HttpHeader;
import java.util.Locale;
import java.text.DateFormat;
import java.util.Date;

public class ArticleViewModel extends ViewModel<Article> {

   /* Return the article's headline. */
   public String getHeadline() {
      return model.getHeadline();

   /* Return the article's body. */
   public String getBody() {
      return model.getBody();

   Extract the Accept-Language field from the HTTP header.
   The first five characters of this field provide the locale,
   such as 'en-us.'
   public String acceptLanguage;

   The getDatePublished method returns a date in a format as expected
   by the client's locale prepended with the string 'Date published: '.
   public String getDatepublished() {

      /* Retrieve the date published from the model. */
      Date datePublished = model.getDatePublished();

      Extract the first five characters from the Accept-Language field
      to get the client's language and country.
      String httpLocale = this.acceptLanguage.substring(0,5);

      Declare a standard Locale variable; set it to en-us or en-au depending
      on the characters extracted from the Accept-Language field.
      Locale readerLocale = null;
      if (httpLocale.equals("en-US")) {
         readerLocale = new Locale("en","us");
      } else {
         readerLocale = new Locale("en","au");

      Instantiate a DateFormat variable that formats the date based on the
      discovered locale.
      DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, readerLocale);

      /* Return the formatted date prepended with the string 'Date published: '. */
      return "Date published: " + df.format(datePublished);



The following image is an example of the previous snippet’s output.


You can modularize your code by implementing the interface PageEntryView—a marker interface you can use to determine the required view model based on the model’s class or other criteria. See the following example.

public class ArticleViewModel extends ViewModel<Article> implements PageEntryView {

   if ((model instanceof DailySection) || (model instanceof WeeklySection)) {
      return createView(SectionViewModel.class, model);
   } else {
      return createView(ArticleViewModel.class, model);

For information about the createView method in lines 4 and 6, see createView.