September 14, 2023Lawrence Lockhart

Bringing Spring Boot and React together with Hilla

Intro

As a newly-minted Developer Advocate with Vaadin, I’m in the unique position of having fresh eyes to explore our frameworks, components and other services. For the last few days, I’ve been building with Hilla, a full-stack framework for building web applications, as I build a pet project in public. This follow-along blog will detail both my process and insights I’ve gained along the way.

Architecture

Hilla combines a Spring Boot backend with a reactive TypeScript frontend in a single project. It’s well-suited for web applications utilizing Lit or React for the UI, and helps the user build data-rich business applications faster, with its own UI components and integrated tooling. Visit the Hilla docs here Hilla Documentation for a quick start guide, tutorials, and link to Hilla’s extensive component library.

Calling the Backend

Much of the magic of Hilla lies in the way it handles Spring Service classes for use on the front end. These classes, once annotated with @BrowserCallable, serve as the bridge between the Java backend and the TypeScript frontend. When the application starts, Hilla scans the classpath for these annotated classes and generates TypeScript modules for them, allowing you to call backend methods directly and facilitating type-safe communication from React to the backend service.

My project

For my project, I’m building an app called Tech Connect. It’s a web application designed to connect people seeking mentorship in a tech discipline with a person who has agreed to be a mentor to one or more who sign up. As a Community Manager of a tech meetup group for the last 3 years, our means of pairing people together has been through Slack messages and Google Sheets. All data is visible to all users which isn’t an ideal scenario. Since we are a globally-distributed org, I thought it would be valuable to have a web app that ultimately supports unique logins, and auto-pairing, and unique views per user.

Starting the project

To initialize a Hilla project, I executed the following from a command-line interface: npx @hilla/cli init tech-connect where tech-connect was the title of my project (only requires Node 18.0+ and JDK 17+). Executing the maven wrapper command ./mvnw builds the project. With that one command, your front and back end will be built. Going to http://localhost:8080 in your web browser displays the default page.

If you've previously worked with Spring Boot, you'll find Hilla project structure to be a familiar territory. But what sets Hilla apart is how seamlessly it marries this backend framework with your frontend. For instance, since my project involves pairing mentors and mentees based on technology stack, I created a Participant model and DTO. In Hilla, not only do we define this model, but it automatically generates TypeScript interfaces that we can use directly in the frontend. This ensures type safety and saves an enormous amount of time that you'd otherwise spend syncing your frontend and backend models.

@Entity
@JsonIgnoreProperties({"mentor"})
public class Participant {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
   private String name;
   private String email;
   @Enumerated(EnumType.STRING)
   private Technology technology;
   @JsonManagedReference
   @OneToMany(mappedBy = "mentor", cascade = CascadeType.ALL) // One mentor can have many mentees
    private List<Participant> mentees;
       public Participant() {
       }
       public Participant(String email, Technology technology) {
           this.email = email;
           this.technology = technology;
       }
       public Participant(String doe, String python) {
       }
       // Getters and Setters
       public Long getId() {
           return id;
       }
    }
import type Participant_1 from "./Participant.js";
import type Technology_1 from "./Participant/Technology.js";
interface Participant {
   email?: string;
   id?: number;
   mentees?: Array<Participant_1 | undefined>;
   name?: string;
   technology?: Technology_1;
}
export default Participant;

Building the Frontend

The frontend development phase was straightforward thanks to Hilla's tight integration with React. Usually, hooking up a React frontend with a Spring Boot backend involves configuring REST APIs or GraphQL queries. But remember the @BrowserCallable service classes I mentioned earlier? They come into play here. Instead of the usual tangle of fetch-calls, Hilla makes the process incredibly smooth to call backend methods directly from your React components. Given the simplicity of importing the automatically generated TypeScript client, Hilla opens up room to focus on UI/UX rather than on backend connection logistics.

@BrowserCallable
@Service
@AnonymousAllowed
public class ParticipantEndpoint {
   private ParticipantRepository participantRepository;
   @Autowired
   private ParticipantService participantService;
   public ParticipantEndpoint(ParticipantRepository participantRepository, ParticipantService participantService) {
       this.participantRepository = participantRepository;
   }
   public List<ParticipantDTO> findAll() {
       return participantService.findAll();
    }
   }

Wrapping up

After implementing an H2 in-memory database and SQL file to generate mock data I now have a working web application persisting data in-memory and displaying it on the front end. The repo can be found here: Tech Connect Repo. The next steps are to build out service classes to facilitate a working mentor-mentee pairing application and integrate some of the super-useful Hilla web components to enhance the user experience.

What have I learned so far? First, I realized the immense value in automating boilerplate code. Secondly, I learned the power of type-safe programming that spans both the frontend and backend. I feel like I’ve only scratched the surface and I can't wait to dive deeper into this framework.

Follow us here at @hillaframework on Twitter for updates, and be sure to tag us when you share cool stuff you've built with Hilla!

Landing page display of mentors and mentees
Landing page display of mentors and mentees

Lawrence Lockhart

Lawrence Lockhart

Lawrence is a Developer Advocate with Vaadin. He works with the Hilla and Flow products and enjoys tech conversations that lead to developer wins.

© 2024 Vaadin. All rights reserved