> Markdown version of [Call Java Services](https://vaadin.com/docs/latest/building-apps/react/call-services). Section index: [llms.txt](https://vaadin.com/docs/latest/building-apps/llms.txt)

# Call Java Services from React Views

A React view runs in the browser, so it gets its data from the server by calling Java services. Vaadin lets you do this in a type-safe way — without writing a REST controller — by making a service *browser-callable* and generating a TypeScript client for it. This guide covers the basics; for the full details, see the [Browser-Callable Services reference guide](https://vaadin.com/docs/latest/hilla/guides/browser-callable-services.md). Browser-callable services need the Hilla Spring Boot starter in the project, as described in [Enabling React Views in a Project](https://vaadin.com/docs/latest/building-apps/react.md#enabling).

## <a id="making-a-service-browser-callable"></a>Making a Service Browser-Callable

Annotate a Java service with `@BrowserCallable`. Vaadin then exposes a server endpoint for it and generates a matching TypeScript client, so you can call it from the browser without configuring URLs by hand:

```java
@BrowserCallable
@AnonymousAllowed // (1)
public class CounterService {
    public int addOne(int number) {
        return number + 1;
    }
}
```

1. Browser-callable services are inaccessible by default. You must add a security annotation to grant access. See [Secure React Views](https://vaadin.com/docs/latest/building-apps/react/security.md).

The TypeScript client is regenerated automatically when the application starts in development mode, when a service is hot-swapped, and during a production build. The generator reads compiled Java byte code, so the classes must be compiled first.

## <a id="calling-a-service"></a>Calling a Service

Import the generated client from `Frontend/generated/endpoints` and call its methods. Client functions are always `async`, so use `await` or handle the returned `Promise`:

```tsx
import { Button } from "@vaadin/react-components";
import { useSignal } from "@vaadin/hilla-react-signals";
import { CounterService } from "Frontend/generated/endpoints";

export default function CounterView() {
    const number = useSignal(0);
    const addOne = async () => {
        number.value = await CounterService.addOne(number.value);
    };
    return (
        <main>
            <div>{number}</div>
            <Button onClick={addOne}>Add One</Button>
        </main>
    );
}
```

## <a id="passing-objects"></a>Passing Objects

Services can receive and return objects, not only primitives. Vaadin generates a TypeScript interface for each Java type used. You can use classes or records:

> **Tip: Prefer Records**
>
> If you’re unsure whether to use a class or a record, use a record. Records are concise and immutable, reducing boilerplate.

City.java

```java
public record City(String name, String country) {}
```

generates:

city.ts

```typescript
interface City {
    name?: string;
    country?: string;
}
export default City;
```

Vaadin uses Jackson for serialization, so Jackson annotations can customize the generated types. See the [Type Conversion reference guide](https://vaadin.com/docs/latest/hilla/reference/type-conversion.md) for details.

## <a id="nullability"></a>Nullability

By default, Java primitive types (`int`, `boolean`, and similar) become non-nullable in TypeScript, while reference types (`String`, `LocalDate`, and similar) become nullable — which is why `name` and `country` above are generated as optional (`?`).

To make a reference type non-nullable, annotate it with the **JSpecify** `@NonNull` annotation:

```java
import org.jspecify.annotations.NonNull;

public record City(@NonNull String name, @NonNull String country) {}
```

The same applies to method parameters and return values, including the elements of collections:

```java
public @NonNull List<@NonNull City> findCities(@NonNull Query query) {
    // ...
}
```

> **Tip: Change the Default**
>
> If most types in your project should be non-nullable, apply Spring’s `@NonNullApi` at the package level in `package-info.java`. For more control over nullability, see the [Type Nullability reference guide](https://vaadin.com/docs/latest/hilla/reference/type-nullability.md).

## <a id="pushing-updates-with-reactive-services"></a>Pushing Updates with Reactive Services

The service methods shown so far return a single value in response to a call. A service can instead push a **stream** of values to the browser over time by returning a [Reactor](https://projectreactor.io/) `Flux`. This is useful for live data, such as a clock, a progress indicator, or notifications. A browser-callable service can only return a `Flux` — convert a `Mono` to one with `flux()`.

The following service emits the current date and time every second:

```java
@BrowserCallable
public class TimeService {

    @AnonymousAllowed
    public Flux<@NonNull String> getClock() {
        return Flux.interval(Duration.ofSeconds(1)) // (1)
                .onBackpressureDrop() // (2)
                .map(_interval -> Instant.now().toString()); // (3)
    }
}
```

1. Emit a new value every second.

2. Drop values that can’t be sent to the client in time.

3. Output the current date and time as a string.

For how to produce reactive streams on the server, including from background jobs, see [Producing Reactive Streams](https://vaadin.com/docs/latest/building-apps/business-logic/background-jobs/interaction/reactive.md).

### <a id="subscribing-from-a-view"></a>Subscribing from a View

Vaadin generates the TypeScript types for the service. Call the generated method to get a `Subscription`, then register a callback with `onNext()`:

```typescript
const subscription = TimeService.getClock().onNext(time => {
    // Update the UI state
});
```

A **cold** stream — one that starts when subscribed and completes on its own, such as a single background-job result — doesn’t need to be cancelled. A **hot** stream — one that emits continuously, such as a chat feed — must be cancelled when the component is removed from the DOM. Subscribe inside a React effect and cancel in its cleanup function:

```typescript
useEffect(() => {
    const subscription = ChatService.messages().onNext(onMessageReceived);
    return () => subscription.cancel();
}, []);
```

### <a id="handling-errors"></a>Handling Errors

An error terminates the stream: the subscription is cancelled and no more values arrive. Register an error callback with `onError()`. For a hot stream, consider resubscribing as part of recovery:

```typescript
ChatService.messages().onNext(onMessageReceived).onError(onError);
```

The error callback receives no information about the error itself.

### <a id="buffering-high-frequency-streams"></a>Buffering High-Frequency Streams

Don’t push updates to the browser more than two to four times per second. If a stream emits faster than that, buffer it **in the service** with `Flux.buffer()` so the client receives batches instead. The generated method then emits arrays:

```java
@AnonymousAllowed
public Flux<@NonNull List<@NonNull Event>> bufferedEventStream() {
    return eventStream().buffer(Duration.ofMillis(250)); // (1)
}
```

1. Buffer events for 250 ms, then emit them as a `List<Event>`.

### <a id="recovering-lost-subscriptions"></a>Recovering Lost Subscriptions

A subscription can be lost without being cancelled — for example when the user’s device sleeps or briefly loses its network connection. Vaadin re-establishes the connection automatically, but the subscription may no longer be valid. Register an `onSubscriptionLost()` callback to decide what happens:

```typescript
useEffect(() => {
    const subscription = ChatService.messages()
        .onNext(onMessageReceived)
        .onSubscriptionLost(() => ActionOnLostSubscription.RESUBSCRIBE);
    return () => subscription.cancel();
}, []);
```

The callback returns `RESUBSCRIBE` to call the server method again, or `REMOVE` (the default) to leave the subscription closed until the client resubscribes explicitly.

## <a id="next-steps"></a>Next Steps

- [Secure React Views](https://vaadin.com/docs/latest/building-apps/react/security.md) — control who can call your services and access your views.
