Principles

Jmix is designed for creating web applications with extensive data models and complex UI primarily tailored for internal users of an organization.

Examples of such applications include a simple CRUD, an admin UI for a website, a business automation tool, a CRM or an ERP-class system. These applications typically involve managing dozens or hundreds of interconnected entities in hundreds or thousands of screens, while using mostly standard UI components like fields, forms and tables.

To effectively create applications of such kind, developers need a tool that enables them to operate on a higher level of abstraction than provided by mainstream technologies like Spring or Jakarta EE. The tool should hide the unnecessary details and save from writing repetitive code, since such applications are inherently repetitive in nature: all the same entities, attributes, UI fields, screens, etc. But the abstraction level must not be too high, to allow developers to express business logic in a familiar programming language and use modern powerful development tools from IDE and VCS to testing frameworks and CI/CD.

We believe that Jmix provides an adequate abstraction for aforementioned class of applications and eliminates unnecessary complications. Below, we describe the principles that Jmix is based on.

Full-Stack Development

The Jmix approach to full-stack development has two main aspects:

  1. Using the single programming language and development paradigm. A backend developer can create a business feature on the full stack from the database schema to UI, while writing plain synchronous Java (or Kotlin) code. No need to have expertise in frontend technologies like asynchronous JavaScript and ever-changing ecosystem.

  2. You don’t have to build an API. A Jmix web application can perfectly function without exposing any API endpoints that introduce complexity and security risks.

These aspects should actually be attributed to the Vaadin framework which is used by Jmix under the hood. Vaadin provides a rich set of UI components each of which has a client part and a server part. The client part is written in JavaScript and runs in the browser, the server part is written in Java and runs on the server. Users interact with the client part of the components, while the server part directly works with the application Java code:

principles full stack 1

If you are new to this concept, we recommend reading the article in our blog post: Simplicity & Focus Through Server-Driven Web UI Development. Here we’ll just briefly repeat the conclusions.

A single programming language and development paradigm allow backend developers to create whole business features instead of just backend parts and APIs. This approach can dramatically improve the productivity of a team and enable building a product without the need for expensive frontend development investments.

The fact that the API is not needed for functioning of UI saves a lot of time for designing, developing, documenting and maintaining the API endpoints. It is also inherently more secure, because the application sends to the browser only data that are really displayed on the user’s screen. There is no risk of extra data being inadvertently exposed to JavaScript in the browser, and there is much less surface area for security vulnerabilities.

On the other hand, the abstraction over the frontend makes it more difficult to customize UI or create own UI components. It’s of course possible, but generally harder than when using frontend frameworks directly. Also, with the Vaadin’s server-side state model, each user session requires a certain amount of memory on the server, which limits the vertical scalability.

And obviously, Jmix may not be the best solution if the organization already has separate teams of backend and frontend developers, along with established development practices around these teams.

So, the Jmix and Vaadin approach to full-stack development will provide more value if the developers are mostly satisfied with the functionality of existing UI components and need deep customizations only in certain parts of the application UI. Another condition is that the number of concurrent users is predictable and not too high (say, less than 100K). Both conditions are usually true for B2B applications that Jmix is targeted for.

And the last note on the monolithic vs. microservices architecture. Full-stack development approach, when the UI is coupled with business logic, contradicts the microservices architecture. But this doesn’t mean that full-stack development works only for monoliths. You can take the best of both worlds if you split a large application into a number of cooperating monoliths, each with its own database and UI:

principles full stack 2

Jmix is well suited for building modular monoliths of any size. The concept of add-ons and support for composite projects in Studio allows for flexibility in dividing the codebase. The OpenID Connect and Generic REST add-ons, as well as the fact that Jmix is fully compatible with any asynchronous communication solution, help to integrate self-contained application services into a complete information system.

Unified Data Model

Jmix allows you to represent data from different sources in a single unified model and use it directly in the UI and business logic. You don’t have to create layers of data transfer objects (DTOs) and mappers to and from the persistence model.

Below, we will compare the traditional architecture of Java enterprise applications with the Jmix approach and define the boundaries in which Jmix can bring the most value.

The common approach in the modern enterprise applications development is to have separate data models for persistence and for presentation and business logic. In other words, you usually have a layer of JPA entities mapped to your database tables and a separate layer of Data Transfer Objects (DTOs) to pass them to/from the frontend through REST controllers (or using GraphQL or other API technologies). In the traditional JavaScript SPA frontend, you also have the same DTOs represented in JSON.

principles model 1

This architecture gives you great flexibility: you can change persistence and presentation models independently, you can convert data to the most convenient structure for storage and UI, and you can exclude certain data from exposure through the API for security reasons.

But what price you have to pay for this flexibility? Obviously, you need to repeat a lot of classes and attributes, and you need to write mappers from one model to another and back. Is it worth it? It depends. If you write an application with few entities and a fancy UI structured very differently from the ER-model of the stored data, separating the persistence and presentation data models would be a natural choice.

In many B2B applications the situation is quite opposite: data should be represented in UI in the same structure as they are stored in the database. Taking into account also the size of the data model in such applications (usually tens or hundreds of entities), the separation of models doesn’t seem like a good idea anymore. It just brings too much boilerplate code for too little value. This code must be written in the first place, and must be maintained while the system evolves: consider what you need to do after adding an attribute to a JPA entity and corresponding table to display this attribute in UI.

As we discussed in the previous section, Jmix applications, thanks to Vaadin, don’t need an API for building the user interface. And you can easily restrict data exposed to users: you just don’t create UI controls for certain entity attributes and these attributes never leave the backend. So the security argument for having separate models also loses its force.

Taking into account all considerations above, the basic approach in Jmix applications is to work with the single data model in all layers: persistence, business logic and UI. For most cases it means using JPA entities and their attributes mapped to database fields. But Jmix doesn’t limit you with just the persistence model.

The difference between persistence and presentation models can be a real thing even for simple CRUD applications. For example, you may need to calculate some value based on the stored data, display this value in UI and work with it in the business logic. Then it makes sense to define a transient attribute in an entity and calculate the value when the entity is loaded.

Another case is when you need to work with data sources different from relational databases. Then you cannot use JPA, and you define the model in Plain Old Java Objects (POJOs) mapped to external APIs or non-relational databases.

And finally, you may have sophisticated parts of UI where you need some POJOs structured differently from the persistence model.

With Jmix, all these requirements (transient attributes, POJOs mapped to external data, UI-only POJOs) can be implemented within the single data model. That is, instead of stacking different models on top of each other, you can expand the main JPA persistence model by adding non-JPA items to it.

principles model 2

In applications that display data mostly in the same structure as they are stored, this approach brings obvious benefits: you don’t duplicate the whole model on different layers and don’t write boilerplate code for maintaining this duplication. Instead, you can extend the underlying persistence model with required elements only when they are needed.

To better understand how Jmix provides a unified data model containing different elements, and what you can do with this model, refer to the Data Model and Metadata section.

Ready-Made Components

Jmix provides ready-made components to solve common tasks in enterprise applications. They range from sophisticated UI controls for working with data to full-stack features like report generation and business process management.

This category also includes high-level abstractions and declarative approach for UI building, data access and security. You can find an overview of these features in the next section.

Jmix focuses on a particular area of enterprise applications, and therefore it’s able to provide a lot of sensible defaults. These practices and settings serve as starting points, lower the entry barrier and speed up the development of applications.

Using Mainstream Technologies

Jmix is built on top of mainstream technologies (Java, Spring, JPA) and tends to not reinvent the wheel. There are no restrictions on bypassing Jmix abstractions and working directly with underlying technologies when needed.

From the tooling and development practices perspective, you can use modern testing frameworks, static code analysis, CI/CD and version control systems.

Extensibility

Jmix is built with extensibility in mind. If something in the framework doesn’t work for you, extend or replace it with your own solution. The same is true for the add-ons and applications created with Jmix - a customized solution can be built on top of the existing ones.

The Modularity and Extension section describes the Jmix extensibility features in detail.