Skip to content

Working with strongly typed models aka Code First approach

Ondřej Chrastina edited this page Oct 4, 2022 · 1 revision

Contents

  1. Strongly-typed models
  2. Defining a model
    1. Typing the properties
      1. Typing simple elements
      2. Typing linked content items
    2. Naming the properties
    3. Examples
  3. Retrieving content items
    1. Casting to strong types
  4. Adding support for runtime type resolution

Strongly-typed models

Besides the basic methods for retrieving content items, the DeliveryClient supports fetching of strongly-typed models.

// Basic retrieval
new DeliveryClient("975bf280-fd91-488c-994c-2f04416e5ee3")
.getItem("article_about_coffee");

// Strongly-typed model retrieval
new DeliveryClient("975bf280-fd91-488c-994c-2f04416e5ee3")
.getItem("article_about_coffee", Article.class);

This approach is beneficial for its:

  • type safety during compile-time
  • convenience of usage by a developer (article.getArticleTitle() vs. @article.getString("article_title"))
  • support of type-dependent functionalities (such as usages in your chosen view template engine)

Defining a model

The models are simple JavaBean POJO classes, which means they don't have any attached behavior or dependency on an external framework. Note, you must ensure that you have a default no-argument constructor as well as setter methods that are named to match your properties.

Typing the properties

Typing simple elements

Here are the data types you can use for different content type elements:

  • Built-in Java types such as String, ZonedDateTime, Double and their nullable equivalents for simple elements like Number or Text.
  • List<com.kenticocloud.delivery.Option> for Multiple choice elements
  • List<com.kenticocloud.delivery.Asset> for Assets elements
  • List<com.kenticocloud.delivery.Taxonomy> for Taxonomy elements

Typing linked content items

Mapping to individual linked content items is supported, see Naming the properties.

To map to several Linked items elements, use either List<T> or Map<String, T>.

Depending on your scenario, use one of the following as the data type parameter:

  • Specific content type model (e.g., Article) – when the element contains content items based on a single content type.
  • ContentItem – when the element can contain mixed content types and you don't need type safety.

When mapping to a specific content type model as a list or map, you must use the ContentItemMapping annotation on the target class to specify the content type it maps too.

@ContentItemMapping("article")
public class Article {
...
}

Typing Rich text

For Rich text elements, use String to receive HTML code resolved using string-based resolver as outlined in Rendering content items in Rich text.

Naming the properties

By default, the model properties and content type elements are matched by codenames of the elements. The SDK tries to convert the element codenames to CamelCase. For example, a content type element with the codename of article_title translates to a property called articleTitle.

If you need to change the codename of an element the property is bound to, you can enrich the property with the ElementMapping annotation.

@ElementMapping("text_field")
public string articleTitle;

Linked items elements are matched in the same manner as content type elements.

If you need to change the codename of a single linked content item the property is bound to, you can enrich the property with the ContentItemMapping annotation.

@ContentItemMapping("origins_of_arabica_bourbon")
ContentItem arabicaBourbonOrigin;

Examples

You can find a sample model at https://github.com/Kentico/delivery-sdk-java/blob/master/src/test/java/com/kenticocloud/delivery/ArticleItem.java

Retrieving content items

All the getItem and getItems methods have their corresponding methods where you can pass in a Class that represents the model you want to load. The parameters are the same as for the non-generic variants. The only difference is that you have to specify the class as an additional argument.

You can either specify the type directly (e.g., getItem("on_roasts", ArticleItem.class)) or pass the type as Object.class (e.g., getItem("on_roasts", Object.class)). Use the second approach if you don't know what the type is to let the SDK resolve it during runtime.

This argument represents the model you want to load. You can specify the parameter in two ways:

  • by using a content type model, for example getItem("on_roasts", ArticleItem.class)
  • by passing Object.class, for example, getItem("on_roasts", Object.class)

Use the second approach if you don't know what the content type will be and you want the application to resolve it during runtime. See Adding support for runtime type resolution for more details.

Casting to strong types

Note that it's possible to cast ContentItemResponse and ContentItemsListingResponse to strongly-typed equivalents by calling castTo(Class<T> tClass). Calling this method on ContentItemsListingResponse returns List<T>.

Adding support for runtime type resolution

The DeliveryClient supports runtime type resolution. This means you can pass Object.class as an argument instead of explicitly specifying the data type in the model or when calling the getItem and getItems methods. The data type will be resolved dynamically during the runtime.

For example:

Object model = client.getItem("on_roasts", Object.class);
Assert.assertTrue(model instanceOf ArticleItem); // type will be e.g. 'ArticleItem'

For this to work, the SDK needs to know the mappings between the content types and your models.

If you want to use the runtime type resolution in your application, you have 3 options. You can either register the codename of the type with your class. You can annotate you class with @ContentItem(codename) and register just the class. You can also scan the classpath for annotated classes.

// register by codename
client.registerType("article", ArticleItem.class);

// register by annotated class
client.registerType(ArticleItem.class);

// register by scanning the classpath for annotated classes
client.scanClasspathForMappings("com.dancinggoat");