Support and Documentation

Annotations

There are two groups of annotations specific to the View system: type and field.

Type annotations

Type annotations are class-level annotations. They typically appear with view-model classes, but may be used with other classes or interface implementations.

@HandlebarsTemplate

Identifies the view model as a producer of Handlebars output, and specifies the Handlebars template's location. This annotation is included in the Brightspot Handlebars plugin.

This annotation requires the @ViewInterface annotation.

import com.psddev.cms.view.PageEntryView;
import com.psddev.cms.view.ViewInterface;
import com.psddev.cms.view.ViewModel;
import com.psddev.handlebars.HandlebarsTemplate;

@HandlebarsTemplate("Article")
@ViewInterface
public class ArticleViewModel extends ViewModel<Article> implements PageEntryView {

    public String getBody() {
        return model.getBody();
    }

    public String getHeadline() {
        return model.getHeadline();
    }
}

The above example specifies that for the class ArticleViewModel, the associated Handlebars file is <webroot>/Article.hbs.

For detailed information about Handlebars, see Handlebars.

@JsonView

Declares the view model as a producer of JSON output.

This annotation requires the @ViewInterface annotation.

import com.psddev.cms.view.JsonView;
import com.psddev.cms.view.PageEntryView;
import com.psddev.cms.view.ViewInterface;
import com.psddev.cms.view.ViewModel;

@JsonView
@ViewInterface
public class ArticleViewModel extends ViewModel<Article> implements PageEntryView {

    public String getBody() {
        return model.getBody();
    }

    public String getHeadline() {
        return model.getHeadline();
    }
}

The JSON output is an object with keys corresponding to the model's fields and associated values, as in the following example.

{
  "body" : "A platoon of aliens who traveled four light years in suspended animation landed in Times Square Wednesday evening...",
  "headline" : "Crippled by Earth's Gravity, Aliens Demand Submission"
}
@ViewInterface

Invokes a process to transform a Model's data into the form specified by another annotation, usually @HandlebarsTemplate (for Handlebars output), @JsonView (for JSON output), or @ViewRendererClass (for customized output). See those annotations for examples of how to use @ViewInterface.

@ViewRendererClass

Specifies a class implementing ViewRenderer to render the model's data.

This annotation requires the @ViewInterface annotation.

The following example comes from Brightspot's implementation for RawView:

package com.psddev.cms.view;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

@ViewInterface
@ViewRendererClass(RawViewRenderer.class)
public interface RawView {

    List<?> getItems();

    /* static methods... */

}
Field annotations

The following field-level annotations appear before the declaration of individual fields within a ViewModel.

@CurrentSite

Retrieves the current Site object based on the Request URL. This annotation is available only if your Brightspot project is configured as a multi-site instance.

import com.psddev.cms.view.servlet.CurrentSite;

public class ArticleViewModel extends ViewModel<Article> {

    @CurrentSite 1
    private Site currentSite;

}

1

Retrieves the current site into the variable currentSite.

@HttpCookie

Retrieves the value for a specified cookie. If the specified cookie does not exist in the request, the annotation returns a null value.

import com.psddev.cms.view.servlet.HttpCookie;

public class ArticleViewModel extends ViewModel<Article> {

    @HttpCookie("username") 1
    private String userName;

}

1

Specifies retrieving the value for the cookie username into the property userName.

@HttpHeader

Retrieves the value for a specified field in the HTTP request header. If the specified field does not exist in the request header, the annotation returns a null value.

import com.psddev.cms.view.servlet.HttpHeader;

public class ArticleViewModel extends ViewModel<Article> {

    @HttpHeader("User-Agent") 1
    private String userAgent;

}

1

Retrieves the value for the header field User-Agent into the property userAgent.

@HttpMethod

Retrieves the HTTP request method. Typical values for the request method are GET and POST. For a listing of possible HTTP request methods, see HTTP request methods.

import com.psddev.cms.view.servlet.HttpMethod;

public class ArticleViewModel extends ViewModel<Article> {

   @HttpMethod 1
   private String httpMethod;

}

1

Retrieves the request method into the variable httpMethod.

@HttpParameter

Retrieves the value of a requested parameter passed in a URL's query string or in a posted form. For example, if the URL is http://www.example.com/index.html?userid=5, you can use this annotation to retrieve the value for userid. If the parameter does not exist in the query string or form, this annotation returns a null value.

import com.psddev.cms.view.servlet.HttpParameter;

public class ArticleViewModel extends ViewModel<Article> {

    @HttpParameter("userid") 1
    private String userID;

}

1

Sets the property userID to the value of the query parameter userid.

@HttpRequestAttribute

Retrieves the object or string representing a requested servlet attribute. If the attribute does not exist, this annotation returns a null value.

import com.psddev.cms.view.servlet.HttpRequestAttribute;

public class ArticleViewModel extends ViewModel<Article> {

    @HttpRequestAttribute("currentdate") 1
    private String currentDate;

}

1

Retrieves the value for the attribute currentdate into the property currentDate.

@HttpServletPath

Returns the servlet path, typically the path appearing after the domain in a URL. For example, in the URL http://www.example.com/solar-system-implodes, the servlet path is /solar-system-implodes.

import com.psddev.cms.view.servlet.HttpServletPath;

public class ArticleViewModel extends ViewModel<Article> {

    @HttpServletPath 1
    private String servletPath;

}

1

Retrieves the servlet path into the property servletPath.

@HttpSignedCookie

Retrieves the value for a specified signed cookie. If the specified cookie does not exist in the request, the annotation returns a null value.

import com.psddev.cms.view.servlet.HttpSignedCookie;

public class ArticleViewModel extends ViewModel<Article> {

    @HttpSignedCookie("username") 1
    private String userName;

}

1

Retrieves the value for the signed cookie username into the property userName.

@HttpStorageItemParameter

Transforms a submitted file into a StorageItem, and associates the value for name with the StorageItem. The files can be uploaded files or JSON representations of files.

For example, the following HTML snippet submits two images to the server, one as a file and another in JSON format.

<html>
   <input type="file" name="image" />
   <input type="hidden" value="{JSON structure here}" name="imageJson" />
</html>

The following view model snippet transforms the uploaded files into StorageItems.

import com.psddev.cms.view.servlet.HttpStorageItemParameter;

public class ArticleViewModel extends ViewModel<Article> {

    @HttpStorageItemParameter("image") 1
    private StorageItem profileImage;

    @HttpStorageItemParameter("imageJson") 2
    private StorageItem profileImageJson;

}

1

Transforms the file submitted in an <input> tag with name image, and then saves that file in the property profileImage.

2

Transforms the JSON file submitted in an <input> tag with name imageJson, and then saves that file in the property profileImageJson.

@MainObject

Retrieves the object associated with a published permalink. For example, if the permalink associated with an article is http://localhost/gravity-canceled-today, this annotation returns the object associated with /gravity-canceled-today.

import com.psddev.cms.view.servlet.MainObject;

public class ArticleViewModel extends ViewModel<Article> {

   @MainObject 1
   private String mainObject;

}

1

Retrieves the object into the property mainObject.

Custom field annotations

Custom field annotations are a mechanism for populating fields on a view model before any of your view-model logic executes. Currently, ServletViewRequestAnnotationProcessor is the only interface which allows you to populate fields on your view model. If you need to access the HttpServletRequest on your view model, then as a best practice you should create a custom annotation.

The simplest pattern for creating custom view-model annotations is to implement the annotation in a class and then apply the annotation to a view model's property or method. For many examples of advanced implementations of view-model annotations, including standalone annotation processors, see the Brightspot repository's servlet directory.

In the following sample, you develop a custom view-model annotation that checks if the current user is logged in before displaying an article's body. If the user is not logged in, the view model displays an appropriate message.

Step 1: Define annotation

In a file CurrentUser.java, enter the following text:

import com.psddev.cms.view.servlet.ServletViewRequestAnnotationProcessor;
import com.psddev.cms.view.servlet.ServletViewRequestAnnotationProcessorClass;

import yourpackage.User; /* User-defined class */

import java.lang.annotation.*;

@ServletViewRequestAnnotationProcessorClass(CurrentUserProcessor.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD) 1
public @interface CurrentUser { 
}

class CurrentUserProcessor implements ServletViewRequestAnnotationProcessor<CurrentUser> { 2

    @Override
    public Object getValue(HttpServletRequest request, String fieldName, CurrentUser annotation) {

        Cookie[] cookies = request.getCookies(); 3

        for (Cookie cookie : cookies ) { 4

            if (cookie.getName().equals("authenticationCookieName")) { 5
                if (passesAuthenticatonTest(cookie.getValue())) { 6
                    User currentUser = lookupUserByToken(cookie); 7
                    return currentUser;
                } else {
                    return null;
                }
            }
        }

        return null;
    }
}

1

Declares the @CurrentUser annotation as applicable to fields.

2

Implements the annotation's processor as an implementation of ServletViewRequestAnnotationProcessor:

3

Retrieves the cookies provided by an HTTP request.

4

Loops over all the cookies.

5

Processes the cookie authenticationCookieName, which is present only if the user is logged in.

6

Checks if the authentication cookie is valid. passesAuthenticatonTest is a user-defined function.

7

Retrieves the user record associated with the authentication cookie. lookupUserByToken is a user-defined function.

Step 2: Apply annotation to view model

In the view model, enter the following text:

import annotations.CurrentUser;
import yourpackage.User; /* User-defined class */
import com.psddev.cms.view.ViewModel;
import com.psddev.cms.view.PageEntryView;

import styleguide.content.article.ArticleView;

public class ArticleViewModel extends ViewModel<Article> implements ArticleView, PageEntryView {

    @CurrentUser 1
    private User currentUser;

    @Override
    public String getBody() { 2
        if (currentUser == null) {
            return "Please log in or register to read this story.";
        } else {
            return model.getBody();
        }
    }
}

1

Applies the customized annotation @CurrentUser to the property currentUser:

  • If the user is logged in, the annotation initializes the property to the current user's User record.

  • If the user is not logged in, the annotation initializes the property to null.

2

Implements the getBody method:

  • If currentUser is null, the user is not logged in and the view model displays a prompt.

  • If currentUser is not null, the view model displays the article's body.

custom-viewmodel-annotation.svg