Get Content-Backed View Models
Content-backed view models are accessed through the Get operation's View field, allowing you to fetch transformed presentation data for a specific content item. This approach layers view model transformations on top of content fetching—you identify the content item with the usual with lookup, then select a view model representation of it.
This page assumes familiarity with the Get operation; you'll use the same configuration and query structure with the addition of the View field. The same editorial features available on content—most notably Preview—work seamlessly with content-backed view models, allowing you to render unpublished changes through the exact same presentation logic as live content.
Configuration
Write a ViewModel<M> class for your content type, annotate it with @ViewInterface, and register it with entryViewClass:
16public class ArticleViewModel extends ViewModel<Article> {78@WebParameter9private Integer summaryLength;1011public String getHeadline() {12return model.getHeadline();13}1415public String getSummary() {162324public Boolean getRecentlyPublished() {2529}30
191015@Override16protected GCASchemaSettings getSchemaSettings() {17return GCASchemaSettings.newBuilder()18.readonlyEntryClass(Article.class)19.entryViewClass(ArticleViewModel.class)20.endpointViewType(OperationType.QUERY, NavigationViewModel.class)21.build();22}23}
Querying a view
The View field appears on Get results for any type that has registered view classes. It takes a required of argument—a one-of input selecting the view by schema type name (an enum of the available views) or fully-qualified Java class name—and returns a union of the record's possible view types:
- GraphQL Query
- GraphQL Variables
- GraphQL Response
1query GetArticleView($with: RecordGetInput!, $request: Record__ArticleView__RequestInput) {2Get {3Record(with: $with) {4View(of: {type: ArticleView}) {5... on Record__ArticleView {6Response(typed: $request) {7data {8__typename9_id10headline11summary12recentlyPublished13}14}15}16}17}18}19}20
1{2"with": {3"_id": "0000019e-b88d-d0f1-abff-fdcd360e0000"4},5"request": {6"parameters": {7// !tooltip[/all/] Parameter values are always lists of strings, mirroring HTTP request parameters. They are coerced to the view model field's Java type.8"all": {9"summaryLength": ["24"]10}11}12}13}14
1{2"data": {3"Get": {4"Record": {5"View": {6"Response": {7"data": {8"__typename": "ArticleView",9"_id": "a1c55f8e6b37328596c76d77644f4b790000019eb88dd0f1abfffdcd360e0000",10"headline": "Welcome to Brightspot",11"summary": "Hello world! This is a l…",12"recentlyPublished": true13}14}15}16}17}18}19}20
The pattern is: View(of: ...) → ... on Record__<ViewType> → Response(...) → data → your view's fields.
Passing parameters
View models frequently accept input—a summary length, a locale, a pagination cursor. Declare fields on your view model with web request annotations (like @WebParameter), and the GCA exposes them through the Response field's arguments:
typed— a view-specific input type (e.g.Record__ArticleView__RequestInput) whoseparameters/allmap carries your parameters by name. Values are lists of strings—exactly like HTTP request parameters—and are coerced to the Java field types.request— an untyped equivalent shared by all views, useful when building queries dynamically.
This mirrors how the same ViewModel classes behave when rendering web pages: the GCA constructs a synthetic web request from your GraphQL arguments, so view models work identically in both worlds.
Previewing through views
Because view models are the contract your front end consumes, previewing unpublished content is most useful through the view. The Preview field on Get results (requires includeGetPreview()) exposes its own View field, so the same query shape renders a shared preview instead of the live record:
1{2Get {3Record(with: {_id: "..."}) {4Preview(id: "...") {5View(of: {type: ArticleView}) {6... on Record__ArticleView {7Response {8data {9headline10summary11}12}13}14}15}16}17}18}
This is the foundation for real-time preview in headless front ends: the editor's in-progress changes flow through your exact production presentation logic.
Accessing the backing model
By default, a view exposes only what its getters declare—that's the point. If consumers also need raw model access alongside the view, enable includeModelOnViews() to add a _model field to every view type. For debugging, allowRawViewAccess() adds a _raw field returning the whole view as a map—watch out for cyclic references, and consider excludeTypeNamesFromRawView() if type names are sensitive.
Next steps
- Get Standalone View Models — views that don't need a content ID
- Understanding ViewModel Schema — how view classes map to schema types