Type Nullability
Types that are set as non_nullable are in essence required. Whereas types that are set as nullable are not required and thereby optional. By default, types are mapped and generated using the Java rules:
-
Any primitive type, such as
int, is non-nullable. -
Any reference type, such as
StringorInteger, is nullable. -
A collection accepts
null, unless the collection item type is primitive. -
A map accepts
null, unless the collection item type is primitive.
Any of these nullable types can be made non-nullable by applying a @NonNull annotation. Vaadin recommends using @org.jspecify.annotations.NonNull. The full list of supported annotations is as follows:
-
org.jspecify.annotations.NonNull(Recommended) -
org.springframework.lang.NonNull -
jakarta.annotation.Nonnull -
com.vaadin.hilla.Nonnull(Deprecated)
Endpoint Functions
For an endpoint function, nullable elements are as follows: Function Parameter Type or Function Return Type.
For Function Parameter Types, arguments cannot be omitted, even when the parameter types are nullable. To receive a null parameter value in Java, send an undefined argument in the endpoint function call.
Source code
Original Java endpoint class
import org.jspecify.annotations.NonNull;
@Endpoint
class PersonEndpoint {
// Person must have at least the first and last name.
public void setFullName(@NonNull String firstName, @NonNull String lastName, String middleName) {
// omitted code
}
// Full name must exist.
@NonNull
public String getFullName() {
// omitted code
}
// Person should have no connections with other people. If they have,
// the connection cannot be null.
public Map<String, @NonNull String> getConnections() {
// omitted code
}
}Source code
Generated TypeScript endpoint functions
export async function setName(
firstName: string,
lastName: string,
middleName: string | undefined
) {
return client.call('PersonEndpoint', 'setFullName', {firstName, lastName, middleName});
}
export async function getFullName(): Promise<string> {
return client.call('PersonEndpoint', 'getFullName');
}
export async function getConnections(): Promise<Record<string, string> | undefined> {
return client.call('PersonEndpoint', 'getConnections');
}Data Class Properties
Properties of data classes are nullable. Unlike the function parameters, all nullable properties can be omitted.
Source code
Original properties in Java data class
public class MyBean {
private long id;
@NonNull
private String value;
private String description;
private Map<String, String> map;
@NonNull
private List<String> list;
}Source code
Generated properties in TypeScript data interface
export default interface MyBean {
id: number;
value: string;
description?: string;
map?: Record<string, string | undefined>;
list: Array<string | undefined>;
}Collection Item Types
The collection item type is nullable.
Source code
Original properties in Java data class
public class MyBean {
private List<String> list;
private List<@NonNull String> nonNullableList;
private Map<String, String> map;
private Map<String, @NonNull String> nonNullableMap;
}Source code
Generated properties in TypeScript data interface
export default interface MyBean {
list?: Array<string | undefined>;
nonNullableList?: Array<string>;
map?: Record<string, string | undefined>;
nonNullableMap?: Record<string, string>;
}@NonNullApi
Along with @NonNull annotations, you could also use package-level @NonNullApi annotations. It would make all the nullable types in a package non-nullable by default. All nested types — List and Map items, etc. — are also affected.
By default, the following annotation is supported: org.springframework.lang.NonNullApi.
To make any type nullable, you must add a @Nullable annotation to it. Vaadin recommends using @org.jspecify.annotations.Nullable. The full list of supported annotations is as follows:
-
org.jspecify.annotations.Nullable(Recommended) -
jakarta.annotation.Nullable -
org.springframework.lang.Nullable -
com.vaadin.hilla.Nullable(Deprecated)
Source code
package-info.java
package-info.java@NonNullApi
package com.example.application;Source code
MyBean.java
MyBean.javapublic class MyBean {
public List<String> list;
public Map<String, Integer> map;
@Nullable
public String nullable;
}Source code
MyBean.ts
MyBean.tsexport default interface MyBean {
list: Array<string>;
map: Record<string, number>;
nullable?: string;
}