Flow: The most productive way is 100% Java
Hilla: Full-stack React framework for Java
My Leads
Spring Boot
UI
@Route("contacts")
public class ContactsView extends VerticalLayout {
public ContactsView(ContactService contactService) {
var grid = new Grid<>(Contact.class);
grid.setItems(contactService.getContacts());
grid.addComponentColumn(contact ->
new Image(contact.getPictureUrl(), contact.getName())).setAutoWidth(true);
grid.addColumn(Contact::getName).setHeader("Name").setAutoWidth(true);
grid.addColumn(Contact::getCompany).setHeader("Company").setAutoWidth(true);
grid.addComponentColumn(contact ->
new DatePicker(contact.getLastContacted(), e ->
Notification.show(contact.getName() + " updated: " + e.getValue())
)).setHeader("Last Contacted").setAutoWidth(true);
}
}
Services
@Service
public class ContactService {
private final ContactRepository contactRepository;
public ContactService(ContactRepository contactRepository) {
this.contactRepository = contactRepository;
}
public List<Contact> getContacts() {
return contactRepository.findAll();
}
}
Data
@Entity
public final class Contact {
@Id
@GeneratedValue
private Long id;
private String name;
private String company;
private LocalDate lastContacted;
private String pictureUrl;
// Constructor, getters and setters
}
UI
export default function ContactsView() {
const contacts = useSignal<Contact[]>([]);
useEffect(() => {
ContactService.getContacts().then(newContacts =>
contacts.value = newContacts
);
}, []);
return (
<Grid items={contacts.value}>
<GridColumn autoWidth>
{({item}) => (
<img src={item.pictureUrl} alt={item.name}/>
)}
</GridColumn>
<GridColumn path="name" autoWidth/>
<GridColumn path="company" autoWidth/>
<GridColumn path="lastContacted" autoWidth>
{({item}) => (
<DatePicker value={item.lastContacted} onChange={e =>
Notification.show(`${item.name} updated: ${e.target.value}`)}/>
)}
</GridColumn>
</Grid>
);
}
Spring Boot
Services
@BrowserCallable
@Service
public class ContactService {
private final ContactRepository contactRepository;
public ContactService(ContactRepository contactRepository) {
this.contactRepository = contactRepository;
}
public List<Contact> getContacts() {
return contactRepository.findAll();
}
}
Data
@Entity
public final class Contact {
@Id
@GeneratedValue
private Long id;
private String name;
private String company;
private String jobTitle;
private LocalDate lastContacted;
private String pictureUrl;
// Constructor, getters and setters
PRODUCTIVITY
CONTROL
Flow
Components
Flow
Spring Boot
Hilla
Components
React
Hilla
Spring Boot
Next.js
Components
React
Next.js
Node.js
Decoupled
Components
React or Angular
REST or GraphQL
Backend of choice
Open Source
The core of the product is licensed under permissive Apache 2.0
license. Commercial features are available where we can add value beyond the fully functional
core.
First party support
Vaadin is built by a company named Vaadin. Since 2000. Our team has supported thousands of
organizations building their applications.
15-year maintenance
Business applications should have a long lifespan. Up to 15 years of support is available for each
version. Migrations are supported by automated tooling.